Skip to content

Update Arcane Release Assets #2688

Update Arcane Release Assets

Update Arcane Release Assets #2688

name: Update Arcane Release Assets
on:
schedule:
- cron: '*/30 * * * *'
workflow_dispatch:
permissions:
contents: write
pull-requests: write
id-token: write
jobs:
update-release-assets:
if: ${{ github.repository_owner == 'getarcaneapp' && github.actor != 'getarcaneappbot' }}
runs-on: depot-ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Fetch releases list
id: releases
run: |
set -euo pipefail
RELEASES_JSON=/tmp/releases.json
curl -sSL \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/getarcaneapp/arcane/releases?per_page=100" \
-o "$RELEASES_JSON"
echo "releases_json=$RELEASES_JSON" >> "$GITHUB_OUTPUT"
- name: Check current assets
id: check
shell: bash
run: |
set -euo pipefail
RELEASES_JSON="${{ steps.releases.outputs.releases_json }}"
VERSION=$(jq -r '[.[] | select(.draft == false and .prerelease == false)][0].tag_name // ""' "$RELEASES_JSON")
if [[ -z "$VERSION" ]]; then
echo "No releases found in $RELEASES_JSON" >&2
exit 1
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
CHANGELOG_UP_TO_DATE=false
shopt -s nullglob
CHANGELOG_FILES=(content/changelog/*.md)
if (( ${#CHANGELOG_FILES[@]} > 0 )); then
CHANGELOG_UP_TO_DATE=true
while IFS= read -r tag; do
if ! grep -qE "^##[[:space:]]+$tag\\b" "${CHANGELOG_FILES[@]}"; then
CHANGELOG_UP_TO_DATE=false
break
fi
done < <(jq -r '.[] | select(.draft == false and .prerelease == false) | .tag_name' "$RELEASES_JSON")
fi
SBOM_UP_TO_DATE=false
if [[ -f static/sbom/version.txt ]]; then
CURRENT=$(cat static/sbom/version.txt)
if [[ "$CURRENT" == "$VERSION" ]]; then
SBOM_UP_TO_DATE=true
fi
fi
if [[ "$CHANGELOG_UP_TO_DATE" == "true" && "$SBOM_UP_TO_DATE" == "true" ]]; then
echo "skip_all=true" >> "$GITHUB_OUTPUT"
else
echo "skip_all=false" >> "$GITHUB_OUTPUT"
fi
if [[ "$CHANGELOG_UP_TO_DATE" == "true" ]]; then
echo "do_changelog=false" >> "$GITHUB_OUTPUT"
else
echo "do_changelog=true" >> "$GITHUB_OUTPUT"
fi
if [[ "$SBOM_UP_TO_DATE" == "true" ]]; then
echo "do_sbom=false" >> "$GITHUB_OUTPUT"
else
echo "do_sbom=true" >> "$GITHUB_OUTPUT"
fi
- name: Update changelog
if: steps.check.outputs.do_changelog == 'true'
shell: bash
run: |
set -euo pipefail
RELEASES_JSON="${{ steps.releases.outputs.releases_json }}" REPO="getarcaneapp/arcane" CHANGELOG_DIR="content/changelog" bash scripts/update-changelog.sh
- name: Checkout arcane repo
if: steps.check.outputs.do_sbom == 'true'
uses: actions/checkout@v7
with:
repository: getarcaneapp/arcane
ref: ${{ steps.check.outputs.version }}
path: arcane
fetch-depth: 1
- name: Set up Go
if: steps.check.outputs.do_sbom == 'true'
uses: actions/setup-go@v7
with:
go-version-file: arcane/go.mod
- name: Set up just
if: steps.check.outputs.do_sbom == 'true'
uses: extractions/setup-just@v4
- name: Generate config.json
if: steps.check.outputs.do_sbom == 'true'
shell: bash
run: |
set -euo pipefail
cd arcane
just docs config ../static/config.json
- name: Extract SBOMs from published images
if: steps.check.outputs.do_sbom == 'true'
shell: bash
run: |
set -euo pipefail
VERSION="${{ steps.check.outputs.version }}"
mkdir -p static/sbom/manager static/sbom/agent
# Pull the SBOM attestations attached to the published images, so
# the data matches exactly what ships. On a multi-platform tag,
# `.SBOM` is a map keyed by platform, each entry holding the SPDX
# document. jq pretty-prints to avoid compact single-line JSON in
# repo diffs; -e fails the job if a platform has no attestation.
for image in manager agent; do
if [[ "$image" == "manager" ]]; then
ref="ghcr.io/getarcaneapp/arcane:$VERSION"
else
ref="ghcr.io/getarcaneapp/arcane-headless:$VERSION"
fi
sboms=$(docker buildx imagetools inspect "$ref" --format '{{ json .SBOM }}')
for spec in \
"linux/amd64:linux_amd64" \
"linux/arm64:linux_arm64" \
"linux/arm/v7:linux_armv7" \
"linux/riscv64:linux_riscv64"
do
platform="${spec%:*}"
out="static/sbom/$image/${spec##*:}.spdx.json"
if ! jq -e --arg p "$platform" '.[$p].SPDX' <<< "$sboms" > "$out"; then
echo "No SBOM attestation for $platform in $ref" >&2
exit 1
fi
done
done
- name: Write SBOM metadata and cleanup
if: steps.check.outputs.do_sbom == 'true'
run: |
set -euo pipefail
VERSION="${{ steps.check.outputs.version }}"
# Save version
echo "$VERSION" > static/sbom/version.txt
# Create metadata file
cat > static/sbom/metadata.json << EOF
{
"version": "$VERSION",
"updated": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"images": {
"manager": {
"name": "ghcr.io/getarcaneapp/arcane",
"architectures": ["linux/amd64", "linux/arm64", "linux/arm/v7", "linux/riscv64"],
"sbomFiles": {
"amd64": "/sbom/manager/linux_amd64.spdx.json",
"arm64": "/sbom/manager/linux_arm64.spdx.json",
"armv7": "/sbom/manager/linux_armv7.spdx.json",
"riscv64": "/sbom/manager/linux_riscv64.spdx.json"
}
},
"agent": {
"name": "ghcr.io/getarcaneapp/arcane-headless",
"architectures": ["linux/amd64", "linux/arm64", "linux/arm/v7", "linux/riscv64"],
"sbomFiles": {
"amd64": "/sbom/agent/linux_amd64.spdx.json",
"arm64": "/sbom/agent/linux_arm64.spdx.json",
"armv7": "/sbom/agent/linux_armv7.spdx.json",
"riscv64": "/sbom/agent/linux_riscv64.spdx.json"
}
}
}
}
EOF
echo "SBOM files generated for $VERSION"
ls -la static/sbom/
ls -la static/sbom/manager/
ls -la static/sbom/agent/
# Clean up cloned repo
rm -rf arcane
- name: Check for changes
id: changes
if: steps.check.outputs.skip_all != 'true'
run: |
if [[ -n "$(git status --porcelain -- content/changelog.md content/changelog/ static/config.json static/sbom/)" ]]; then
echo "has_changes=true" >> "$GITHUB_OUTPUT"
else
echo "has_changes=false" >> "$GITHUB_OUTPUT"
fi
- name: Create pull request
if: steps.changes.outputs.has_changes == 'true'
uses: peter-evans/create-pull-request@v8
with:
token: ${{ secrets.ARCANE_BOT_TOKEN }}
commit-message: 'chore(release): update assets for ${{ steps.check.outputs.version }}'
committer: 'getarcaneappbot <info@getarcane.app>'
author: 'getarcaneappbot <info@getarcane.app>'
signoff: true
title: 'chore(release): update assets for ${{ steps.check.outputs.version }}'
body: |
Updates Arcane release assets for ${{ steps.check.outputs.version }}.
## Changes
- Changelog entry (if new)
- Generated `static/config.json` (if changed)
- SBOM files for manager and agent images (if new)
---
*This PR was automatically generated.*
branch: 'chore/release-assets-${{ steps.check.outputs.version }}'
base: main
labels: 'docs(changelog),chore(config),chore(sbom)'
add-paths: |
content/changelog.md
content/changelog/
static/config.json
static/sbom/
delete-branch: true