Repository navigation
SQLite3MC release #17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| name: SQLite3MC release | |
| "on": | |
| schedule: | |
| - cron: "17 5 * * *" | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: SQLite3MC release to vendor, such as 2.5.2. Empty means the latest. | |
| required: false | |
| type: string | |
| retry: | |
| description: Vendor it even if its pull request was closed unmerged. | |
| required: false | |
| type: boolean | |
| default: false | |
| # Every write goes through the app token, so the workflow token stays read-only. | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| concurrency: | |
| group: ${{ github.workflow }} | |
| cancel-in-progress: false | |
| jobs: | |
| vendor: | |
| name: Vendor a SQLite3MC release | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| # A manual dispatch may select another ref, and only main's tree belongs here. | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: main | |
| persist-credentials: false | |
| - name: Pick the release | |
| id: release | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GH_REPO: ${{ github.repository }} | |
| REQUESTED: ${{ inputs.version }} | |
| RETRY: ${{ inputs.retry }} | |
| run: | | |
| set -euo pipefail | |
| pinned=$(sed -nE 's/^pub const SQLITE3MC_VERSION: &str = "(.*)";$/\1/p' src/lib.rs) | |
| if [ -n "$REQUESTED" ]; then | |
| target=$REQUESTED | |
| [ "$target" != "$pinned" ] && moved=yes | |
| else | |
| target=$(gh release view --repo utelle/SQLite3MultipleCiphers --json tagName --jq '.tagName | ltrimstr("v")') | |
| newest=$(printf '%s\n%s\n' "$pinned" "$target" | sort -V | tail -n 1) | |
| [ "$target" != "$pinned" ] && [ "$newest" = "$target" ] && moved=yes | |
| fi | |
| echo "pinned $pinned, target $target" | |
| # A pull request closed unmerged is a rejection, which only a retry dispatch overrides. | |
| rejected=$(gh pr list --head "sqlite3mc/v$target" --state closed --json mergedAt \ | |
| --jq '[.[] | select(.mergedAt == null)] | length') | |
| if [ "${moved:-}" = yes ] && [ "$rejected" -gt 0 ] && [ "$RETRY" != true ]; then | |
| echo "SQLite3MC $target was rejected by closing its pull request, so it is skipped" | |
| moved= | |
| fi | |
| echo "target=$target" >> "$GITHUB_OUTPUT" | |
| [ "${moved:-}" = yes ] && echo "moved=yes" >> "$GITHUB_OUTPUT" | |
| true | |
| - if: steps.release.outputs.moved == 'yes' | |
| uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 | |
| - if: steps.release.outputs.moved == 'yes' | |
| env: | |
| TARGET: ${{ steps.release.outputs.target }} | |
| run: ./bump.sh "$TARGET" | |
| # A pull request from the app, unlike one from the workflow token, starts CI, CodeQL, | |
| # Coverage and Sonar on it, and so does every later push to its branch. | |
| - if: steps.release.outputs.moved == 'yes' | |
| name: Mint an app token | |
| id: app-token | |
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| with: | |
| client-id: ${{ secrets.RELEASE_APP_CLIENT_ID }} | |
| private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }} | |
| permission-contents: write | |
| permission-pull-requests: write | |
| - if: steps.release.outputs.moved == 'yes' | |
| name: Open the pull request | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | |
| GH_REPO: ${{ github.repository }} | |
| APP_SLUG: ${{ steps.app-token.outputs.app-slug }} | |
| VERSION: ${{ steps.release.outputs.target }} | |
| run: | | |
| set -euo pipefail | |
| sqlite=$(sed -nE 's/^pub const SQLITE_VERSION: &str = "(.*)";$/\1/p' src/lib.rs) | |
| branch="sqlite3mc/v$VERSION" | |
| title="Vendor SQLite3MC $VERSION on SQLite $sqlite" | |
| bot_id=$(gh api "/users/${APP_SLUG}%5Bbot%5D" --jq .id) | |
| git config user.name "${APP_SLUG}[bot]" | |
| git config user.email "${bot_id}+${APP_SLUG}[bot]@users.noreply.github.com" | |
| git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" | |
| git checkout -b "$branch" | |
| git add Cargo.toml Cargo.lock smoke/Cargo.lock upgrade.sh src/lib.rs sqlite3mc | |
| git commit -m "$title" | |
| # An unchanged push would only rerun every check, so the branch moves only when its | |
| # content changed or main moved under it. | |
| if git ls-remote --exit-code --heads origin "$branch" >/dev/null; then | |
| git fetch --depth=2 origin "$branch":refs/remotes/origin/"$branch" | |
| if [ "$(git rev-parse "origin/$branch^{tree}")" = "$(git rev-parse "HEAD^{tree}")" ] \ | |
| && [ "$(git rev-parse "origin/$branch^")" = "$(git rev-parse HEAD^)" ]; then | |
| echo "$branch already holds this content on the current main" | |
| else | |
| git push --force-with-lease origin HEAD:refs/heads/"$branch" | |
| fi | |
| else | |
| git push origin HEAD:refs/heads/"$branch" | |
| fi | |
| open=$(gh pr list --head "$branch" --state open --json number --jq length) | |
| [ "$open" -gt 0 ] || gh pr create \ | |
| --base main --head "$branch" \ | |
| --title "$title" \ | |
| --body "SQLite3MC $VERSION, from https://github.com/utelle/SQLite3MultipleCiphers/releases/tag/v$VERSION. The archive's checksum was taken from the release's SHA256SUMS after its Sigstore signature verified against SQLite3MC's own release workflow, and the vendored files were extracted from the archive unchanged." | |
| # Every other release branch is superseded, whether its pull request is open or closed. | |
| gh pr list --state open --json number,headRefName \ | |
| --jq ".[] | select(.headRefName | startswith(\"sqlite3mc/v\")) | select(.headRefName != \"$branch\") | .number" \ | |
| | while read -r n; do gh pr close "$n" --comment "Superseded by SQLite3MC $VERSION."; done | |
| git ls-remote --heads origin 'refs/heads/sqlite3mc/v*' | cut -f2 \ | |
| | { grep -vx "refs/heads/$branch" || true; } \ | |
| | while read -r ref; do git push origin --delete "$ref"; done |