diff --git a/.gitea/workflows/deploy-prod.yml b/.gitea/workflows/deploy-prod.yml index 5db685ad..d7228c37 100644 --- a/.gitea/workflows/deploy-prod.yml +++ b/.gitea/workflows/deploy-prod.yml @@ -185,6 +185,25 @@ jobs: test -s "${ARTIFACT}.sha256" || { echo "ERROR: checksum file missing"; exit 1; } echo "✓ Checksum downloaded" + - name: Download Release Manifest + run: | + ARTIFACT="${{ steps.fetch.outputs.artifact }}" + TOKEN="${{ secrets.GITEA_TOKEN }}" + RELEASE_TAG="${{ steps.fetch.outputs.tag }}" + MANIFEST_URL="https://gitea.taxbaik.com/api/v1/repos/${{ env.REPO }}/releases/tags/${RELEASE_TAG}" + + RELEASE=$(curl -sf --connect-timeout 10 --max-time 30 -H "Authorization: token $TOKEN" "$MANIFEST_URL") + MANIFEST_DOWNLOAD_URL=$(echo "$RELEASE" | jq -r '.assets[] | select(.name == "'"${ARTIFACT}"'.manifest.json") | .browser_download_url') + + if [ -z "$MANIFEST_DOWNLOAD_URL" ] || [ "$MANIFEST_DOWNLOAD_URL" = "null" ]; then + echo "ERROR: No manifest asset found for release $RELEASE_TAG" + exit 1 + fi + + curl -sfL --connect-timeout 10 --max-time 120 -H "Authorization: token $TOKEN" -o "${ARTIFACT}.manifest.json" "$MANIFEST_DOWNLOAD_URL" + test -s "${ARTIFACT}.manifest.json" || { echo "ERROR: manifest file missing"; exit 1; } + echo "✓ Manifest downloaded" + - name: Validate Release Checksum run: | ARTIFACT="${{ steps.fetch.outputs.artifact }}" @@ -198,6 +217,38 @@ jobs: fi echo "✓ Artifact checksum verified" + - name: Validate Release Manifest + run: | + ARTIFACT="${{ steps.fetch.outputs.artifact }}" + python3 - <<'PY' + import json + import hashlib + import pathlib + import sys + + artifact = pathlib.Path("${ARTIFACT}") + manifest = json.loads(pathlib.Path("${ARTIFACT}.manifest.json").read_text(encoding="utf-8")) + expected = { + "artifact": artifact.name, + "version": "${{ steps.fetch.outputs.tag }}", + "commit": "${{ steps.fetch.outputs.commit }}", + } + + for key, value in expected.items(): + if manifest.get(key) != value: + print(f"ERROR: manifest {key} mismatch: {manifest.get(key)!r} != {value!r}") + sys.exit(1) + + actual_sha = hashlib.sha256(artifact.read_bytes()).hexdigest() + if manifest.get("sha256") != actual_sha: + print("ERROR: manifest sha256 mismatch") + print(f"Expected: {manifest.get('sha256')}") + print(f"Actual: {actual_sha}") + sys.exit(1) + + print("✓ Manifest verified") + PY + - name: Setup SSH run: | mkdir -p ~/.ssh diff --git a/.gitea/workflows/prepare-release.yml b/.gitea/workflows/prepare-release.yml index 7d981329..5727aaa9 100644 --- a/.gitea/workflows/prepare-release.yml +++ b/.gitea/workflows/prepare-release.yml @@ -162,6 +162,30 @@ jobs: echo "✓ Checksum created: ${ARTIFACT}.sha256" cat "${ARTIFACT}.sha256" + - name: Generate Release Manifest + run: | + VERSION="${{ steps.metadata.outputs.version }}" + COMMIT="${{ steps.metadata.outputs.commit }}" + ARTIFACT="quantengine_${VERSION}.tar.gz" + CHECKSUM=$(cat "${ARTIFACT}.sha256") + python3 - <