name: Release on: push: tags: - 'v*' permissions: contents: write jobs: release: # The repository runner advertises Gitea's default ubuntu-latest label. # Using an unavailable custom label leaves every release permanently queued. runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Validate release tag id: release_meta env: GITEA_REF_NAME: ${{ github.ref_name }} GITEA_SHA: ${{ github.sha }} run: | VERSION=${GITEA_REF_NAME#v} test "$GITEA_REF_NAME" = "v$VERSION" ./scripts/check-semver.sh "$VERSION" test "$(git rev-parse "refs/tags/$GITEA_REF_NAME^{commit}")" = "$GITEA_SHA" test -z "$(git status --porcelain --untracked-files=all)" printf 'version=%s\n' "$VERSION" >> "$GITHUB_OUTPUT" - uses: actions/setup-java@v4 with: distribution: temurin java-version: '17' cache: maven - uses: actions/setup-node@v4 with: node-version: '22' cache: npm cache-dependency-path: frontend/package-lock.json - name: Verify backend env: RELEASE_VERSION: ${{ steps.release_meta.outputs.version }} run: ./backend/mvnw -f backend/pom.xml -Drevision="$RELEASE_VERSION" test - name: Verify frontend working-directory: frontend run: | HUSKY=0 npm ci npm run lint -- --no-fix npm run stylelint npm test npm run audit:dependencies npm run build npx playwright install --with-deps chromium npm run test:e2e npm run test:dist - name: Verify release contracts and scripts run: | ./scripts/check-openapi.sh openapi.yaml ./scripts/test-install-fixture.sh ./scripts/test-git-install-fixture.sh ./scripts/test-update-fixture.sh ./scripts/test-baota-start-fixture.sh ./scripts/test-purge-fixture.sh ./scripts/test-gitea-publish-fixture.sh shellcheck deploy/install.sh deploy/install-from-git.sh deploy/update.sh deploy/baota-start.sh deploy/baota-init.sh \ deploy/purge.sh \ scripts/check-semver.sh \ scripts/package-release.sh scripts/publish-gitea-release.sh \ scripts/generate-release-key.sh scripts/test-install-fixture.sh \ scripts/test-git-install-fixture.sh \ scripts/test-update-fixture.sh scripts/test-gitea-publish-fixture.sh \ scripts/test-baota-start-fixture.sh scripts/test-purge-fixture.sh \ scripts/verify-release.sh - name: Build and sign release assets env: RELEASE_SIGNING_KEY_B64: ${{ secrets.RELEASE_SIGNING_KEY_B64 }} RELEASE_VERSION: ${{ steps.release_meta.outputs.version }} KAIDI_TRUSTED_RELEASE_PUBLIC_KEY_SHA256: ${{ vars.KAIDI_RELEASE_PUBLIC_KEY_SHA256 }} KAIDI_RELEASE_NOTES: Kaidi Finance ${{ github.ref_name }} KAIDI_SOURCE_REVISION: ${{ github.sha }} KAIDI_SOURCE_REF: ${{ github.ref_name }} KAIDI_SOURCE_DIRTY: 'false' run: | test -n "$RELEASE_SIGNING_KEY_B64" trap 'shred -u "$RUNNER_TEMP/release-key.pem" 2>/dev/null || rm -f "$RUNNER_TEMP/release-key.pem"' EXIT printf '%s' "$RELEASE_SIGNING_KEY_B64" | base64 --decode > "$RUNNER_TEMP/release-key.pem" chmod 600 "$RUNNER_TEMP/release-key.pem" KAIDI_RELEASE_SIGNING_KEY="$RUNNER_TEMP/release-key.pem" \ ./scripts/package-release.sh "$RELEASE_VERSION" - name: Verify signed release assets env: KAIDI_TRUSTED_RELEASE_PUBLIC_KEY_SHA256: ${{ vars.KAIDI_RELEASE_PUBLIC_KEY_SHA256 }} KAIDI_EXPECTED_SOURCE_REVISION: ${{ github.sha }} KAIDI_EXPECTED_SOURCE_REF: ${{ github.ref_name }} KAIDI_EXPECTED_SOURCE_DIRTY: 'false' run: ./scripts/verify-release.sh dist/release - name: Publish Gitea release env: GITEA_TOKEN: ${{ secrets.RELEASE_GITEA_TOKEN }} GITEA_SERVER_URL: ${{ github.server_url }} GITEA_REPOSITORY: ${{ github.repository }} GITEA_REF_NAME: ${{ github.ref_name }} GITEA_SHA: ${{ github.sha }} run: ./scripts/publish-gitea-release.sh - name: Upload Playwright report after failure if: failure() uses: actions/upload-artifact@v4 with: name: playwright-report-${{ github.run_id }} path: frontend/playwright-report if-no-files-found: ignore retention-days: 7