-
Notifications
You must be signed in to change notification settings - Fork 0
133 lines (124 loc) · 6.09 KB
/
Copy pathsqlite3mc-release.yml
File metadata and controls
133 lines (124 loc) · 6.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
---
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 fuzz/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