Fix repository management script for parallel execution

- Remove redundant run_cmd function, use run_aptly consistently
- Include EOS releases in repository processing (remove -ve 'eos' filter)
- Fix showall command to auto-discover repos from isolated databases
- Fix source file preservation in parallel mode (keep sources for workers)
- Fix snapshot management to handle published snapshots correctly
- Fix drop_unsupported_releases to only drop unsupported, not all repos
- Remove isolated DB cleanup that caused data loss on each run
- Remove inappropriate sudo usage from html and date commands
- Enable FORCE_PUBLISH by default for better workflow
- Improve common snapshot creation in isolated mode
- Add isolated database support to showall function

Signed-off-by: Igor Pecovnik <igor@armbian.com>
This commit is contained in:
Igor Pecovnik
2026-01-04 12:13:34 +01:00
committed by Igor
parent 4648add145
commit 6d2d2e97a8

View File

@@ -5,7 +5,7 @@ DRY_RUN=false # Full dry-run: don't make any repository changes
KEEP_SOURCES=false # Keep source packages when adding to repo (don't delete)
SINGLE_RELEASE="" # Process only a single release (for GitHub Actions parallel workflow)
FORCE_ADD=false # Force re-adding packages even if they already exist in repo
FORCE_PUBLISH=false # Force publishing even when no packages to add
FORCE_PUBLISH=true # Force publishing even when no packages to add
# Logging function - uses syslog, view logs with: journalctl -t repo-management -f
# Arguments:
@@ -14,24 +14,6 @@ log() {
logger -t repo-management "$*"
}
# Execute a command, respecting dry-run mode
# In dry-run mode, logs what would be executed without actually running it
# Arguments:
# $* - Command to execute
# Returns:
# Command exit status (0 in dry-run mode)
run_cmd() {
local cmd="$*"
if [[ "$DRY_RUN" == true ]]; then
log "[DRY-RUN] Would execute: $cmd"
return 0
else
log "Executing: $cmd"
eval "$cmd"
return $?
fi
}
# Execute aptly command and check for errors
# Exits with status 1 if the command fails (unless in dry-run mode)
# Arguments:
@@ -65,7 +47,7 @@ drop_unsupported_releases() {
supported_releases=()
else
log "Cleanup: dropping unsupported releases"
supported_releases=($(grep -rw config/distributions/*/support -ve 'eos' | cut -d"/" -f3))
supported_releases=($(grep -rw config/distributions/*/support | cut -d"/" -f3))
fi
# Get currently published repositories
@@ -82,25 +64,74 @@ drop_unsupported_releases() {
# Drop the identified repositories
for repo in "${repos_to_drop[@]}"; do
run_cmd aptly publish drop -config="${CONFIG}" "${repo}"
run_aptly publish drop -config="${CONFIG}" "${repo}"
done
}
# Display contents of all repositories
# Shows packages in the common repository and release-specific repositories (utils, desktop)
# Uses global DISTROS array for iteration
# In single-release mode, shows content from isolated database
# Otherwise, shows content from main database and any existing isolated databases
# Uses global DISTROS array for iteration, or discovers repos automatically if DISTROS is empty
showall() {
echo "Displaying common repository contents"
aptly repo show -with-packages -config="${CONFIG}" common 2>/dev/null | tail -n +7
for release in "${DISTROS[@]}"; do
# Only show if the repo exists
if aptly repo show -config="${CONFIG}" "${release}-utils" &>/dev/null; then
echo "Displaying repository contents for $release-utils"
aptly repo show -with-packages -config="${CONFIG}" "${release}-utils" | tail -n +7
# If DISTROS array is empty, discover repos from the database
local releases_to_show=("${DISTROS[@]}")
if [[ ${#DISTROS[@]} -eq 0 ]]; then
# First, discover releases from isolated databases
local all_repos=()
if [[ -d "$output" ]]; then
for isolated_dir in "$output"/aptly-isolated-*; do
if [[ -d "$isolated_dir" ]]; then
local release_name=$(basename "$isolated_dir" | sed 's/aptly-isolated-//')
all_repos+=("$release_name")
fi
done
fi
if aptly repo show -config="${CONFIG}" "${release}-desktop" &>/dev/null; then
# Also get repos from main database (for non-isolated repos)
local main_repos
main_repos=($(aptly repo list -config="${CONFIG}" -raw 2>/dev/null | awk '{print $NF}' | grep -E '^.+-(utils|desktop)$' | sed 's/-(utils|desktop)$//' | sort -u))
# Merge and deduplicate
all_repos+=("${main_repos[@]}")
releases_to_show=($(echo "${all_repos[@]}" | tr ' ' '\n' | sort -u))
fi
for release in "${releases_to_show[@]}"; do
# In single-release mode, only show that specific release from the isolated database
if [[ -n "$SINGLE_RELEASE" ]]; then
if [[ "$release" != "$SINGLE_RELEASE" ]]; then
continue
fi
fi
# Check if there's an isolated database for this release
local isolated_db="${output}/aptly-isolated-${release}"
local show_config="$CONFIG"
if [[ -d "$isolated_db" ]]; then
# Create temporary config for the isolated database
local temp_config
temp_config="$(mktemp)"
sed 's|"rootDir": ".*"|"rootDir": "'$isolated_db'"|g' tools/repository/aptly.conf > "$temp_config"
show_config="$temp_config"
fi
# Show utils repo if it exists
if aptly repo show -config="${show_config}" "${release}-utils" &>/dev/null; then
echo "Displaying repository contents for $release-utils"
aptly repo show -with-packages -config="${show_config}" "${release}-utils" | tail -n +7
fi
# Show desktop repo if it exists
if aptly repo show -config="${show_config}" "${release}-desktop" &>/dev/null; then
echo "Displaying repository contents for $release-desktop"
aptly repo show -with-packages -config="${CONFIG}" "${release}-desktop" | tail -n +7
aptly repo show -with-packages -config="${show_config}" "${release}-desktop" | tail -n +7
fi
# Clean up temp config if we created one
if [[ -n "$temp_config" && -f "$temp_config" ]]; then
rm -f "$temp_config"
fi
done
}
@@ -205,8 +236,9 @@ adding_packages() {
# Determine whether to remove source files after adding to repo
# KEEP_SOURCES mode preserves source packages
# DRY_RUN mode also preserves sources (and skips all repo modifications)
# SINGLE_RELEASE mode preserves sources so parallel workers don't delete files needed by other workers
local remove_flag="-remove-files"
if [[ "$KEEP_SOURCES" == true ]] || [[ "$DRY_RUN" == true ]]; then
if [[ "$KEEP_SOURCES" == true ]] || [[ "$DRY_RUN" == true ]] || [[ -n "$SINGLE_RELEASE" ]]; then
remove_flag=""
fi
@@ -239,13 +271,24 @@ update_main() {
# Add packages from main folder
adding_packages "common" "" "main" "$input_folder"
# Drop old snapshot
# Drop old snapshot if it exists and is not published
if [[ -n $(aptly snapshot list -config="${CONFIG}" -raw | awk '{print $(NF)}' | grep "common") ]]; then
run_aptly -config="${CONFIG}" snapshot drop common | logger -t repo-management >/dev/null
# Check if snapshot is published
if ! aptly publish list -config="${CONFIG}" 2>/dev/null | grep -q "common"; then
run_aptly -config="${CONFIG}" snapshot drop common | logger -t repo-management >/dev/null
else
log "WARNING: common snapshot is published, cannot drop. Packages added to repo but snapshot not updated."
log "Run 'update' command to update all releases with new packages."
return 0
fi
fi
# Create new snapshot
run_aptly -config="${CONFIG}" snapshot create common from repo common | logger -t repo-management >/dev/null
# Create new snapshot if it doesn't exist or was dropped
if [[ -z $(aptly snapshot list -config="${CONFIG}" -raw | awk '{print $(NF)}' | grep "common") ]]; then
run_aptly -config="${CONFIG}" snapshot create common from repo common | logger -t repo-management >/dev/null
else
log "common snapshot already exists, skipping creation"
fi
log "Common component built successfully"
}
@@ -267,18 +310,26 @@ process_release() {
log "Processing release: $release"
# In isolated mode (SINGLE_RELEASE), ensure common snapshot exists
# It should have been created by 'update-main' command, but if not, create empty common
if [[ -n "$SINGLE_RELEASE" && -z $(aptly snapshot list -config="${CONFIG}" -raw | awk '{print $(NF)}' | grep "common") ]]; then
log "WARNING: Common snapshot not found. Creating empty common snapshot."
log "Please run 'update-main' command first to populate common packages."
# Create empty common repo
# It should have been created by 'update-main' command, but if not, create it from input packages
if [[ -n "$SINGLE_RELEASE" ]]; then
# Create common repo if it doesn't exist
if [[ -z $(aptly repo list -config="${CONFIG}" -raw | awk '{print $(NF)}' | grep common) ]]; then
aptly repo create -config="${CONFIG}" -distribution="common" -component="main" -comment="Armbian common packages" "common" | logger -t repo-management >/dev/null
run_aptly repo create -config="${CONFIG}" -distribution="common" -component="main" -comment="Armbian common packages" "common" | logger -t repo-management >/dev/null
fi
# Create snapshot (will be empty until update-main is run)
aptly -config="${CONFIG}" snapshot create common from repo common | logger -t repo-management >/dev/null
# Add packages from main input folder to common repo
# This ensures each isolated worker has the common packages
log "Populating common repo from input folder: $input_folder"
adding_packages "common" "" "main" "$input_folder"
# Drop old common snapshot if it exists (in isolated DB, snapshots aren't published yet)
if [[ -n $(aptly snapshot list -config="${CONFIG}" -raw | awk '{print $(NF)}' | grep "common") ]]; then
run_aptly -config="${CONFIG}" snapshot drop common | logger -t repo-management >/dev/null
fi
# Create snapshot with packages
run_aptly -config="${CONFIG}" snapshot create common from repo common | logger -t repo-management >/dev/null
log "Created common snapshot with packages for isolated mode"
fi
# Create release-specific repositories if they don't exist
@@ -305,13 +356,11 @@ process_release() {
log "Package counts for $release: utils=$utils_count, desktop=$desktop_count"
# If no packages in either repo and not previously published, skip publishing
# Unless FORCE_PUBLISH is enabled
# Always publish - even if no release-specific packages, we still need to publish common/main
# Check if this release was previously published for logging
if [[ "$utils_count" -eq 0 && "$desktop_count" -eq 0 && "$FORCE_PUBLISH" != true ]]; then
# Check if this release was previously published
if ! aptly publish list -config="${CONFIG}" 2>/dev/null | grep -q "^\[${release}\]"; then
log "No packages to publish for $release and not previously published. Skipping."
return 0
log "No release-specific packages for $release. Publishing common/main component only."
else
log "No new packages but $release was previously published. Will publish with common only."
fi
@@ -321,12 +370,19 @@ process_release() {
log "Force publish enabled: will publish even with no packages"
fi
# Drop old snapshots if they exist
if [[ -n $(aptly snapshot list -config="${CONFIG}" -raw | awk '{print $(NF)}' | grep "${release}-utils") ]]; then
run_aptly -config="${CONFIG}" snapshot drop ${release}-utils | logger -t repo-management 2>/dev/null
# Drop old snapshots if we have new packages to add OR if FORCE_PUBLISH is enabled
# This ensures fresh snapshots are created for force-publish scenarios
if [[ "$utils_count" -gt 0 || "$FORCE_PUBLISH" == true ]]; then
if [[ -n $(aptly snapshot list -config="${CONFIG}" -raw | awk '{print $(NF)}' | grep "${release}-utils") ]]; then
log "Dropping existing ${release}-utils snapshot"
run_aptly -config="${CONFIG}" snapshot drop ${release}-utils | logger -t repo-management 2>/dev/null
fi
fi
if [[ -n $(aptly snapshot list -config="${CONFIG}" -raw | awk '{print $(NF)}' | grep "${release}-desktop") ]]; then
run_aptly -config="${CONFIG}" snapshot drop ${release}-desktop | logger -t repo-management 2>/dev/null
if [[ "$desktop_count" -gt 0 || "$FORCE_PUBLISH" == true ]]; then
if [[ -n $(aptly snapshot list -config="${CONFIG}" -raw | awk '{print $(NF)}' | grep "${release}-desktop") ]]; then
log "Dropping existing ${release}-desktop snapshot"
run_aptly -config="${CONFIG}" snapshot drop ${release}-desktop | logger -t repo-management 2>/dev/null
fi
fi
# Create snapshots only for repos that have packages
@@ -426,11 +482,14 @@ process_release() {
-label="Armbian" \
-config="${CONFIG}" \
-component="$component_list" \
-distribution="${release}" snapshot $snapshot_list > /dev/null
-distribution="${release}" snapshot $snapshot_list
# If using isolated DB, copy published files to shared output location FIRST
log "Isolated mode check: SINGLE_RELEASE='$SINGLE_RELEASE' publish_dir='$publish_dir' output_folder='$output_folder'"
if [[ -n "$SINGLE_RELEASE" && "$publish_dir" != "$output_folder" ]]; then
log "Copying published files from isolated DB to shared output"
log "Source: ${publish_dir}/public"
log "Destination: ${output_folder}/public"
if [[ -d "${publish_dir}/public" ]]; then
mkdir -p "${output_folder}/public"
# Use rsync to copy published repo files to shared location
@@ -684,7 +743,7 @@ merge_repos() {
log "Copied GPG key to repository"
# Write repository sync control file
sudo date +%s > ${output_folder}/public/control
date +%s > ${output_folder}/public/control
log "Updated repository control file"
# Display repository contents
@@ -755,7 +814,7 @@ repo-manipulate() {
echo "<thead><tr><td colspan=3><h2>$release</h2></tr><tr><th>Main</th><th>Utils</th><th>Desktop</th></tr></thead>"
echo "<tbody><tr><td width=33% valign=top>"
aptly repo show -with-packages -config="${CONFIG}" "${release}-utils" | tail -n +7 | sed 's/.*/&<br>/'
echo "</td><td width=33% valign=top>" | sudo tee -a ${filename}
echo "</td><td width=33% valign=top>"
aptly repo show -with-packages -config="${CONFIG}" "${release}-desktop" | tail -n +7 | sed 's/.*/&<br>/'
echo "</td></tr></tbody>"
done
@@ -822,8 +881,8 @@ repo-manipulate() {
;;
update)
# remove old releases from publishing
drop_unsupported_releases "all"
# remove old releases from publishing (only drops unsupported releases, not all)
drop_unsupported_releases ""
publishing "$1" "$2" "$3" "$4" "$5"
# Only use signing function for non-single-release mode
# In single-release mode, workers already signed their components
@@ -851,7 +910,7 @@ input="output/debs-beta"
output="output/repository"
command="show"
if [[ -d "config/distributions" ]]; then
releases=$(grep -rw config/distributions/*/support -ve 'eos' 2>/dev/null | cut -d"/" -f3 | xargs | sed -e 's/ /,/g')
releases=$(grep -rw config/distributions/*/support 2>/dev/null | cut -d"/" -f3 | xargs | sed -e 's/ /,/g')
if [[ -z "$releases" ]]; then
log "WARNING: No releases found in config/distributions"
fi
@@ -1000,13 +1059,7 @@ if [[ -n "$SINGLE_RELEASE" ]]; then
# Create isolated aptly directory for this release
IsolatedRootDir="${output}/aptly-isolated-${SINGLE_RELEASE}"
# Clean up isolated DB from previous runs to ensure fresh state
# This prevents database/pool desync and "no such file" errors
if [[ -d "$IsolatedRootDir" ]]; then
log "Cleaning up isolated DB from previous run: $IsolatedRootDir"
rm -rf "${IsolatedRootDir}"
fi
# Create the isolated directory if it doesn't exist
if ! mkdir -p "$IsolatedRootDir"; then
log "ERROR: mkdir $IsolatedRootDir: permission denied"
exit 1