-
-
Notifications
You must be signed in to change notification settings - Fork 136
190 lines (175 loc) · 7.43 KB
/
vpm-publish.yml
File metadata and controls
190 lines (175 loc) · 7.43 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
name: VPM Publish
on:
schedule:
# Saturday 14:00 UTC
- cron: '0 14 * * 6'
workflow_dispatch:
inputs:
tag_override:
description: 'Tag override (default: vpm-YYYY-Www.RUN). Required when stable=true.'
required: false
stable:
description: 'Cut a stable (non-prerelease) release. Uses package.json versions as-is, no dev suffix.'
type: boolean
default: false
# Serialize publishes so cron + manual dispatch can never race on the vpm branch.
# Each run produces its own tag (vpm-YYYY-Www.RUN) so release-tag races aren't
# possible, but the shared vpm branch still needs ordering.
concurrency:
group: vpm-publish
cancel-in-progress: false
permissions:
contents: write # release creation + push to the vpm branch
env:
VPM_BRANCH: vpm
VPM_INDEX_FILE: vpm-repo.json
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Compute tag and dev suffix
id: meta
env:
TAG_OVERRIDE: ${{ inputs.tag_override }}
RUN_NUMBER: ${{ github.run_number }}
STABLE: ${{ inputs.stable }}
run: |
set -euo pipefail
if [ "${STABLE:-false}" = "true" ]; then
# Stable mode: package.json versions are shipped as-is. A tag
# override is mandatory so stable runs don't collide with the
# weekly cron's vpm-YYYY-Www.RUN namespace.
if [ -z "${TAG_OVERRIDE}" ]; then
echo "::error::stable=true requires tag_override (e.g. v1.2.3)"
exit 1
fi
TAG="${TAG_OVERRIDE}"
SUFFIX=""
else
# Weekly/dev mode: suffix derived from week + run number,
# deterministic for re-runs of the same workflow run, fresh for
# each new run. Maintainers don't bump package.json — the cron
# snapshot does it for them.
TAG="${TAG_OVERRIDE:-vpm-$(date -u +%G-W%V).${RUN_NUMBER}}"
SUFFIX="dev.$(date -u +%G.W%V).${RUN_NUMBER}"
fi
{
echo "tag=$TAG"
echo "suffix=$SUFFIX"
echo "stable=${STABLE:-false}"
} >> "$GITHUB_OUTPUT"
# Stage the previous index for update-index to merge into.
# branch + non-empty file → normal merge
# branch + missing/empty file → ABORT (corruption / accidental delete)
# branch absent → first-run bootstrap
- name: Stage previous index
id: stage
run: |
set -euo pipefail
mkdir -p prev
if git ls-remote --exit-code --heads origin "$VPM_BRANCH" >/dev/null 2>&1; then
git fetch --depth=1 origin "$VPM_BRANCH"
git show "FETCH_HEAD:$VPM_INDEX_FILE" > "prev/$VPM_INDEX_FILE" 2>/dev/null \
|| { echo "::error::$VPM_BRANCH branch exists but $VPM_INDEX_FILE is missing on it"; exit 1; }
[ -s "prev/$VPM_INDEX_FILE" ] \
|| { echo "::error::$VPM_INDEX_FILE on $VPM_BRANCH is empty"; exit 1; }
echo "first_run=false" >> "$GITHUB_OUTPUT"
else
: > "prev/$VPM_INDEX_FILE"
echo "first_run=true" >> "$GITHUB_OUTPUT"
echo "First run: $VPM_BRANCH branch does not exist yet."
fi
- name: Build packages
env:
DEV_SUFFIX: ${{ steps.meta.outputs.suffix }}
run: python3 .github/scripts/vpmpackagegen.py build --dev-suffix "$DEV_SUFFIX" --out out
# Merge per-package metadata into the prior index. The added.txt lists
# zip filenames of newly-added entries — empty only if the workflow run
# is being re-attempted with the same run_number on the same source
# state (every entry already in the index from the prior attempt). In
# the normal weekly path, every package gets a fresh dev-suffixed
# version so all 29 are added.
- name: Generate new index
id: index
env:
REPO: ${{ github.repository }}
SERVER_URL: ${{ github.server_url }}
TAG: ${{ steps.meta.outputs.tag }}
STABLE: ${{ steps.meta.outputs.stable }}
run: |
set -euo pipefail
BASE_URL="${SERVER_URL}/${REPO}/releases/download/${TAG}"
SELF_URL="https://raw.githubusercontent.com/${REPO}/${VPM_BRANCH}/${VPM_INDEX_FILE}"
echo "::notice title=VPM Repo URL::$SELF_URL"
python3 .github/scripts/vpmpackagegen.py update-index \
--require-superset \
--self-url "$SELF_URL" \
--added-list added.txt \
"prev/$VPM_INDEX_FILE" \
"$BASE_URL" \
out/meta > new-index.json
if [ -s added.txt ]; then
count=$(wc -l < added.txt)
echo "Added ${count} package version(s)."
echo "has_changes=true" >> "$GITHUB_OUTPUT"
{
echo "### Added packages (${count})"
echo
while IFS=$'\t' read -r name version _zip; do
echo "- \`${name}\` @ \`${version}\`"
done < added.txt
} > release-body.md
cat release-body.md >> "$GITHUB_STEP_SUMMARY"
else
if [ "${STABLE}" = "true" ]; then
echo "::error::stable=true but no new package versions were added — bump versions in package.json or use a fresh tag."
exit 1
fi
echo "Re-run with no new versions; release and push will be skipped."
echo "has_changes=false" >> "$GITHUB_OUTPUT"
fi
# Upload zips BEFORE pushing the index so the index never references
# a missing asset. Re-runs are safe — the action uploads to the
# existing release if the tag already exists, and the build is
# deterministic so identical bytes produce identical asset content.
- name: Create release and upload zips
if: steps.index.outputs.has_changes == 'true'
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.meta.outputs.tag }}
name: VPM ${{ steps.meta.outputs.tag }}
body_path: release-body.md
prerelease: ${{ steps.meta.outputs.stable != 'true' }}
files: out/artifacts/*.zip
fail_on_unmatched_files: true
# Push the new index to the vpm branch in a fresh clone so we don't
# entangle the main checkout's worktree state.
- name: Publish to vpm branch
if: steps.index.outputs.has_changes == 'true'
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
TAG: ${{ steps.meta.outputs.tag }}
FIRST_RUN: ${{ steps.stage.outputs.first_run }}
run: |
set -euo pipefail
git config --global user.name "github-actions[bot]"
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
URL="https://x-access-token:${GH_TOKEN}@github.com/${REPO}.git"
if [ "$FIRST_RUN" = "true" ]; then
git init -q -b "$VPM_BRANCH" vpm-pub
git -C vpm-pub remote add origin "$URL"
else
git clone -q --depth 1 --branch "$VPM_BRANCH" --single-branch "$URL" vpm-pub
fi
cp new-index.json "vpm-pub/$VPM_INDEX_FILE"
cd vpm-pub
git add "$VPM_INDEX_FILE"
git commit -q -m "vpm: $TAG"
git push -u origin "$VPM_BRANCH"