@krx3d/tizentube2 1.30.710 → 1.30.730

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,136 @@
1
+ name: Sync from GitHub
2
+
3
+ # Brings whatever changed on github.com/KrX3D/TizenTube into this mirror as a
4
+ # single pull request, and leaves that pull request to be reviewed and merged
5
+ # rather than writing to main itself.
6
+ #
7
+ # One pull request, not one per run: the sync branch is reused and force-moved
8
+ # to GitHub's current tip, and a run that finds the pull request already open
9
+ # updates the branch and says so instead of opening another.
10
+ #
11
+ # Lives in .gitea/workflows rather than .github/workflows deliberately. The
12
+ # second is synced from GitHub and holds that repository's own workflows —
13
+ # including the one that publishes to npm, which must never run here. See
14
+ # runs-on below for how that is kept from happening.
15
+ #
16
+ # It is nonetheless committed on GitHub as well, where it does nothing: GitHub
17
+ # Actions reads .github/workflows and only that, so this file is never parsed
18
+ # there and never appears in the Actions tab. It is here so that the mirror
19
+ # holds no commit GitHub lacks. When it lived only on the mirror, the mirror's
20
+ # main was permanently one commit ahead, so every sync was a real merge and
21
+ # left two more merge commits behind it. With the file on both sides the two
22
+ # branches are identical and each sync fast-forwards.
23
+
24
+ on:
25
+ schedule:
26
+ # Hourly, offset off the hour so it does not land with everything else.
27
+ - cron: '17 * * * *'
28
+ workflow_dispatch:
29
+
30
+ jobs:
31
+ sync:
32
+ # Deliberately not ubuntu-latest. This repository carries the GitHub
33
+ # workflows too, and they all ask for ubuntu-latest — so a runner
34
+ # registered with this label alone can run this workflow and none of
35
+ # those. The Actions tab can also disable them one by one, which is worth
36
+ # doing as well; this is the part that holds without anyone remembering.
37
+ runs-on: gitea-sync
38
+ steps:
39
+ - name: Bring GitHub's changes onto the sync branch and open one pull request
40
+ env:
41
+ # A personal access token with write access to this repository.
42
+ # Falls back to the token Gitea Actions provides, which is enough to
43
+ # push but may not be allowed to open a pull request depending on the
44
+ # instance's settings — hence the preference.
45
+ SYNC_TOKEN: ${{ secrets.SYNC_TOKEN }}
46
+ AUTO_TOKEN: ${{ secrets.GITEA_TOKEN }}
47
+ SERVER_URL: ${{ github.server_url }}
48
+ REPO: ${{ github.repository }}
49
+ SOURCE: https://github.com/KrX3D/TizenTube.git
50
+ SYNC_BRANCH: github-sync
51
+ BASE_BRANCH: main
52
+ run: |
53
+ set -eu
54
+
55
+ TOKEN="${SYNC_TOKEN:-${AUTO_TOKEN:-}}"
56
+ if [ -z "$TOKEN" ]; then
57
+ echo "No token available. Add a repository secret named SYNC_TOKEN"
58
+ echo "holding a personal access token with write access."
59
+ exit 1
60
+ fi
61
+
62
+ # The scheme is kept rather than assumed: this instance is plain http
63
+ # today and may not be tomorrow.
64
+ case "$SERVER_URL" in
65
+ https://*) SCHEME=https; HOSTPART="${SERVER_URL#https://}" ;;
66
+ *) SCHEME=http; HOSTPART="${SERVER_URL#http://}" ;;
67
+ esac
68
+ HOSTPART="${HOSTPART%/}"
69
+ PUSH_URL="$SCHEME://$TOKEN@$HOSTPART/$REPO.git"
70
+ API="$SCHEME://$HOSTPART/api/v1/repos/$REPO"
71
+
72
+ # Only the base branch: this mirror carries 154 branches and cloning
73
+ # all of them to compare one would cost minutes per run.
74
+ git clone --quiet --single-branch --branch "$BASE_BRANCH" "$PUSH_URL" work
75
+ cd work
76
+ git config user.name "Gitea Actions"
77
+ git config user.email "actions@local"
78
+
79
+ git remote add github "$SOURCE"
80
+ git fetch --quiet --tags github "$BASE_BRANCH"
81
+ TIP=$(git rev-parse "github/$BASE_BRANCH")
82
+ echo "GitHub $BASE_BRANCH is at $TIP"
83
+
84
+ # Already contained: nothing changed since the last merge, so there is
85
+ # nothing to open a pull request about.
86
+ if git merge-base --is-ancestor "$TIP" "origin/$BASE_BRANCH"; then
87
+ echo "This mirror already contains it. Nothing to do."
88
+ exit 0
89
+ fi
90
+
91
+ AHEAD=$(git rev-list --count "origin/$BASE_BRANCH..$TIP")
92
+ echo "$AHEAD commit(s) to bring over"
93
+
94
+ # Force, because the branch is a pointer at GitHub's tip and nothing
95
+ # else: anything that was on it has either been merged or superseded.
96
+ git push --quiet --force "$PUSH_URL" "$TIP:refs/heads/$SYNC_BRANCH"
97
+ # Tags come along for free and are worth having in a mirror.
98
+ git push --quiet --tags "$PUSH_URL" || echo "(tags unchanged or rejected, continuing)"
99
+
100
+ # One pull request: if one is already open from this branch, the push
101
+ # above has just updated it.
102
+ OPEN=$(curl -sf -H "Authorization: token $TOKEN" \
103
+ "$API/pulls?state=open&limit=50" \
104
+ | tr '}' '\n' | grep -c "\"ref\":\"$SYNC_BRANCH\"" || true)
105
+ if [ "${OPEN:-0}" -gt 0 ]; then
106
+ echo "A pull request from $SYNC_BRANCH is already open; its branch now points at $TIP."
107
+ exit 0
108
+ fi
109
+
110
+ # The commit list goes in the body, escaped for JSON and joined with
111
+ # literal newline escapes so no multi-line quoting is needed.
112
+ LIST=$(git log --oneline --no-decorate "origin/$BASE_BRANCH..$TIP" \
113
+ | head -40 \
114
+ | sed 's/\\/\\\\/g; s/"/\\"/g' \
115
+ | sed ':a;N;$!ba;s/\n/\\n/g')
116
+ TITLE="Sync $AHEAD commit(s) from GitHub"
117
+ BODY="Brings $AHEAD commit(s) from github.com/KrX3D/TizenTube up to \`$TIP\`.\\n\\nThis mirror is a backup; merging keeps it current without touching GitHub.\\n\\n$LIST"
118
+
119
+ printf '{"head":"%s","base":"%s","title":"%s","body":"%s"}' \
120
+ "$SYNC_BRANCH" "$BASE_BRANCH" "$TITLE" "$BODY" > /tmp/pr.json
121
+
122
+ HTTP=$(curl -s -o /tmp/pr-out.json -w '%{http_code}' \
123
+ -X POST -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
124
+ "$API/pulls" --data @/tmp/pr.json)
125
+ echo "create pull request -> HTTP $HTTP"
126
+ if [ "$HTTP" = "409" ]; then
127
+ echo "Gitea says such a pull request already exists; the branch is updated."
128
+ exit 0
129
+ fi
130
+ if [ "$HTTP" != "201" ]; then
131
+ head -c 400 /tmp/pr-out.json
132
+ echo
133
+ echo "The branch $SYNC_BRANCH is updated regardless; the pull request can be opened by hand."
134
+ exit 1
135
+ fi
136
+ echo "Opened a pull request for $AHEAD commit(s)."
@@ -119,6 +119,8 @@ on:
119
119
  paths-ignore:
