diff --git a/.gitea/workflows/build-iso.yaml b/.gitea/workflows/build-iso.yaml index 6c7786d..6d583ed 100644 --- a/.gitea/workflows/build-iso.yaml +++ b/.gitea/workflows/build-iso.yaml @@ -29,7 +29,7 @@ jobs: - name: Install archiso and dependencies run: | set -euo pipefail - pacman -Syu --noconfirm --needed archiso jq git-lfs zstd + pacman -Syu --noconfirm --needed archiso jq zstd - name: Ensure /dev/stdin exists for mkinitcpio run: | @@ -81,14 +81,12 @@ jobs: echo "tag_name=${TAG_NAME}" >> "$GITHUB_OUTPUT" echo "release_name=Arch Linux ISO (${BASE_DATE} Rev ${REVISION})" >> "$GITHUB_OUTPUT" - - name: Create Release and Upload ISO via Git LFS + - name: Create Release and Upload ISO env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} # Use internal Gitea URL to bypass traefik proxy timeout on large uploads GITEA_API: http://192.168.1.168:3000/api/v1 - GITEA_PUBLIC_URL: https://git.vilaythong.us REPOSITORY: ${{ github.repository }} - RELEASES_REPO: alvinlollo/AlvinArch-releases TAG_NAME: ${{ steps.tag.outputs.tag_name }} RELEASE_NAME: ${{ steps.tag.outputs.release_name }} run: | @@ -104,15 +102,6 @@ jobs: exit 1 fi - RELEASES_OWNER="${RELEASES_REPO%%/*}" - RELEASES_NAME="${RELEASES_REPO#*/}" - GITEA_BASE="${GITEA_API%/api/v1}" - GITEA_SCHEME="${GITEA_BASE%%://*}" - GITEA_HOST="${GITEA_BASE#*://}" - CLONE_URL="${GITEA_SCHEME}://${RELEASES_OWNER}:${GITEA_TOKEN}@${GITEA_HOST}/${RELEASES_REPO}.git" - REPO_DIR="$PWD/.releases-repo" - trap 'rm -rf "$REPO_DIR"' EXIT - # Collect the ISOs produced by the build isos=(out/*.iso) if (( ${#isos[@]} == 0 )); then @@ -140,93 +129,14 @@ jobs: sha256sums+=("$sha") done - # Make sure the releases repo exists (create it via API if missing) - if ! curl -sf -o /dev/null -H "Authorization: token $GITEA_TOKEN" \ - "$GITEA_API/repos/$RELEASES_REPO"; then - echo "Creating releases repo '$RELEASES_REPO'..." - curl -sf -X POST \ - -H "Authorization: token $GITEA_TOKEN" \ - -H "Content-Type: application/json" \ - "$GITEA_API/user/repos" \ - -d "{\"name\": \"$RELEASES_NAME\", \"description\": \"Compressed Arch Linux live ISOs (Git LFS)\", \"auto_init\": true}" > /dev/null - fi - - # Push the compressed ISOs to the releases repo via Git LFS - if ! GIT_LFS_SKIP_SMUDGE=1 git clone --quiet "$CLONE_URL" "$REPO_DIR" 2>/dev/null; then - echo "❌ Failed to clone $RELEASES_REPO (check token access)." >&2 - exit 1 - fi - - # Work on the 'main' branch (create it if the remote default differs) - if git -C "$REPO_DIR" rev-parse --verify -q origin/main >/dev/null 2>&1; then - git -C "$REPO_DIR" checkout -q -B main origin/main - else - git -C "$REPO_DIR" checkout -q -B main - fi - - git -C "$REPO_DIR" lfs install --local - git -C "$REPO_DIR" lfs track "*.iso.zst" - mkdir -p "$REPO_DIR/releases/$TAG_NAME" - for zst in "${zst_files[@]}"; do - cp "$zst" "$REPO_DIR/releases/$TAG_NAME/" - done - - # Seed a short README redirecting to the main repo (status badges on top) - cat > "$REPO_DIR/README.md" <<'MDEOF' - [![Scheduled ArchISO Build](https://git.vilaythong.us/alvinlollo/AlvinArch/actions/workflows/build-iso.yaml/badge.svg?branch=main)](https://git.vilaythong.us/alvinlollo/AlvinArch/actions?workflow=build-iso.yaml) - [![Tests](https://git.vilaythong.us/alvinlollo/AlvinArch/actions/workflows/tests.yaml/badge.svg?branch=main)](https://git.vilaythong.us/alvinlollo/AlvinArch/actions?workflow=tests.yaml) - - # AlvinArch Releases - - Compressed (zstd) Arch Linux live ISOs built automatically by - [alvinlollo/AlvinArch](https://git.vilaythong.us/alvinlollo/AlvinArch). - - **Main repository:** [alvinlollo/AlvinArch](https://git.vilaythong.us/alvinlollo/AlvinArch) - MDEOF - - git -C "$REPO_DIR" config user.name "Gitea Actions" - git -C "$REPO_DIR" config user.email "actions@gitea.local" - git -C "$REPO_DIR" add .gitattributes README.md "releases/$TAG_NAME" - if git -C "$REPO_DIR" diff --cached --quiet; then - echo "⚠️ No changes to commit for $TAG_NAME — releasing as-is." >&2 - else - git -C "$REPO_DIR" commit --quiet -m "Add $TAG_NAME" - fi - if ! git -C "$REPO_DIR" push --quiet origin main; then - echo "❌ Failed to push $TAG_NAME to $RELEASES_REPO." >&2 - exit 1 - fi - - # Free disk space immediately — the clone + LFS objects are multi-GB - rm -rf "$REPO_DIR" - - # Verify each LFS object exists server-side (oid == the sha256 we recorded) - for i in "${!zst_files[@]}"; do - fname=$(basename "${zst_files[$i]}") - size=$(stat -c %s "${zst_files[$i]}") - oid=${sha256sums[$i]} - lfs_payload=$(jq -nc --arg oid "$oid" --argjson sz "$size" \ - '{operation:"download",transfers:["basic"],objects:[{oid:$oid,size:$sz}]}') - obj=$(curl -sf -u "$RELEASES_OWNER:$GITEA_TOKEN" \ - -H "Content-Type: application/vnd.git-lfs+json" \ - -d "$lfs_payload" \ - "$GITEA_BASE/$RELEASES_REPO.git/info/lfs/objects/batch") - if [[ "$(jq -r '.objects[0] | has("actions")' <<< "$obj")" != "true" ]]; then - echo "❌ Verification failed: LFS object for '$fname' ($size bytes) missing on server." >&2 - exit 1 - fi - echo " ✅ Verified '$fname' ($size bytes) on $RELEASES_REPO" - done - - # Create the release with a link to the file directory + SHA-256 checksums - DOWNLOAD_URL="$GITEA_PUBLIC_URL/$RELEASES_REPO/src/branch/main/releases/$TAG_NAME" - printf -v body 'Arch Linux live ISO %s\n\nDownload: %s\n\nChecksums (SHA-256):\n' \ - "$RELEASE_NAME" "$DOWNLOAD_URL" + # Build the release body with SHA-256 checksums + printf -v body 'Arch Linux live ISO %s\n\nChecksums (SHA-256):\n' "$RELEASE_NAME" for i in "${!zst_files[@]}"; do printf -v line -- '- `%s`: sha256 `%s`\n' "$(basename "${zst_files[$i]}")" "${sha256sums[$i]}" body+="$line" done + # Create the release payload=$(jq -nc --arg tag "$TAG_NAME" --arg name "$RELEASE_NAME" --arg body "$body" \ '{tag_name:$tag,name:$name,body:$body}') RELEASE_ID=$(curl -sf -X POST \ @@ -234,22 +144,19 @@ jobs: -H "Content-Type: application/json" \ "$GITEA_API/repos/$REPOSITORY/releases" \ -d "$payload" | jq -er '.id') + echo " ✅ Created release $TAG_NAME (ID: $RELEASE_ID)" - echo " ✅ Released $TAG_NAME (ID: $RELEASE_ID) with download link + SHA-256 checksums" - - # Mirror the release on the releases repo via API (creates tag + release) - if ! curl -sf -o /dev/null -H "Authorization: token $GITEA_TOKEN" \ - "$GITEA_API/repos/$RELEASES_REPO/releases/tags/$TAG_NAME"; then - if ! curl -sf -X POST \ - -H "Authorization: token $GITEA_TOKEN" \ - -H "Content-Type: application/json" \ - "$GITEA_API/repos/$RELEASES_REPO/releases" \ - -d "$payload" > /dev/null; then - echo "⚠️ Failed to mirror release on $RELEASES_REPO (non-fatal)." >&2 - else - echo " ✅ Mirrored $TAG_NAME release on $RELEASES_REPO" - fi - fi + # Upload each .zst file as a release asset + for i in "${!zst_files[@]}"; do + fname=$(basename "${zst_files[$i]}") + size=$(stat -c %s "${zst_files[$i]}") + echo "Uploading $fname ($(( size / 1024 / 1024 )) MiB) to release $TAG_NAME..." + curl -sf -X POST \ + -H "Authorization: token $GITEA_TOKEN" \ + -F "attachment=@${zst_files[$i]}" \ + "$GITEA_API/repos/$REPOSITORY/releases/$RELEASE_ID/assets" | jq -er '.browser_download_url' + echo " ✅ Uploaded $fname" + done - name: Keep only latest 2 releases if: success() @@ -257,27 +164,24 @@ jobs: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} GITEA_API: http://192.168.1.168:3000/api/v1 REPOSITORY: ${{ github.repository }} - RELEASES_REPO: alvinlollo/AlvinArch-releases run: | set -euo pipefail test -n "$GITEA_TOKEN" - for repo in "$REPOSITORY" "$RELEASES_REPO"; do - echo "Pruning old releases in $repo..." - readarray -t ids < <(curl -sf -H "Authorization: token $GITEA_TOKEN" \ - "$GITEA_API/repos/$repo/releases" \ - | jq -er 'sort_by(.created_at) | .[].id') + echo "Pruning old releases in $REPOSITORY..." + readarray -t ids < <(curl -sf -H "Authorization: token $GITEA_TOKEN" \ + "$GITEA_API/repos/$REPOSITORY/releases" \ + | jq -er 'sort_by(.created_at) | .[].id') - to_delete=$(( ${#ids[@]} - 2 )) - if (( to_delete > 0 )); then - for ((i = 0; i < to_delete; i++)); do - id=${ids[$i]} - echo "Deleting old release ID: $id (in $repo)" - curl -sf -X DELETE -H "Authorization: token $GITEA_TOKEN" \ - "$GITEA_API/repos/$repo/releases/$id" - done - fi - done + to_delete=$(( ${#ids[@]} - 2 )) + if (( to_delete > 0 )); then + for ((i = 0; i < to_delete; i++)); do + id=${ids[$i]} + echo "Deleting old release ID: $id" + curl -sf -X DELETE -H "Authorization: token $GITEA_TOKEN" \ + "$GITEA_API/repos/$REPOSITORY/releases/$id" + done + fi - name: Cleanup mkarchiso mounts and workdirs if: always() # Runs on success, failure, or cancellation @@ -297,7 +201,7 @@ jobs: $PRIV losetup -D || true # Remove working directories with proper permissions - $PRIV rm -rf "$PWD/work" "$PWD/.releases-repo" + $PRIV rm -rf "$PWD/work" - name: Remove built ISO if: always()