Skip to content

SQLite3MC release

SQLite3MC release #17

---
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