120
120
  - 'dist/**'
121
121
  - 'package.json'
122
+ # Read by the Gitea mirror, ignored by GitHub Actions entirely.
123
+ - '.gitea/**'
122
124
  push:
123
125
  branches:
124
126
  - main
@@ -130,6 +132,11 @@ on:
130
132
  - 'LICENSE'
131
133
  - 'AGENTS.md'
132
134
  - 'README.md'
135
+ # The mirror's own workflow lives here. GitHub never runs it, and it is
136
+ # not in the published package, so a change to it must not publish a new
137
+ # version — which is exactly what it did once: #827 touched nothing but
138
+ # .gitea/workflows/sync-from-github.yml and bumped 1.30.710 to 1.30.720.
139
+ - '.gitea/**'
133
140
  - 'package.json'
134
141
  - 'tizen.log'
135
142
  - 'dist/**'
@@ -222,56 +229,56 @@ jobs:
222
229
  patch = 0;
223
230
  }
224
231
 
225
- // npm refuses forever to reuse a version number that was once
226
- // published and later unpublished. The cleanup step in this same
227
- // workflow unpublishes old releases, so 780 of the 857 numbers this
228
- // package has ever used are permanently burned. Whenever
229
- // package.json drops back into that range - a revert, a bad merge,
230
- // an upstream sync - every run then fails with
231
- // E400 Cannot publish over previously published version "x.y.z"
232
- // and, because the bump is committed and pushed BEFORE publishing,
233
- // main is left pinned on the burned number so every later run fails
234
- // the same way. That is exactly what happened twice at 1.16.10.
235
- //
236
- // The registry time map lists every version ever used, live or not,
237
- // so skipping past them makes the bump self-correcting.
238
- //
239
- // Wrapped in an async IIFE on purpose: this script is fed to `node -`
240
- // on stdin, and a top-level await next to the require() above makes
241
- // Node fail the whole script with ERR_AMBIGUOUS_MODULE_SYNTAX.
242
- (async () => {
243
- let used = null;
244
- try {
245
- const res = await fetch('https://registry.npmjs.org/' + pkg.name);
246
- if (res.ok) {
247
- const meta = await res.json();
248
- const isSemver = (k) => /^[0-9]+[.][0-9]+[.][0-9]+$/.test(k);
249
- used = new Set(Object.keys(meta.time || {}).filter(isSemver));
250
- }
251
- } catch (e) {
252
- // Registry unreachable: fall through to the plain bump rather
253
- // than blocking a release. A real collision still fails loudly
254
- // at publish.
255
- used = null;
256
- }
257
-
258
- let newVer = `${major}.${minor}.${patch}`;
259
- if (used) {
260
- const firstChoice = newVer;
261
- let guard = 0;
262
- while (used.has(newVer) && guard++ < 500) {
263
- patch += 10;
264
- if (patch >= 1000) { minor += 1; patch = 0; }
265
- newVer = `${major}.${minor}.${patch}`;
266
- }
267
- if (used.has(newVer)) throw new Error('No unused version found near ' + ver);
268
- if (newVer !== firstChoice) console.log('Skipped burned version numbers: ' + firstChoice + ' -> ' + newVer);
269
- }
270
-
271
- pkg.version = newVer;
272
- fs.writeFileSync(path, JSON.stringify(pkg, null, 2) + String.fromCharCode(10), 'utf8');
273
- console.log('Bumped version: ' + ver + ' -> ' + newVer);
274
- })();
232
+ // npm refuses forever to reuse a version number that was once
233
+ // published and later unpublished. The cleanup step in this same
234
+ // workflow unpublishes old releases, so 780 of the 857 numbers this
235
+ // package has ever used are permanently burned. Whenever
236
+ // package.json drops back into that range - a revert, a bad merge,
237
+ // an upstream sync - every run then fails with
238
+ // E400 Cannot publish over previously published version "x.y.z"
239
+ // and, because the bump is committed and pushed BEFORE publishing,
240
+ // main is left pinned on the burned number so every later run fails
241
+ // the same way. That is exactly what happened twice at 1.16.10.
242
+ //
243
+ // The registry time map lists every version ever used, live or not,
244
+ // so skipping past them makes the bump self-correcting.
245
+ //
246
+ // Wrapped in an async IIFE on purpose: this script is fed to `node -`
247
+ // on stdin, and a top-level await next to the require() above makes
248
+ // Node fail the whole script with ERR_AMBIGUOUS_MODULE_SYNTAX.
249
+ (async () => {
250
+ let used = null;
251
+ try {
252
+ const res = await fetch('https://registry.npmjs.org/' + pkg.name);
253
+ if (res.ok) {
254
+ const meta = await res.json();
255
+ const isSemver = (k) => /^[0-9]+[.][0-9]+[.][0-9]+$/.test(k);
256
+ used = new Set(Object.keys(meta.time || {}).filter(isSemver));
257
+ }
258
+ } catch (e) {
259
+ // Registry unreachable: fall through to the plain bump rather
260
+ // than blocking a release. A real collision still fails loudly
261
+ // at publish.
262
+ used = null;
263
+ }
264
+
265
+ let newVer = `${major}.${minor}.${patch}`;
266
+ if (used) {
267
+ const firstChoice = newVer;
268
+ let guard = 0;
269
+ while (used.has(newVer) && guard++ < 500) {
270
+ patch += 10;
271
+ if (patch >= 1000) { minor += 1; patch = 0; }
272
+ newVer = `${major}.${minor}.${patch}`;
273
+ }
274
+ if (used.has(newVer)) throw new Error('No unused version found near ' + ver);
275
+ if (newVer !== firstChoice) console.log('Skipped burned version numbers: ' + firstChoice + ' -> ' + newVer);
276
+ }
277
+
278
+ pkg.version = newVer;
279
+ fs.writeFileSync(path, JSON.stringify(pkg, null, 2) + String.fromCharCode(10), 'utf8');
280
+ console.log('Bumped version: ' + ver + ' -> ' + newVer);
281
+ })();
275
282
  NODE
