f54795f34f
The CI builds a non-reproducible tarball after the tag is created, then updates artifacthub-pkg.yml on main with the correct checksum. But Artifact Hub reads from the tag ref, not main, so it sees the stale checksum and Headlamp rejects the plugin with "Checksum mismatch". Changes: - Add guard step: if the GitHub release tarball checksum already matches the metadata in the current commit, skip the entire build (prevents infinite retrigger loop) - After updating metadata on main, force-move the tag to that commit so AH reads the correct checksum - Push main + tag directly to GitHub to avoid mirror sync delay - Replace akkuman/gitea-release-action with curl-based approach so all steps use the same shell guard pattern Release flow: tag push -> build -> publish releases -> update metadata on main -> force-move tag -> (retriggered run hits guard -> exits) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
185 lines
8.6 KiB
YAML
185 lines
8.6 KiB
YAML
name: Release
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
|
|
jobs:
|
|
release:
|
|
runs-on: ubuntu-latest
|
|
container: node:20
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Check if release is already finalized
|
|
run: |
|
|
VERSION=${GITHUB_REF_NAME#v}
|
|
TARBALL_URL="https://github.com/cpfarhood/polaris-headlamp-plugin/releases/download/${GITHUB_REF_NAME}/polaris-headlamp-plugin-${VERSION}.tar.gz"
|
|
HTTP_CODE=$(curl -sL -o /tmp/release.tar.gz -w "%{http_code}" "$TARBALL_URL" 2>/dev/null)
|
|
if [ "$HTTP_CODE" = "200" ]; then
|
|
ACTUAL="sha256:$(sha256sum /tmp/release.tar.gz | awk '{print $1}')"
|
|
EXPECTED=$(grep 'archive-checksum' artifacthub-pkg.yml | awk '{print $2}')
|
|
echo "Release tarball checksum: $ACTUAL"
|
|
echo "Metadata checksum: $EXPECTED"
|
|
if [ "$ACTUAL" = "$EXPECTED" ]; then
|
|
echo "SKIP_BUILD=true" >> $GITHUB_ENV
|
|
echo "Checksums match - release is finalized, nothing to do"
|
|
fi
|
|
else
|
|
echo "No existing release (HTTP $HTTP_CODE) - will build"
|
|
fi
|
|
rm -f /tmp/release.tar.gz
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
[ "$SKIP_BUILD" = "true" ] && exit 0
|
|
npm ci
|
|
|
|
- name: Build plugin
|
|
run: |
|
|
[ "$SKIP_BUILD" = "true" ] && exit 0
|
|
npx @kinvolk/headlamp-plugin build
|
|
|
|
- name: Package tarball
|
|
run: |
|
|
[ "$SKIP_BUILD" = "true" ] && exit 0
|
|
npx @kinvolk/headlamp-plugin package
|
|
|
|
- name: Compute tarball checksum
|
|
run: |
|
|
[ "$SKIP_BUILD" = "true" ] && exit 0
|
|
TARBALL=$(ls *.tar.gz)
|
|
CHECKSUM=$(sha256sum "$TARBALL" | awk '{print $1}')
|
|
echo "TARBALL=$TARBALL" >> $GITHUB_ENV
|
|
echo "CHECKSUM=$CHECKSUM" >> $GITHUB_ENV
|
|
echo "Tarball: $TARBALL"
|
|
echo "Checksum: sha256:$CHECKSUM"
|
|
|
|
- name: Install Docker CLI
|
|
run: |
|
|
[ "$SKIP_BUILD" = "true" ] && exit 0
|
|
apt-get update && apt-get install -y docker.io
|
|
|
|
- name: Build and push Docker image
|
|
run: |
|
|
[ "$SKIP_BUILD" = "true" ] && exit 0
|
|
docker build -t git.farh.net/${{ github.repository }}:${{ github.ref_name }} -t git.farh.net/${{ github.repository }}:latest .
|
|
echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.farh.net -u ${{ github.actor }} --password-stdin
|
|
docker push git.farh.net/${{ github.repository }}:${{ github.ref_name }}
|
|
docker push git.farh.net/${{ github.repository }}:latest
|
|
|
|
- name: Create Gitea release
|
|
run: |
|
|
[ "$SKIP_BUILD" = "true" ] && exit 0
|
|
API_URL="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}"
|
|
# Create release (or get existing)
|
|
RELEASE=$(curl -s -X POST \
|
|
-H "Authorization: token ${{ github.token }}" \
|
|
-H "Content-Type: application/json" \
|
|
"${API_URL}/releases" \
|
|
-d "{\"tag_name\":\"${GITHUB_REF_NAME}\",\"name\":\"${GITHUB_REF_NAME}\"}")
|
|
RELEASE_ID=$(echo "$RELEASE" | node -e "process.stdin.resume();let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>console.log(JSON.parse(d).id))")
|
|
if [ "$RELEASE_ID" = "undefined" ]; then
|
|
RELEASE=$(curl -sf \
|
|
-H "Authorization: token ${{ github.token }}" \
|
|
"${API_URL}/releases/tags/${GITHUB_REF_NAME}")
|
|
RELEASE_ID=$(echo "$RELEASE" | node -e "process.stdin.resume();let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>console.log(JSON.parse(d).id))")
|
|
fi
|
|
echo "Gitea Release ID: $RELEASE_ID"
|
|
# Delete existing assets
|
|
ASSETS=$(curl -sf \
|
|
-H "Authorization: token ${{ github.token }}" \
|
|
"${API_URL}/releases/${RELEASE_ID}/assets")
|
|
echo "$ASSETS" | node -e "
|
|
process.stdin.resume();let d='';
|
|
process.stdin.on('data',c=>d+=c);
|
|
process.stdin.on('end',()=>{
|
|
JSON.parse(d).forEach(a=>console.log(a.id));
|
|
})" | while read -r ASSET_ID; do
|
|
curl -sf -X DELETE \
|
|
-H "Authorization: token ${{ github.token }}" \
|
|
"${API_URL}/releases/${RELEASE_ID}/assets/${ASSET_ID}"
|
|
done
|
|
# Upload tarball
|
|
curl -sf -X POST \
|
|
-H "Authorization: token ${{ github.token }}" \
|
|
-F "attachment=@${TARBALL}" \
|
|
"${API_URL}/releases/${RELEASE_ID}/assets?name=${TARBALL}"
|
|
echo "Gitea release updated"
|
|
|
|
- name: Create GitHub release
|
|
continue-on-error: true
|
|
run: |
|
|
[ "$SKIP_BUILD" = "true" ] && exit 0
|
|
GH_API="https://api.github.com/repos/cpfarhood/polaris-headlamp-plugin"
|
|
# Create release or fetch existing one
|
|
BODY=$(curl -s -X POST \
|
|
-H "Authorization: token ${{ secrets.GH_PAT }}" \
|
|
-H "Accept: application/vnd.github+json" \
|
|
"${GH_API}/releases" \
|
|
-d "{\"tag_name\":\"${GITHUB_REF_NAME}\",\"name\":\"${GITHUB_REF_NAME}\",\"generate_release_notes\":true}")
|
|
RELEASE_ID=$(echo "$BODY" | node -e "process.stdin.resume();let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>console.log(JSON.parse(d).id))")
|
|
if [ "$RELEASE_ID" = "undefined" ]; then
|
|
echo "Release already exists, fetching it..."
|
|
BODY=$(curl -sf \
|
|
-H "Authorization: token ${{ secrets.GH_PAT }}" \
|
|
-H "Accept: application/vnd.github+json" \
|
|
"${GH_API}/releases/tags/${GITHUB_REF_NAME}")
|
|
RELEASE_ID=$(echo "$BODY" | node -e "process.stdin.resume();let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>console.log(JSON.parse(d).id))")
|
|
fi
|
|
echo "GitHub Release ID: $RELEASE_ID"
|
|
# Delete existing assets with the same name
|
|
ASSETS=$(curl -sf \
|
|
-H "Authorization: token ${{ secrets.GH_PAT }}" \
|
|
-H "Accept: application/vnd.github+json" \
|
|
"${GH_API}/releases/${RELEASE_ID}/assets")
|
|
echo "$ASSETS" | node -e "
|
|
process.stdin.resume();let d='';
|
|
process.stdin.on('data',c=>d+=c);
|
|
process.stdin.on('end',()=>{
|
|
const assets=JSON.parse(d);
|
|
assets.filter(a=>a.name==='${TARBALL}').forEach(a=>console.log(a.id));
|
|
})" | while read -r ASSET_ID; do
|
|
echo "Deleting existing asset $ASSET_ID..."
|
|
curl -sf -X DELETE \
|
|
-H "Authorization: token ${{ secrets.GH_PAT }}" \
|
|
"${GH_API}/releases/assets/${ASSET_ID}"
|
|
done
|
|
# Upload tarball
|
|
curl -sf -X POST \
|
|
-H "Authorization: token ${{ secrets.GH_PAT }}" \
|
|
-H "Content-Type: application/gzip" \
|
|
"https://uploads.github.com/repos/cpfarhood/polaris-headlamp-plugin/releases/${RELEASE_ID}/assets?name=${TARBALL}" \
|
|
--data-binary "@${TARBALL}"
|
|
echo "GitHub release updated with same tarball"
|
|
|
|
- name: Update metadata and align tag
|
|
run: |
|
|
[ "$SKIP_BUILD" = "true" ] && exit 0
|
|
VERSION=${GITHUB_REF_NAME#v}
|
|
git checkout main
|
|
sed -i "s|headlamp/plugin/archive-checksum:.*|headlamp/plugin/archive-checksum: sha256:${CHECKSUM}|" artifacthub-pkg.yml
|
|
sed -i "s|headlamp/plugin/archive-url:.*|headlamp/plugin/archive-url: \"https://github.com/cpfarhood/polaris-headlamp-plugin/releases/download/${GITHUB_REF_NAME}/polaris-headlamp-plugin-${VERSION}.tar.gz\"|" artifacthub-pkg.yml
|
|
sed -i "s|^version:.*|version: ${VERSION}|" artifacthub-pkg.yml
|
|
git config user.name "gitea-actions[bot]"
|
|
git config user.email "gitea-actions[bot]@git.farh.net"
|
|
git add artifacthub-pkg.yml
|
|
git diff --cached --quiet || {
|
|
git commit -m "ci: update artifact hub metadata for ${GITHUB_REF_NAME}"
|
|
git push origin main
|
|
}
|
|
# Force-move tag to the commit with correct checksum.
|
|
# This triggers a new CI run, but the guard step will detect
|
|
# that the release checksum already matches and skip the build.
|
|
git tag -f ${GITHUB_REF_NAME}
|
|
git push -f origin ${GITHUB_REF_NAME}
|
|
# Also push to GitHub directly to avoid waiting for mirror sync
|
|
git remote add github https://x-access-token:${{ secrets.GH_PAT }}@github.com/cpfarhood/polaris-headlamp-plugin.git 2>/dev/null || true
|
|
git push github main 2>/dev/null || true
|
|
git push -f github ${GITHUB_REF_NAME} 2>/dev/null || true
|
|
echo "Tag ${GITHUB_REF_NAME} aligned with updated metadata"
|