@krx3d/tizentube2 1.12.661
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.
- package/.gitattributes +2 -0
- package/.github/FUNDING.yml +2 -0
- package/.github/workflows/build-publish-cleanup.yml +609 -0
- package/.github/workflows/claude.yml +58 -0
- package/.github/workflows/codeql.yml +44 -0
- package/LICENSE +674 -0
- package/README.md +94 -0
- package/dist/service.js +49869 -0
- package/dist/userScript.js +15 -0
- package/package.json +25 -0
- package/scripts/tampermonkey/tizentube-loader.user.js +18 -0
- package/scripts/tampermonkey/tizentube-log-button.user.js +54 -0
- package/tizen.log +320 -0
package/.gitattributes
ADDED
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
# -----------------------------------------------------------------------------
|
|
2
|
+
# Build, publish, and cleanup TizenTube on npm
|
|
3
|
+
#
|
|
4
|
+
# WHAT THIS WORKFLOW DOES
|
|
5
|
+
# -----------------------
|
|
6
|
+
# - Runs on every push to the `main` branch (build + verification + version bump)
|
|
7
|
+
# - Runs on push to main and manual dispatch (build + npm publish + cleanup)
|
|
8
|
+
# - Builds:
|
|
9
|
+
# - dist/userScript.js (browser userscript, bundled & minified)
|
|
10
|
+
# - dist/service.js (DIAL service, bundled with Rollup)
|
|
11
|
+
# - Publishes the package to https://www.npmjs.com on release only
|
|
12
|
+
# - Automatically removes old versions from npm (within 72-hour window)
|
|
13
|
+
# - Deprecates older versions (beyond 72-hour window) if any remain
|
|
14
|
+
# - Purges jsDelivr CDN cache after publishing
|
|
15
|
+
#
|
|
16
|
+
# WHEN IT RUNS
|
|
17
|
+
# ------------
|
|
18
|
+
# push to main:
|
|
19
|
+
# - Bumps version in root package.json (+10 patch, rollover to minor)
|
|
20
|
+
# - Builds the project (dist files contain the NEW version)
|
|
21
|
+
# - Commits updated package.json + dist outputs back to repo
|
|
22
|
+
# - Does NOT publish to npm
|
|
23
|
+
#
|
|
24
|
+
# push/workflow_dispatch:
|
|
25
|
+
# - Builds the project
|
|
26
|
+
# - Publishes to npm
|
|
27
|
+
# - Removes old versions (≤72 hours old, keeps current version only)
|
|
28
|
+
# - Deprecates very old versions (>72 hours, if unpublish fails)
|
|
29
|
+
# - Purges jsDelivr cache
|
|
30
|
+
#
|
|
31
|
+
# AUTOMATIC VERSION CLEANUP
|
|
32
|
+
# -------------------------
|
|
33
|
+
# After publishing a new version, this workflow automatically:
|
|
34
|
+
# - Identifies all versions except the newly published one
|
|
35
|
+
# - Unpublishes versions that are ≤72 hours old (npm policy allows this)
|
|
36
|
+
# - Deprecates versions >72 hours old (unpublish no longer allowed)
|
|
37
|
+
# - Result: Only the latest version remains active on npm
|
|
38
|
+
#
|
|
39
|
+
# Note: npm allows unpublishing versions within ~72 hours of publication.
|
|
40
|
+
# After that window, versions can only be deprecated, not removed.
|
|
41
|
+
#
|
|
42
|
+
# VERSION BUMP RULE (push to main only)
|
|
43
|
+
# -------------------------------------
|
|
44
|
+
# - Increments patch by +10:
|
|
45
|
+
# 1.17.680 -> 1.17.690 -> ... -> 1.17.990
|
|
46
|
+
# - When patch would hit 1000:
|
|
47
|
+
# 1.17.990 -> 1.18.0
|
|
48
|
+
#
|
|
49
|
+
# LOOP PREVENTION
|
|
50
|
+
# --------------
|
|
51
|
+
# - Bot commits include "[skip ci]"
|
|
52
|
+
# - Job is skipped when:
|
|
53
|
+
# - actor is github-actions[bot], OR
|
|
54
|
+
# - commit message contains "[skip ci]"
|
|
55
|
+
#
|
|
56
|
+
# PREREQUISITES (REQUIRED)
|
|
57
|
+
# -----------------------
|
|
58
|
+
# 1) Create an npm account:
|
|
59
|
+
# https://www.npmjs.com/signup
|
|
60
|
+
#
|
|
61
|
+
# 2) Create an npm access token:
|
|
62
|
+
# - npm → Profile → Access Tokens
|
|
63
|
+
# - Click "Generate New Token"
|
|
64
|
+
# - Token name: anything you want
|
|
65
|
+
# - CHECK: "Bypass two-factor authentication (2FA)"
|
|
66
|
+
# - Packages and scopes:
|
|
67
|
+
# - Permissions: Read and Write
|
|
68
|
+
# - Scope: All packages
|
|
69
|
+
# - Expiration date: e.g. 90 days
|
|
70
|
+
# - Click "Generate token" and COPY it
|
|
71
|
+
#
|
|
72
|
+
# 3) Add the token to GitHub Secrets:
|
|
73
|
+
# - GitHub repository → Settings
|
|
74
|
+
# - Security → Secrets and variables → Actions
|
|
75
|
+
# - Repository secrets → New repository secret
|
|
76
|
+
# Name: NPM_TOKEN
|
|
77
|
+
# Secret: <paste npm token here>
|
|
78
|
+
#
|
|
79
|
+
# PACKAGE REQUIREMENTS
|
|
80
|
+
# --------------------
|
|
81
|
+
# - package.json must contain a unique name, e.g.:
|
|
82
|
+
# "@krx3d/tizentube"
|
|
83
|
+
# - The version MUST be increased before each release
|
|
84
|
+
# (npm will reject duplicate versions)
|
|
85
|
+
#
|
|
86
|
+
# HOW TO PUBLISH A NEW VERSION
|
|
87
|
+
# ----------------------------
|
|
88
|
+
# 1) Push to main (workflow auto-bumps version and rebuilds dist)
|
|
89
|
+
# 2) Create a GitHub Release
|
|
90
|
+
# 3) When the release is published:
|
|
91
|
+
# → GitHub Actions builds
|
|
92
|
+
# → npm publish runs automatically
|
|
93
|
+
# → Old versions are automatically removed
|
|
94
|
+
# → jsDelivr cache is purged
|
|
95
|
+
#
|
|
96
|
+
# CONFIGURATION
|
|
97
|
+
# -------------
|
|
98
|
+
# - PACKAGE_NAME: Set to your npm package name (e.g., '@krx3d/tizentube')
|
|
99
|
+
# - NODE_VERSION: Node.js version to use (default: '20')
|
|
100
|
+
# - UNPUBLISH_WINDOW_HOURS: How long versions can be unpublished (default: '72')
|
|
101
|
+
#
|
|
102
|
+
# -----------------------------------------------------------------------------
|
|
103
|
+
|
|
104
|
+
name: Build, publish and cleanup old npm versions
|
|
105
|
+
|
|
106
|
+
on:
|
|
107
|
+
pull_request:
|
|
108
|
+
paths-ignore:
|
|
109
|
+
- 'dist/**'
|
|
110
|
+
- 'package.json'
|
|
111
|
+
push:
|
|
112
|
+
branches:
|
|
113
|
+
- main
|
|
114
|
+
paths-ignore:
|
|
115
|
+
- '.github/**'
|
|
116
|
+
- '.gitattributes'
|
|
117
|
+
- '.gitignore'
|
|
118
|
+
- '.npmignore'
|
|
119
|
+
- 'LICENSE'
|
|
120
|
+
- 'README.md'
|
|
121
|
+
- 'package.json'
|
|
122
|
+
- 'tizen.log'
|
|
123
|
+
- 'dist/**'
|
|
124
|
+
- 'scripts/**'
|
|
125
|
+
workflow_dispatch:
|
|
126
|
+
|
|
127
|
+
# Allow this workflow to push back changes to the repo
|
|
128
|
+
permissions:
|
|
129
|
+
contents: write
|
|
130
|
+
|
|
131
|
+
env:
|
|
132
|
+
PACKAGE_NAME: '@krx3d/tizentube2'
|
|
133
|
+
PACKAGE_NAME_GH: 'KrX3D/TizenTube'
|
|
134
|
+
NODE_VERSION: '20'
|
|
135
|
+
UNPUBLISH_WINDOW_HOURS: '72'
|
|
136
|
+
|
|
137
|
+
jobs:
|
|
138
|
+
build-publish-clean:
|
|
139
|
+
runs-on: ubuntu-latest
|
|
140
|
+
|
|
141
|
+
# Prevent loop on bot commits and on our own "[skip ci]" commits
|
|
142
|
+
if: >
|
|
143
|
+
github.event_name != 'pull_request' &&
|
|
144
|
+
(github.event_name != 'push' ||
|
|
145
|
+
(github.actor != 'github-actions[bot]' && !contains(github.event.head_commit.message, '[skip ci]')))
|
|
146
|
+
|
|
147
|
+
steps:
|
|
148
|
+
- name: Checkout
|
|
149
|
+
uses: actions/checkout@v6
|
|
150
|
+
with:
|
|
151
|
+
# ensure the checkout action leaves credentials so we can push
|
|
152
|
+
persist-credentials: true
|
|
153
|
+
fetch-depth: 0
|
|
154
|
+
|
|
155
|
+
- name: Setup Node.js
|
|
156
|
+
uses: actions/setup-node@v6
|
|
157
|
+
with:
|
|
158
|
+
node-version: ${{ env.NODE_VERSION }}
|
|
159
|
+
|
|
160
|
+
# ----------------------------
|
|
161
|
+
# Version bump (push to main only) - MUST happen BEFORE building dist
|
|
162
|
+
# ----------------------------
|
|
163
|
+
- name: Bump root package.json version (+10 patch, rollover -> minor)
|
|
164
|
+
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
|
165
|
+
run: |
|
|
166
|
+
set -euo pipefail
|
|
167
|
+
node - <<'NODE'
|
|
168
|
+
const fs = require('fs');
|
|
169
|
+
const path = 'package.json';
|
|
170
|
+
const pkg = JSON.parse(fs.readFileSync(path, 'utf8'));
|
|
171
|
+
|
|
172
|
+
const ver = pkg.version || '0.0.0';
|
|
173
|
+
const m = ver.match(/^(\d+)\.(\d+)\.(\d+)$/);
|
|
174
|
+
if (!m) throw new Error(`Invalid version in package.json: ${ver}`);
|
|
175
|
+
|
|
176
|
+
let major = parseInt(m[1], 10);
|
|
177
|
+
let minor = parseInt(m[2], 10);
|
|
178
|
+
let patch = parseInt(m[3], 10);
|
|
179
|
+
|
|
180
|
+
patch += 10;
|
|
181
|
+
if (patch >= 1000) {
|
|
182
|
+
minor += 1;
|
|
183
|
+
patch = 0;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const newVer = `${major}.${minor}.${patch}`;
|
|
187
|
+
pkg.version = newVer;
|
|
188
|
+
|
|
189
|
+
fs.writeFileSync(path, JSON.stringify(pkg, null, 2) + '\n', 'utf8');
|
|
190
|
+
console.log(`Bumped version: ${ver} -> ${newVer}`);
|
|
191
|
+
NODE
|
|
192
|
+
|
|
193
|
+
- name: Show current version (old -> new)
|
|
194
|
+
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
|
195
|
+
run: |
|
|
196
|
+
set -euo pipefail
|
|
197
|
+
|
|
198
|
+
OLD_VER="$(git show HEAD^:package.json 2>/dev/null | node -e "let s='';process.stdin.on('data',d=>s+=d);process.stdin.on('end',()=>{try{console.log(JSON.parse(s).version||'');}catch{console.log('');}})")"
|
|
199
|
+
NEW_VER="$(node -p "require('./package.json').version")"
|
|
200
|
+
|
|
201
|
+
if [ -z "${OLD_VER:-}" ]; then
|
|
202
|
+
echo "Version: (unknown) -> ${NEW_VER}"
|
|
203
|
+
else
|
|
204
|
+
echo "Version: ${OLD_VER} -> ${NEW_VER}"
|
|
205
|
+
fi
|
|
206
|
+
|
|
207
|
+
# ----------------------------
|
|
208
|
+
# Build mods (userScript.js)
|
|
209
|
+
# ----------------------------
|
|
210
|
+
- name: Clean dist
|
|
211
|
+
run: |
|
|
212
|
+
set -euo pipefail
|
|
213
|
+
rm -rf dist
|
|
214
|
+
mkdir -p dist
|
|
215
|
+
|
|
216
|
+
- name: Install mods dependencies
|
|
217
|
+
run: |
|
|
218
|
+
set -euo pipefail
|
|
219
|
+
cd mods
|
|
220
|
+
npm ci
|
|
221
|
+
|
|
222
|
+
- name: Update Browserslist DB (mods)
|
|
223
|
+
run: |
|
|
224
|
+
set -euo pipefail
|
|
225
|
+
cd mods
|
|
226
|
+
npx update-browserslist-db@latest
|
|
227
|
+
|
|
228
|
+
- name: Build mods (rollup)
|
|
229
|
+
run: |
|
|
230
|
+
set -euo pipefail
|
|
231
|
+
cd mods
|
|
232
|
+
npm install
|
|
233
|
+
npx rollup -c
|
|
234
|
+
|
|
235
|
+
# ----------------------------
|
|
236
|
+
# Build service (service.js)
|
|
237
|
+
# ----------------------------
|
|
238
|
+
- name: Install service dependencies
|
|
239
|
+
run: |
|
|
240
|
+
set -euo pipefail
|
|
241
|
+
cd service
|
|
242
|
+
npm ci
|
|
243
|
+
|
|
244
|
+
- name: Build service (rollup)
|
|
245
|
+
run: |
|
|
246
|
+
set -euo pipefail
|
|
247
|
+
cd service
|
|
248
|
+
npm install
|
|
249
|
+
npx rollup -c
|
|
250
|
+
|
|
251
|
+
# ----------------------------
|
|
252
|
+
# Verify output
|
|
253
|
+
# ----------------------------
|
|
254
|
+
- name: Verify dist output
|
|
255
|
+
run: |
|
|
256
|
+
set -euo pipefail
|
|
257
|
+
echo "Listing dist/ (should contain built outputs):"
|
|
258
|
+
ls -lah dist || true
|
|
259
|
+
test -f dist/userScript.js
|
|
260
|
+
test -f dist/service.js
|
|
261
|
+
|
|
262
|
+
# ----------------------------
|
|
263
|
+
# Commit version bump + built JS to repo (push to main only)
|
|
264
|
+
# NOTE: dist is often gitignored, so we force-add the built files.
|
|
265
|
+
# ----------------------------
|
|
266
|
+
- name: Commit version bump + built files in dist/ (if changed)
|
|
267
|
+
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
|
268
|
+
run: |
|
|
269
|
+
set -euo pipefail
|
|
270
|
+
echo "Committing version bump + built files (if any changes)..."
|
|
271
|
+
|
|
272
|
+
git config --global user.name "github-actions[bot]"
|
|
273
|
+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
274
|
+
|
|
275
|
+
# stage what you actually want to commit
|
|
276
|
+
git add package.json
|
|
277
|
+
|
|
278
|
+
# stage dist files (use -f because dist/ is in .gitignore)
|
|
279
|
+
git add -f dist/userScript.js dist/service.js
|
|
280
|
+
|
|
281
|
+
if git diff --cached --quiet; then
|
|
282
|
+
echo "No changes to commit."
|
|
283
|
+
exit 0
|
|
284
|
+
fi
|
|
285
|
+
|
|
286
|
+
NEWVER=$(node -p "require('./package.json').version")
|
|
287
|
+
git commit -m "chore: bump version to ${NEWVER} + rebuild dist [skip ci]"
|
|
288
|
+
|
|
289
|
+
# IMPORTANT: ensure clean tree before rebase/pull
|
|
290
|
+
# (drops any lockfile drift etc. that you didn't commit)
|
|
291
|
+
git reset --hard HEAD
|
|
292
|
+
git clean -fd
|
|
293
|
+
|
|
294
|
+
git fetch origin main
|
|
295
|
+
#git pull --rebase origin main
|
|
296
|
+
git rebase origin/main
|
|
297
|
+
# git reset --hard
|
|
298
|
+
|
|
299
|
+
echo "Pushing changes back to main..."
|
|
300
|
+
git push origin HEAD:main
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
# --------------------
|
|
304
|
+
# NPM AUTH
|
|
305
|
+
# --------------------
|
|
306
|
+
- name: Configure npm auth
|
|
307
|
+
if: success()
|
|
308
|
+
env:
|
|
309
|
+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
310
|
+
run: |
|
|
311
|
+
set -euo pipefail
|
|
312
|
+
if [ -z "${NPM_TOKEN:-}" ]; then
|
|
313
|
+
echo "::error::NPM_TOKEN secret is not set"
|
|
314
|
+
exit 1
|
|
315
|
+
fi
|
|
316
|
+
printf "//registry.npmjs.org/:_authToken=%s\n" "$NPM_TOKEN" > ~/.npmrc
|
|
317
|
+
printf "always-auth=true\n" >> ~/.npmrc
|
|
318
|
+
npm whoami
|
|
319
|
+
echo "✓ npm auth OK"
|
|
320
|
+
|
|
321
|
+
# --------------------
|
|
322
|
+
# PUBLISH
|
|
323
|
+
# --------------------
|
|
324
|
+
- name: Publish package to npm
|
|
325
|
+
if: success()
|
|
326
|
+
id: publish_npm
|
|
327
|
+
run: |
|
|
328
|
+
set -euo pipefail
|
|
329
|
+
echo "Publishing package..."
|
|
330
|
+
npm publish --access public
|
|
331
|
+
|
|
332
|
+
- name: Wait for npm propagation (after publish)
|
|
333
|
+
if: steps.publish_npm.outcome == 'success'
|
|
334
|
+
run: |
|
|
335
|
+
echo "Waiting for npm propagation..."
|
|
336
|
+
sleep 10
|
|
337
|
+
|
|
338
|
+
# --------------------
|
|
339
|
+
# FETCH VERSIONS
|
|
340
|
+
# --------------------
|
|
341
|
+
- name: Gather versions and publish times
|
|
342
|
+
if: steps.publish_npm.outcome == 'success'
|
|
343
|
+
env:
|
|
344
|
+
PKG: ${{ env.PACKAGE_NAME }}
|
|
345
|
+
run: |
|
|
346
|
+
set -euo pipefail
|
|
347
|
+
echo "Fetching versions & times for ${PKG} ..."
|
|
348
|
+
npm view "${PKG}" versions --json > /tmp/versions.json
|
|
349
|
+
npm view "${PKG}" time --json > /tmp/time.json
|
|
350
|
+
|
|
351
|
+
CUR_VER=$(node -e "console.log(require('./package.json').version)")
|
|
352
|
+
echo "Current repo version: $CUR_VER"
|
|
353
|
+
echo "$CUR_VER" > /tmp/current_version.txt
|
|
354
|
+
|
|
355
|
+
# --------------------
|
|
356
|
+
# DECIDE WHAT TO REMOVE
|
|
357
|
+
# --------------------
|
|
358
|
+
- name: Decide versions to unpublish / deprecate
|
|
359
|
+
if: steps.publish_npm.outcome == 'success'
|
|
360
|
+
env:
|
|
361
|
+
UNPUBLISH_WINDOW_HOURS: ${{ env.UNPUBLISH_WINDOW_HOURS }}
|
|
362
|
+
run: |
|
|
363
|
+
set -euo pipefail
|
|
364
|
+
node -e '
|
|
365
|
+
const fs = require("fs");
|
|
366
|
+
const versions = JSON.parse(fs.readFileSync("/tmp/versions.json","utf8")||"[]");
|
|
367
|
+
const times = JSON.parse(fs.readFileSync("/tmp/time.json","utf8")||"{}");
|
|
368
|
+
const current = fs.readFileSync("/tmp/current_version.txt","utf8").trim();
|
|
369
|
+
|
|
370
|
+
const windowHours = Number(process.env.UNPUBLISH_WINDOW_HOURS || 72);
|
|
371
|
+
const now = Date.now();
|
|
372
|
+
|
|
373
|
+
const toUnpublish = [];
|
|
374
|
+
const toDeprecate = [];
|
|
375
|
+
|
|
376
|
+
for (const v of versions) {
|
|
377
|
+
if (v === current) continue;
|
|
378
|
+
const t = times[v] ? new Date(times[v]) : null;
|
|
379
|
+
if (!t) { toDeprecate.push(v); continue; }
|
|
380
|
+
const ageHours = (now - t.getTime()) / 36e5;
|
|
381
|
+
if (ageHours <= windowHours) toUnpublish.push(v);
|
|
382
|
+
else toDeprecate.push(v);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
fs.writeFileSync("/tmp/to_unpublish.txt", toUnpublish.length ? toUnpublish.join("\n") + "\n" : "");
|
|
386
|
+
fs.writeFileSync("/tmp/to_deprecate.txt", toDeprecate.length ? toDeprecate.join("\n") + "\n" : "");
|
|
387
|
+
console.log("To unpublish (<= " + windowHours + "h):", toUnpublish);
|
|
388
|
+
console.log("To deprecate (> " + windowHours + "h + unknown):", toDeprecate);
|
|
389
|
+
'
|
|
390
|
+
|
|
391
|
+
echo ""
|
|
392
|
+
echo "=== Unpublish candidates ==="
|
|
393
|
+
if [ -s /tmp/to_unpublish.txt ]; then cat /tmp/to_unpublish.txt; else echo "(none)"; fi
|
|
394
|
+
|
|
395
|
+
echo ""
|
|
396
|
+
echo "=== Deprecate candidates ==="
|
|
397
|
+
if [ -s /tmp/to_deprecate.txt ]; then cat /tmp/to_deprecate.txt; else echo "(none)"; fi
|
|
398
|
+
|
|
399
|
+
# --------------------
|
|
400
|
+
# UNPUBLISH
|
|
401
|
+
# --------------------
|
|
402
|
+
- name: Unpublish old versions (verified) and fallback to deprecate
|
|
403
|
+
if: steps.publish_npm.outcome == 'success'
|
|
404
|
+
env:
|
|
405
|
+
PKG: ${{ env.PACKAGE_NAME }}
|
|
406
|
+
run: |
|
|
407
|
+
set -euo pipefail
|
|
408
|
+
|
|
409
|
+
verify_gone(){
|
|
410
|
+
ver="$1"
|
|
411
|
+
tries=8
|
|
412
|
+
i=1
|
|
413
|
+
while [ $i -le $tries ]; do
|
|
414
|
+
echo "verify_gone: attempt $i for ${PKG}@${ver}"
|
|
415
|
+
if npm view "${PKG}@${ver}" --json > /tmp/view_${ver}.json 2>&1; then
|
|
416
|
+
echo "npm view still shows ${PKG}@${ver}"
|
|
417
|
+
i=$((i+1))
|
|
418
|
+
sleep 3
|
|
419
|
+
continue
|
|
420
|
+
else
|
|
421
|
+
echo "npm view does NOT show ${PKG}@${ver} (gone)"
|
|
422
|
+
return 0
|
|
423
|
+
fi
|
|
424
|
+
done
|
|
425
|
+
return 1
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
if [ ! -s /tmp/to_unpublish.txt ]; then
|
|
429
|
+
echo "No versions to unpublish."
|
|
430
|
+
else
|
|
431
|
+
while IFS= read -r ver; do
|
|
432
|
+
ver="$(echo "$ver" | tr -d '\r' | xargs)"
|
|
433
|
+
[ -z "$ver" ] && continue
|
|
434
|
+
|
|
435
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
436
|
+
echo "Attempting unpublish: ${PKG}@${ver}"
|
|
437
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
438
|
+
|
|
439
|
+
if npm unpublish "${PKG}@${ver}" 2>&1 | tee /tmp/npm_unpublish_${ver}.log; then
|
|
440
|
+
echo "npm unpublish command returned success for ${PKG}@${ver}"
|
|
441
|
+
if verify_gone "$ver"; then
|
|
442
|
+
echo "Verified ${PKG}@${ver} removed."
|
|
443
|
+
else
|
|
444
|
+
echo "::warning::Still visible after unpublish attempts -> deprecate fallback"
|
|
445
|
+
npm deprecate "${PKG}@${ver}" "Deprecated — please upgrade to a newer release." 2>&1 | tee /tmp/npm_deprecate_${ver}.log || echo "::warning::deprecate failed for ${ver}"
|
|
446
|
+
fi
|
|
447
|
+
else
|
|
448
|
+
echo "::warning::npm unpublish failed or returned non-zero for ${PKG}@${ver}"
|
|
449
|
+
echo "Attempting to deprecate as fallback..."
|
|
450
|
+
npm deprecate "${PKG}@${ver}" "Deprecated — please upgrade to a newer release." 2>&1 | tee /tmp/npm_deprecate_${ver}.log || echo "::warning::deprecate failed for ${ver}"
|
|
451
|
+
fi
|
|
452
|
+
|
|
453
|
+
done < /tmp/to_unpublish.txt
|
|
454
|
+
fi
|
|
455
|
+
|
|
456
|
+
# --------------------
|
|
457
|
+
# DEPRECATE older (>72h)
|
|
458
|
+
# --------------------
|
|
459
|
+
- name: Deprecate older versions
|
|
460
|
+
if: steps.publish_npm.outcome == 'success'
|
|
461
|
+
env:
|
|
462
|
+
PKG: ${{ env.PACKAGE_NAME }}
|
|
463
|
+
run: |
|
|
464
|
+
set -euo pipefail
|
|
465
|
+
if [ ! -s /tmp/to_deprecate.txt ]; then
|
|
466
|
+
echo "No versions to deprecate."
|
|
467
|
+
exit 0
|
|
468
|
+
fi
|
|
469
|
+
|
|
470
|
+
while IFS= read -r ver; do
|
|
471
|
+
ver="$(echo "$ver" | tr -d '\r' | xargs)"
|
|
472
|
+
[ -z "$ver" ] && continue
|
|
473
|
+
echo "Deprecating ${PKG}@${ver}..."
|
|
474
|
+
npm deprecate "${PKG}@${ver}" "Deprecated — please upgrade to a newer release." 2>&1 | tee /tmp/npm_deprecate_${ver}.log || echo "::warning::Deprecate failed for ${PKG}@${ver}"
|
|
475
|
+
done < /tmp/to_deprecate.txt
|
|
476
|
+
|
|
477
|
+
# --------------------
|
|
478
|
+
# Final wait + verify final state
|
|
479
|
+
# --------------------
|
|
480
|
+
- name: Wait before final verify
|
|
481
|
+
if: steps.publish_npm.outcome == 'success'
|
|
482
|
+
run: |
|
|
483
|
+
echo "Short wait to let registry propagate final state..."
|
|
484
|
+
sleep 8
|
|
485
|
+
|
|
486
|
+
- name: Verify final state
|
|
487
|
+
if: steps.publish_npm.outcome == 'success'
|
|
488
|
+
env:
|
|
489
|
+
PKG: ${{ env.PACKAGE_NAME }}
|
|
490
|
+
run: |
|
|
491
|
+
set -euo pipefail
|
|
492
|
+
echo "Final versions on npm:"
|
|
493
|
+
npm view "${PKG}" versions --json
|
|
494
|
+
echo ""
|
|
495
|
+
echo "Latest version:"
|
|
496
|
+
npm view "${PKG}" version
|
|
497
|
+
|
|
498
|
+
# --------------------
|
|
499
|
+
# Purge jsDelivr cache
|
|
500
|
+
# --------------------
|
|
501
|
+
- name: Generate jsDelivr URLs to purge
|
|
502
|
+
if: steps.publish_npm.outcome == 'success'
|
|
503
|
+
id: cdn_urls
|
|
504
|
+
run: |
|
|
505
|
+
set -euo pipefail
|
|
506
|
+
|
|
507
|
+
NPM_BASE="https://cdn.jsdelivr.net/npm/${PACKAGE_NAME}"
|
|
508
|
+
GH_BASE="https://cdn.jsdelivr.net/gh/${PACKAGE_NAME_GH}"
|
|
509
|
+
|
|
510
|
+
# Create array of URLs (npm + GitHub)
|
|
511
|
+
declare -a URLS=(
|
|
512
|
+
# npm package URLs
|
|
513
|
+
"${NPM_BASE}@latest"
|
|
514
|
+
"${NPM_BASE}@latest/package.json"
|
|
515
|
+
"${NPM_BASE}@latest/dist/userScript.js"
|
|
516
|
+
"${NPM_BASE}@latest/dist/service.js"
|
|
517
|
+
"${NPM_BASE}@*/package.json"
|
|
518
|
+
"${NPM_BASE}@*/dist/userScript.js"
|
|
519
|
+
"${NPM_BASE}@*/dist/service.js"
|
|
520
|
+
"${NPM_BASE}/package.json"
|
|
521
|
+
"${NPM_BASE}/dist/userScript.js"
|
|
522
|
+
"${NPM_BASE}/dist/service.js"
|
|
523
|
+
"${NPM_BASE}@*"
|
|
524
|
+
|
|
525
|
+
# GitHub repo URLs - main branch
|
|
526
|
+
"${GH_BASE}@main"
|
|
527
|
+
"${GH_BASE}@main/package.json"
|
|
528
|
+
"${GH_BASE}@main/dist/userScript.js"
|
|
529
|
+
"${GH_BASE}@main/dist/service.js"
|
|
530
|
+
|
|
531
|
+
# GitHub repo URLs - master branch (if you use it)
|
|
532
|
+
"${GH_BASE}@master"
|
|
533
|
+
"${GH_BASE}@master/package.json"
|
|
534
|
+
"${GH_BASE}@master/dist/userScript.js"
|
|
535
|
+
"${GH_BASE}@master/dist/service.js"
|
|
536
|
+
|
|
537
|
+
# GitHub repo URLs - without branch
|
|
538
|
+
"${GH_BASE}/package.json"
|
|
539
|
+
"${GH_BASE}/dist/userScript.js"
|
|
540
|
+
"${GH_BASE}/dist/service.js"
|
|
541
|
+
|
|
542
|
+
# Purge all GitHub branches/tags
|
|
543
|
+
"${GH_BASE}@*"
|
|
544
|
+
)
|
|
545
|
+
|
|
546
|
+
# Join with commas
|
|
547
|
+
URL_STRING=$(IFS=,; echo "${URLS[*]}")
|
|
548
|
+
|
|
549
|
+
echo "urls=${URL_STRING}" >> $GITHUB_OUTPUT
|
|
550
|
+
echo "Generated CDN URLs:"
|
|
551
|
+
printf '%s\n' "${URLS[@]}"
|
|
552
|
+
|
|
553
|
+
- name: Purge jsDelivr cache
|
|
554
|
+
if: steps.publish_npm.outcome == 'success'
|
|
555
|
+
uses: egad13/purge-jsdelivr-cache@v1
|
|
556
|
+
with:
|
|
557
|
+
url: ${{ steps.cdn_urls.outputs.urls }}
|
|
558
|
+
attempts: 3
|
|
559
|
+
|
|
560
|
+
- name: Purge individual URLs (fallback if batch fails)
|
|
561
|
+
if: steps.publish_npm.outcome == 'success' && failure()
|
|
562
|
+
continue-on-error: true
|
|
563
|
+
run: |
|
|
564
|
+
set +e
|
|
565
|
+
|
|
566
|
+
NPM_BASE="https://cdn.jsdelivr.net/npm/${PACKAGE_NAME}"
|
|
567
|
+
GH_BASE="https://cdn.jsdelivr.net/gh/${PACKAGE_NAME_GH}"
|
|
568
|
+
|
|
569
|
+
declare -a URLS=(
|
|
570
|
+
"${NPM_BASE}@latest"
|
|
571
|
+
"${NPM_BASE}@latest/package.json"
|
|
572
|
+
"${NPM_BASE}@latest/dist/userScript.js"
|
|
573
|
+
"${NPM_BASE}@latest/dist/service.js"
|
|
574
|
+
"${NPM_BASE}@*/package.json"
|
|
575
|
+
"${NPM_BASE}@*/dist/userScript.js"
|
|
576
|
+
"${NPM_BASE}@*/dist/service.js"
|
|
577
|
+
"${NPM_BASE}/package.json"
|
|
578
|
+
"${NPM_BASE}/dist/userScript.js"
|
|
579
|
+
"${NPM_BASE}/dist/service.js"
|
|
580
|
+
"${NPM_BASE}@*"
|
|
581
|
+
"${GH_BASE}@main"
|
|
582
|
+
"${GH_BASE}@main/package.json"
|
|
583
|
+
"${GH_BASE}@main/dist/userScript.js"
|
|
584
|
+
"${GH_BASE}@main/dist/service.js"
|
|
585
|
+
"${GH_BASE}@master"
|
|
586
|
+
"${GH_BASE}@master/package.json"
|
|
587
|
+
"${GH_BASE}@master/dist/userScript.js"
|
|
588
|
+
"${GH_BASE}@master/dist/service.js"
|
|
589
|
+
"${GH_BASE}/package.json"
|
|
590
|
+
"${GH_BASE}/dist/userScript.js"
|
|
591
|
+
"${GH_BASE}/dist/service.js"
|
|
592
|
+
"${GH_BASE}@*"
|
|
593
|
+
)
|
|
594
|
+
|
|
595
|
+
echo "Attempting individual URL purges..."
|
|
596
|
+
for url in "${URLS[@]}"; do
|
|
597
|
+
echo "Purging: $url"
|
|
598
|
+
curl -X POST "https://purge.jsdelivr.net/" \
|
|
599
|
+
-H "cache-control: no-cache" \
|
|
600
|
+
-d "path[]=$url" || echo "Failed to purge $url (continuing...)"
|
|
601
|
+
sleep 2
|
|
602
|
+
done
|
|
603
|
+
|
|
604
|
+
echo "Individual purge attempts complete"
|
|
605
|
+
|
|
606
|
+
- name: Cache purge complete
|
|
607
|
+
if: steps.publish_npm.outcome == 'success'
|
|
608
|
+
|
|
609
|
+
run: echo "✅ jsDelivr cache purge complete (npm + GitHub)"
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
name: Claude Code
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
issue_comment:
|
|
5
|
+
types: [created]
|
|
6
|
+
pull_request_review_comment:
|
|
7
|
+
types: [created]
|
|
8
|
+
issues:
|
|
9
|
+
types: [opened, assigned]
|
|
10
|
+
pull_request_review:
|
|
11
|
+
types: [submitted]
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
claude:
|
|
15
|
+
if: |
|
|
16
|
+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
17
|
+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
18
|
+
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
|
19
|
+
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
permissions:
|
|
22
|
+
contents: write
|
|
23
|
+
pull-requests: write
|
|
24
|
+
issues: write
|
|
25
|
+
id-token: write
|
|
26
|
+
actions: read # Required for Claude to read CI results on PRs
|
|
27
|
+
steps:
|
|
28
|
+
- name: Checkout repository
|
|
29
|
+
uses: actions/checkout@v6
|
|
30
|
+
with:
|
|
31
|
+
fetch-depth: 1
|
|
32
|
+
|
|
33
|
+
- name: Run Claude Code
|
|
34
|
+
id: claude
|
|
35
|
+
uses: anthropics/claude-code-action@v1
|
|
36
|
+
with:
|
|
37
|
+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
38
|
+
|
|
39
|
+
# Optional: Customize the trigger phrase (default: @claude)
|
|
40
|
+
# trigger_phrase: "/claude"
|
|
41
|
+
|
|
42
|
+
# Optional: Trigger when specific user is assigned to an issue
|
|
43
|
+
# assignee_trigger: "claude-bot"
|
|
44
|
+
|
|
45
|
+
# Optional: Configure Claude's behavior with CLI arguments
|
|
46
|
+
# claude_args: |
|
|
47
|
+
# --model claude-opus-4-1-20250805
|
|
48
|
+
# --max-turns 10
|
|
49
|
+
# --allowedTools "Bash(npm install),Bash(npm run build),Bash(npm run test:*),Bash(npm run lint:*)"
|
|
50
|
+
# --system-prompt "Follow our coding standards. Ensure all new code has tests. Use TypeScript for new files."
|
|
51
|
+
|
|
52
|
+
# Optional: Advanced settings configuration
|
|
53
|
+
# settings: |
|
|
54
|
+
# {
|
|
55
|
+
# "env": {
|
|
56
|
+
# "NODE_ENV": "test"
|
|
57
|
+
# }
|
|
58
|
+
# }
|