276
283
 
277
284
  - name: Show current version (old -> new)
@@ -413,35 +420,35 @@ jobs:
413
420
  # --------------------
414
421
  # PUBLISH
415
422
  # --------------------
416
- # --------------------
417
- # Guard: never publish a tarball whose dist does not match its version
418
- # --------------------
419
- # Confirmed on 1.30.0: the tarball carried package.json 1.30.0 alongside a
420
- # dist/userScript.js stamped 1.16.10, so every TV pulling the CDN got a
421
- # build five releases old while the settings menu reported the new number.
422
- #
423
- # It came from re-running a failed run. A re-run replays the ORIGINAL
424
- # commit, so it bumped and built at the old version, and then the
425
- # `git rebase origin/main` below took main's newer package.json while
426
- # keeping the dist it had already built. package.json and dist are only
427
- # guaranteed to agree when a run builds them together, and nothing checked
428
- # that they still did by the time publish happened.
429
- - name: Verify dist matches package.json version
430
- if: success()
431
- run: |
432
- set -euo pipefail
433
- VER="$(node -p "require('./package.json').version")"
434
- echo "package.json version: ${VER}"
435
- for f in dist/userScript.js dist/service.js; do
436
- test -f "$f" || { echo "::error::${f} is missing"; exit 1; }
437
- done
438
- if ! grep -qF "\"${VER}\"" dist/userScript.js; then
439
- FOUND="$(grep -aoE '\"[0-9]+\.[0-9]+\.[0-9]+\"' dist/userScript.js | sort -u | head -3 | xargs echo)"
440
- echo "::error::dist/userScript.js was not built from this version. package.json says ${VER}; the bundle contains ${FOUND:-no version string}. Re-run the workflow from a fresh push rather than re-running an old run, so the bump and the build happen together."
441
- exit 1
442
- fi
443
- echo "dist/userScript.js carries ${VER}"
444
-
423
+ # --------------------
424
+ # Guard: never publish a tarball whose dist does not match its version
425
+ # --------------------
426
+ # Confirmed on 1.30.0: the tarball carried package.json 1.30.0 alongside a
427
+ # dist/userScript.js stamped 1.16.10, so every TV pulling the CDN got a
428
+ # build five releases old while the settings menu reported the new number.
429
+ #
430
+ # It came from re-running a failed run. A re-run replays the ORIGINAL
431
+ # commit, so it bumped and built at the old version, and then the
432
+ # `git rebase origin/main` below took main's newer package.json while
433
+ # keeping the dist it had already built. package.json and dist are only
434
+ # guaranteed to agree when a run builds them together, and nothing checked
435
+ # that they still did by the time publish happened.
436
+ - name: Verify dist matches package.json version
437
+ if: success()
438
+ run: |
439
+ set -euo pipefail
440
+ VER="$(node -p "require('./package.json').version")"
441
+ echo "package.json version: ${VER}"
442
+ for f in dist/userScript.js dist/service.js; do
443
+ test -f "$f" || { echo "::error::${f} is missing"; exit 1; }
444
+ done
445
+ if ! grep -qF "\"${VER}\"" dist/userScript.js; then
446
+ FOUND="$(grep -aoE '\"[0-9]+\.[0-9]+\.[0-9]+\"' dist/userScript.js | sort -u | head -3 | xargs echo)"
447
+ echo "::error::dist/userScript.js was not built from this version. package.json says ${VER}; the bundle contains ${FOUND:-no version string}. Re-run the workflow from a fresh push rather than re-running an old run, so the bump and the build happen together."
448
+ exit 1
449
+ fi
450
+ echo "dist/userScript.js carries ${VER}"
451
+
445
452
  - name: Publish package to npm
