Repository navigation
193 lines (190 loc) · 8.51 KB
/
Copy pathrelease.yml
File metadata and controls
193 lines (190 loc) · 8.51 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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
name: Release
# A version tag packages one VSIX, attaches it to a GitHub release and
# publishes that same file to Open VSX and the Visual Studio Marketplace.
# Only a tag on promoted main whose commit passed verify publishes.
# docs/releasing.md covers the one-time store setup and the Zed registry.
on:
push:
tags: ["v[0-9]+.[0-9]+.[0-9]+"]
permissions:
contents: read
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
jobs:
package:
runs-on: ubuntu-24.04
permissions:
checks: read
contents: read
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Require a tag on promoted main that passed verify
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
fail() { echo "::error::$1"; exit 1; }
commit="$(gh api "repos/$GITHUB_REPOSITORY/commits/$GITHUB_REF_NAME" --jq .sha)"
status="$(gh api "repos/$GITHUB_REPOSITORY/compare/$commit...main" --jq .status)"
[[ "$status" == ahead || "$status" == identical ]] ||
fail "$GITHUB_REF_NAME names $commit, which is not on main. Promote dev to main, then tag the main commit."
verify="$(gh api "repos/$GITHUB_REPOSITORY/commits/$commit/check-runs?check_name=verify&per_page=100" \
--jq '[.check_runs[] | select(.app.slug == "github-actions")] | sort_by(.started_at) | last | .conclusion // "missing"')"
[[ "$verify" == success ]] ||
fail "verify has not passed on $commit (newest result: $verify). Tag the main commit validated by its promotion pull request."
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
package-manager-cache: false
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.4.0
- name: Prepare pinned Rust toolchain
run: rustup toolchain install 1.90 --profile minimal --component rustfmt --target wasm32-wasip2
- run: bun install --frozen-lockfile
- name: Check that the tag names the manifest version
id: version
run: |
version="$(node -p 'require("./vscode/package.json").version')"
if [ "$GITHUB_REF_NAME" != "v$version" ]; then
echo "::error::Tag $GITHUB_REF_NAME does not match manifest version $version."
exit 1
fi
echo "version=$version" >> "$GITHUB_OUTPUT"
- run: bun run verify
- name: Package VS Code extension
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
mkdir -p artifacts
bun run --cwd vscode package -- --out "../artifacts/rootform-$VERSION.vsix"
cd artifacts && sha256sum "rootform-$VERSION.vsix" > SHA256SUMS
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: vsix
path: artifacts/
if-no-files-found: error
github-release:
needs: package
runs-on: ubuntu-24.04
permissions:
contents: write
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: vsix
path: artifacts
- name: Create GitHub release
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ needs.package.outputs.version }}
run: |
set -euo pipefail
# gh uploads to a draft and publishes it last. A re-run keeps a release an earlier attempt published.
if ! gh api "repos/$GITHUB_REPOSITORY/releases/tags/$GITHUB_REF_NAME" >/dev/null 2>&1; then
gh release create "$GITHUB_REF_NAME" artifacts/* \
--repo "$GITHUB_REPOSITORY" --verify-tag \
--title "Rootform editors $VERSION" \
--notes "VS Code and Zed extensions $VERSION. Changes: https://github.com/$GITHUB_REPOSITORY/blob/$GITHUB_REF_NAME/vscode/CHANGELOG.md"
fi
- name: Require an immutable release holding the packaged files
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
expected="$(cd artifacts && for file in *; do jq -nc --arg name "$file" --arg digest "sha256:$(sha256sum "$file" | cut -d' ' -f1)" '{name: $name, digest: $digest}'; done | jq -sc 'sort_by(.name)')"
# The repository enforces immutable releases. GitHub can report the lock a few seconds after publication.
for attempt in 1 2 3 4 5 6; do
release="$(gh api "repos/$GITHUB_REPOSITORY/releases/tags/$GITHUB_REF_NAME")"
actual="$(jq -c '[.assets[] | {name, digest}] | sort_by(.name)' <<<"$release")"
if jq -e '.draft == false and .immutable == true' <<<"$release" >/dev/null && [[ "$actual" == "$expected" ]]; then
echo "Published immutable $(jq -r .html_url <<<"$release") holding the packaged VSIX and SHA256SUMS." >> "$GITHUB_STEP_SUMMARY"
exit 0
fi
sleep $((attempt * 5))
done
echo "::error::$GITHUB_REF_NAME is not an immutable release holding exactly the packaged files, so no store was published. Re-run failed jobs to reuse this run's VSIX."
exit 1
open-vsx:
needs: [package, github-release]
runs-on: ubuntu-24.04
environment: release
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
package-manager-cache: false
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.4.0
- run: bun install --frozen-lockfile
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: vsix
path: artifacts
# The first release creates the namespace with the bootstrap token.
- name: Create the Open VSX namespace
working-directory: vscode
env:
OVSX_PAT: ${{ secrets.OVSX_PAT }}
run: |
namespace="$(node -p 'require("./package.json").publisher')"
status="$(curl -sS -o /dev/null -w '%{http_code}' "https://open-vsx.org/api/$namespace")"
if [ "$status" = "404" ] && [ -n "$OVSX_PAT" ]; then
./node_modules/.bin/ovsx create-namespace "$namespace"
fi
# Trusted publishing exchanges this job's OIDC token. OVSX_PAT exists only
# to bootstrap the first version and takes precedence while it is set.
- name: Publish to Open VSX
working-directory: vscode
env:
OVSX_PAT: ${{ secrets.OVSX_PAT }}
VERSION: ${{ needs.package.outputs.version }}
run: ./node_modules/.bin/ovsx publish --packagePath "../artifacts/rootform-$VERSION.vsix" --skip-duplicate
vs-marketplace:
needs: [package, github-release]
# Runs once the Entra ID identity is configured; until then the VSIX from
# the GitHub release is uploaded on the Marketplace publisher page.
if: vars.AZURE_CLIENT_ID != ''
runs-on: ubuntu-24.04
environment: release
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
package-manager-cache: false
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.4.0
- run: bun install --frozen-lockfile
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: vsix
path: artifacts
- uses: azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906 # v3.1.0
with:
client-id: ${{ vars.AZURE_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TENANT_ID }}
allow-no-subscriptions: true
- name: Publish to the Visual Studio Marketplace
working-directory: vscode
env:
VERSION: ${{ needs.package.outputs.version }}
run: ./node_modules/.bin/vsce publish --azure-credential --packagePath "../artifacts/rootform-$VERSION.vsix" --skip-duplicate