-
Notifications
You must be signed in to change notification settings - Fork 0
194 lines (177 loc) · 7.59 KB
/
Copy pathrelease.yml
File metadata and controls
194 lines (177 loc) · 7.59 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
194
name: Build and release tree-sitter-cli .deb packages
on:
workflow_dispatch:
inputs:
ts_version:
description: "tree-sitter tag to package (e.g. v0.26.10). Leave empty to use the latest release."
required: false
deb_revision:
description: 'Package revision to publish (Debian "debian_revision" convention). Leave empty to auto-pick the next revision. Set this to re-publish a version after a packaging-only fix, without waiting for a new upstream tree-sitter release.'
required: false
schedule:
# Daily check for a new upstream tree-sitter release. No-ops (skips the
# rest of the workflow) if we already published a release for the
# current upstream version.
- cron: "17 6 * * *"
permissions:
contents: write
jobs:
determine-version:
runs-on: ubuntu-latest
outputs:
ts_tag: ${{ steps.version.outputs.ts_tag }}
release_exists: ${{ steps.check.outputs.exists }}
deb_revision: ${{ steps.revision.outputs.revision }}
release_tag: ${{ steps.revision.outputs.tag }}
steps:
- name: Determine target version
id: version
run: |
if [ -n "${{ github.event.inputs.ts_version }}" ]; then
echo "ts_tag=${{ github.event.inputs.ts_version }}" >> "$GITHUB_OUTPUT"
else
tag="$(curl -fsSL https://api.github.com/repos/tree-sitter/tree-sitter/releases/latest | jq -r .tag_name)"
echo "ts_tag=$tag" >> "$GITHUB_OUTPUT"
fi
# Only the scheduled run auto-skips already-published versions: its job
# is just to notice new upstream tree-sitter releases. A manual dispatch
# is always an explicit request to publish, so it proceeds even when a
# release for this version already exists -- that's how you publish a
# packaging-only fix under a bumped deb_revision without waiting for a
# new upstream version.
- name: Check whether this version already has a release
id: check
if: github.event_name == 'schedule'
env:
GH_TOKEN: ${{ github.token }}
TS_TAG: ${{ steps.version.outputs.ts_tag }}
run: |
if gh release list --repo "${{ github.repository }}" --limit 500 --json tagName \
--jq '.[].tagName' \
| grep -qE "^${TS_TAG//./\\.}(-[0-9]+)?\$"; then
echo "A release for $TS_TAG already exists, nothing to do."
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi
- name: Determine package revision
id: revision
env:
GH_TOKEN: ${{ github.token }}
TS_TAG: ${{ steps.version.outputs.ts_tag }}
INPUT_REVISION: ${{ github.event.inputs.deb_revision }}
run: |
if [ -n "$INPUT_REVISION" ]; then
revision="$INPUT_REVISION"
else
max=0
while IFS= read -r tag; do
[ -z "$tag" ] && continue
if [ "$tag" = "$TS_TAG" ]; then
rev=1
elif [[ "$tag" =~ ^${TS_TAG//./\\.}-([0-9]+)$ ]]; then
rev="${BASH_REMATCH[1]}"
else
continue
fi
if [ "$rev" -gt "$max" ]; then
max="$rev"
fi
done < <(gh release list --repo "${{ github.repository }}" --limit 500 --json tagName --jq '.[].tagName')
revision=$((max + 1))
fi
echo "revision=$revision" >> "$GITHUB_OUTPUT"
echo "tag=${TS_TAG}-${revision}" >> "$GITHUB_OUTPUT"
build:
needs: determine-version
if: needs.determine-version.outputs.release_exists != 'true'
# The arm64 leg needs to run on a native arm64 machine: build-deb.sh uses
# `ldd` to resolve the tree-sitter binary's shared-library dependencies,
# which requires actually executing the target binary against real
# arm64 system libraries. Under QEMU emulation on an amd64 host, those
# libraries aren't present at the paths the arm64 dynamic linker
# searches, so dependency detection would silently come back wrong.
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
strategy:
matrix:
arch: [amd64, arm64]
steps:
- uses: actions/checkout@v7
- name: Build .deb
run: scripts/build-deb.sh "${{ needs.determine-version.outputs.ts_tag }}" "${{ matrix.arch }}" "${{ needs.determine-version.outputs.deb_revision }}"
- uses: actions/upload-artifact@v7
with:
name: deb-${{ matrix.arch }}
path: dist/*.deb
if-no-files-found: error
test:
needs: [determine-version, build]
if: needs.determine-version.outputs.release_exists != 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# ubuntu:22.04, debian:11, and debian:12 are excluded: tree-sitter
# releases since v0.25.0 require GLIBC >= 2.39 (a known,
# still-unresolved upstream issue: tree-sitter/tree-sitter#4174),
# which those releases don't ship. The .deb installs there but the
# binary fails to run -- a hard binary incompatibility, not
# something packaging can fix.
distro:
- "ubuntu:24.04"
- "ubuntu:26.04"
- "debian:13"
arch: [amd64, arm64]
steps:
- uses: actions/checkout@v7
- uses: actions/download-artifact@v8
with:
pattern: deb-*
path: dist
merge-multiple: true
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
with:
platforms: arm64
- name: Install / smoke-test / uninstall on ${{ matrix.distro }} (${{ matrix.arch }})
env:
TS_TAG: ${{ needs.determine-version.outputs.ts_tag }}
DEB_REVISION: ${{ needs.determine-version.outputs.deb_revision }}
run: |
version_number="${TS_TAG#v}"
deb_version="${version_number}-${DEB_REVISION}"
docker run --rm --platform "linux/${{ matrix.arch }}" \
-v "$PWD:/w" -w /w "${{ matrix.distro }}" \
./scripts/test-deb.sh "./dist/tree-sitter-cli_${deb_version}_${{ matrix.arch }}.deb" "$version_number"
release:
needs: [determine-version, build, test]
if: needs.determine-version.outputs.release_exists != 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/download-artifact@v8
with:
pattern: deb-*
path: dist
merge-multiple: true
- name: Checksums
working-directory: dist
run: sha256sum *.deb > SHA256SUMS
- name: Create / update GitHub release
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
TAG="${{ needs.determine-version.outputs.release_tag }}"
TS_TAG="${{ needs.determine-version.outputs.ts_tag }}"
# gh release create auto-creates the tag (from the current
# default-branch tip) if it doesn't already exist, so no separate
# git tag/push step is needed here.
if gh release view "${TAG}" --repo "${GITHUB_REPOSITORY}" >/dev/null 2>&1; then
gh release upload "${TAG}" dist/*.deb dist/SHA256SUMS --repo "${GITHUB_REPOSITORY}" --clobber
else
gh release create "${TAG}" dist/*.deb dist/SHA256SUMS \
--repo "${GITHUB_REPOSITORY}" \
--title "tree-sitter-cli ${TAG#v}" \
--notes "Repackage of the official tree-sitter CLI binary release [${TS_TAG}](https://github.com/tree-sitter/tree-sitter/releases/tag/${TS_TAG}) as a .deb for Debian/Ubuntu (amd64, arm64)."
fi