446
453
  if: success()
447
454
  id: publish_npm
@@ -921,21 +928,32 @@ jobs:
921
928
 
922
929
  # The purge above is fire-and-forget: jsDelivr answers "pending" and that
923
930
  # is the end of it. Nothing checked the result, and a capture showed what
924
- # that costs — the unversioned URL, which is the one the TV actually
925
- # fetches, kept serving the previous release for hours after a publish
926
- # (x-cache HIT, age 15039, the bundle inside it a version behind). Every
927
- # TV was loading that, so a diagnostic merged that afternoon was simply
928
- # not running, and its absence read as the feature being broken.
931
+ # that costs — a publish whose bundle did not reach the TVs for hours,
932
+ # which read as the new feature being broken rather than as never having
933
+ # arrived.
929
934
  #
930
- # So the last word belongs to the URL the TV uses, read the way the TV
931
- # reads it. The version string has to be inside the bundle itself: a
932
- # 200 proves nothing when the stale object is also a 200.
935
+ # What is worth checking changed when injector.js started pinning. This
936
+ # step used to read the unversioned path and fail the build over it,
937
+ # because that was the URL the TV fetched. The injector now asks the npm
938
+ # registry for the version and fetches an immutable @version path, and
939
+ # falls back to the unversioned URL only if the registry cannot be
940
+ # reached. So the two are no longer equally serious:
933
941
  #
934
- # One caveat worth stating: jsDelivr serves from many points of presence
935
- # and this checks the one that answers here. It cannot prove every edge
936
- # is current. What it does prove is that the origin resolves this
937
- # package's unversioned path to the version just published — which is the
938
- # failure that was actually seen, and the one that affects every edge.
942
+ # @version path what every TV actually loads. Immutable, so if it
943
+ # does not carry this version then the publish itself
944
+ # is broken, not a cache. Hard failure.
945
+ #
946
+ # unversioned the fallback, and jsDelivr caches its resolution of
947
+ # alias "latest" for twelve hours (s-maxage=43200). It lags a
948
+ # publish by design, and a purge issued before npm's
949
+ # latest has propagated makes it worse by re-caching
950
+ # the old answer. A warning: failing here blocks the
951
+ # .wgt release over something that reaches no TV.
952
+ #
953
+ # Either way the version string has to be inside the bundle itself — a
954
+ # 200 proves nothing when the stale object is also a 200. jsDelivr serves
955
+ # from many points of presence and this reads whichever answers here, so
956
+ # it cannot prove every edge is current.
939
957
  - name: Verify the CDN serves this version
940
958
  if: steps.confirm_publish.outputs.confirmed == 'true'
941
959
  env:
@@ -943,32 +961,72 @@ jobs:
943
961
  run: |
944
962
  set -euo pipefail
945
963
  VER=$(cat /tmp/current_version.txt)
946
- URL="https://cdn.jsdelivr.net/npm/${PKG}/dist/userScript.js"
947
- echo "Checking ${URL} for ${VER} ..."
964
+ PINNED="https://cdn.jsdelivr.net/npm/${PKG}@${VER}/dist/userScript.js"
965
+ ALIAS="https://cdn.jsdelivr.net/npm/${PKG}/dist/userScript.js"
966
+
967
+ # Two things this got wrong before, both of which turned a correct
968
+ # verdict into an unreadable one.
969
+ #
970
+ # -a, because the bundle is minified and counts as binary: without it
971
+ # grep writes "binary file matches" to stderr and no match to stdout,
972
+ # which is why a run that had correctly found the alias stale could
973
+ # only report "an unknown version".
974
+ #
975
+ # And the major from this version rather than any three numbers. A
976
+ # bundle carries its dependencies' versions too, so the generic
977
+ # pattern plus "sort | tail -1" reported the highest-sorting of those
978
+ # — measured: 8.8.278 for a bundle whose own version was 1.30.710.
979
+ # Anchored to the major there is exactly one match, which is the
980
+ # package's own. All of them are printed rather than the last, so a
981
+ # bundle that somehow carried two cannot be described as having one.
982
+ MAJOR="${VER%%.*}"
983
+ served_version() {
984
+ grep -aoE "${MAJOR}\.[0-9]+\.[0-9]+" "$1" | sort -u | tr '\n' ' ' || true
985
+ }
948
986
 
949
- for i in $(seq 1 10); do
950
- if curl -fsSL -H 'Cache-Control: no-cache' "$URL" -o /tmp/cdn_bundle.js; then
951
- if grep -q "$VER" /tmp/cdn_bundle.js; then
952
- echo "attempt ${i}: the CDN serves ${VER}."
987
+ echo "== the path every TV loads: ${PINNED}"
988
+ if ! curl -fsSL -H 'Cache-Control: no-cache' "$PINNED" -o /tmp/cdn_pinned.js; then
989
+ echo "::error::The CDN will not serve ${PINNED} at all, so the publish did not land."
990
+ exit 1
991
+ fi
992
+ if ! grep -aq "$VER" /tmp/cdn_pinned.js; then
993
+ echo "::error::${PINNED} exists but the bundle in it says $(served_version /tmp/cdn_pinned.js), not ${VER}. An immutable path cannot go stale, so this is a broken publish rather than a cache."
994
+ exit 1
995
+ fi
996
+ echo "the pinned path serves ${VER} — which is what injector.js injects."
997
+
998
+ # Then the alias, which is allowed to lag.
999
+ echo "== the fallback alias: ${ALIAS}"
1000
+ for i in $(seq 1 6); do
1001
+ if curl -fsSL -H 'Cache-Control: no-cache' "$ALIAS" -o /tmp/cdn_alias.js; then
1002
+ if grep -aq "$VER" /tmp/cdn_alias.js; then
1003
+ echo "attempt ${i}: the alias serves ${VER} too, so there is nothing left to wait for."
953
1004
  exit 0
954
1005
  fi
955
- FOUND=$(grep -oE '[0-9]+\.[0-9]+\.[0-9]+' /tmp/cdn_bundle.js | sort -u | tail -1 || true)
956
- echo "attempt ${i}: still serving ${FOUND:-an unknown version}"
1006
+ echo "attempt ${i}: the alias still serves $(served_version /tmp/cdn_alias.js)"
957
1007
  else
958
- echo "attempt ${i}: the CDN could not be read"
1008
+ echo "attempt ${i}: the alias could not be read"
959
1009
  fi
960
1010
 
961
- # Ask again rather than only waiting: the first purge can land
962
- # before npm's latest has propagated, in which case jsDelivr
963
- # re-resolves the old version and caches that instead.
964
- curl -s -X POST -H 'Content-Type: application/json' \
1011
+ # Ask again rather than only waiting, and this time watch the
1012
+ # request: the purge API is asynchronous and answers "pending", so
1013
+ # the previous blind sleep could not tell a finished purge from a
1014
+ # queued one.
1015
+ PURGE=$(curl -s -X POST -H 'Content-Type: application/json' \
965
1016
  --data "{\"path\":[\"/npm/${PKG}/dist/userScript.js\",\"/npm/${PKG}/dist/service.js\",\"/npm/${PKG}@latest/dist/userScript.js\",\"/npm/${PKG}@latest/dist/service.js\"]}" \
966
- https://purge.jsdelivr.net/ > /dev/null || true
967
- sleep 20
1017
+ https://purge.jsdelivr.net/ || true)
1018
+ PURGE_ID=$(printf '%s' "$PURGE" | sed -n 's/.*"id"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
1019
+ echo " purge requested: ${PURGE_ID:-no id returned}"
1020
+ for _ in $(seq 1 5); do
1021
+ sleep 6
1022
+ [ -n "$PURGE_ID" ] || break
1023
+ STATUS=$(curl -s "https://purge.jsdelivr.net/status/${PURGE_ID}" | sed -n 's/.*"status"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
1024
+ echo " purge ${PURGE_ID}: ${STATUS:-unknown}"
1025
+ [ "$STATUS" = "pending" ] || break
1026
+ done
968
1027
  done
969
1028
 
970
- echo "::error::The CDN is still not serving ${VER} at ${URL} after ten attempts. Every TV will keep loading the previous bundle until this clears, which looks exactly like the new build not working. Purge it by hand (https://www.jsdelivr.com/tools/purge) or re-run this workflow."
971
- exit 1
1029
+ echo "::warning::${ALIAS} is still serving $(served_version /tmp/cdn_alias.js) rather than ${VER}. That is the fallback path only: injector.js pins to ${PINNED}, verified above, and uses the alias just when the npm registry is unreachable. jsDelivr caches its idea of \"latest\" for up to twelve hours and this clears on its own; purge by hand at https://www.jsdelivr.com/tools/purge to hurry it."
972
1030
 
973
1031
  - name: Cache purge complete
974
1032
  if: steps.confirm_publish.outputs.confirmed == 'true'
@@ -82,6 +82,12 @@ on:
82
82
  workflow_run:
83
83
  workflows: ['Build, publish and cleanup old npm versions']
84
84
  types: [completed]
85
+ # The branch the triggering run was on, which for a pull-request build is
86
+ # the feature branch. Without this, every pull request started a run here
87
+ # that the job-level `if` below immediately skipped: real runs, listed in
88
+ # the Actions tab, queued and accounted for, that could never do anything.
89
+ # Filtering at the trigger means they are never created.
90
+ branches: ['main']
85
91
  push:
86
92
  tags:
87
93
  - 'v*.*.*'
@@ -100,8 +106,10 @@ jobs:
100
106
  # Only proceed on a successful npm-publish run that was itself triggered by
101
107
  # a push to main (build-publish-cleanup.yml's job is skipped entirely for
102
108
  # pull_request runs, which can still report an overall "success" — checking
103
- # .workflow_run.event too avoids firing off of those). Tag pushes and
104
- # manual dispatch always proceed.
109
+ # .workflow_run.event too avoids firing off of those). The branches filter
110
+ # on the trigger now stops those runs from being created at all; this stays
111
+ # as the second check, since it also covers a publish run dispatched by
112
+ # hand off main. Tag pushes and manual dispatch always proceed.
105
113
  if: >
106
114
  github.event_name != 'workflow_run' ||
107
115
  (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push')
@@ -1,44 +1,55 @@
1
- name: "CodeQL"
2
-
3
- on:
4
- push:
5
- branches: ["main"]
6
- pull_request:
7
- branches: ["main"]
8
- schedule:
9
- - cron: '23 3 * * 1'
10
-
11
- jobs:
12
- analyze:
13
- name: Analyze (${{ matrix.language }})
14
- runs-on: ubuntu-latest
15
- permissions:
16
- actions: read
17
- contents: read
18
- security-events: write
19
-
20
- strategy:
21
- fail-fast: false
22
- matrix:
23
- language: ["javascript-typescript"]
24
-
25
- steps:
26
- - name: Checkout repository
27
- uses: actions/checkout@v6
28
-
29
- - name: Initialize CodeQL
30
- uses: github/codeql-action/init@v4
31
- with:
32
- languages: ${{ matrix.language }}
33
- queries: security-extended,security-and-quality
34
- config: |
35
- paths-ignore:
36
- - dist/**
37
-
38
- - name: Autobuild
39
- uses: github/codeql-action/autobuild@v4
40
-
41
- - name: Perform CodeQL Analysis
42
- uses: github/codeql-action/analyze@v4
43
- with:
1
+ name: "CodeQL"
2
+
3
+ on:
4
+ # Pushes to main and the weekly sweep, but deliberately not pull_request.
5
+ #
6
+ # Every change arrives through a pull request that is then fast-forwarded
7
+ # onto main, so analysing both meant analysing the same tree twice: half of
8
+ # this repository's CodeQL runs were duplicates of the other half.
9
+ #
10
+ # Keeping the push side rather than the pull_request side is the deliberate
11
+ # half of that choice. Code scanning treats analyses of the default branch
12
+ # as the state of the project, which is what the Security tab lists and what
13
+ # gets fixed from; a pull_request-only setup leaves that state to the weekly
14
+ # cron. The cost is that a newly introduced alert shows up just after a merge
15
+ # instead of just before, which is how the alerts in this repository have
16
+ # actually been found and fixed.
17
+ push:
18
+ branches: ["main"]
19
+ schedule:
20
+ - cron: '23 3 * * 1'
21
+
22
+ jobs:
23
+ analyze:
24
+ name: Analyze (${{ matrix.language }})
25
+ runs-on: ubuntu-latest
26
+ permissions:
27
+ actions: read
28
+ contents: read
29
+ security-events: write
30
+
31
+ strategy:
32
+ fail-fast: false
33
+ matrix:
34
+ language: ["javascript-typescript"]
35
+
36
+ steps:
37
+ - name: Checkout repository
38
+ uses: actions/checkout@v6
39
+
40
+ - name: Initialize CodeQL
41
+ uses: github/codeql-action/init@v4
42
+ with:
43
+ languages: ${{ matrix.language }}
44
+ queries: security-extended,security-and-quality
45
+ config: |
46
+ paths-ignore:
47
+ - dist/**
48
+
49
+ - name: Autobuild
50
+ uses: github/codeql-action/autobuild@v4
51
+
52
+ - name: Perform CodeQL Analysis
53
+ uses: github/codeql-action/analyze@v4
54
+ with:
44
55
  category: "/language:${{matrix.language}}"