CI / lint (push) Successful in 3s
CI / extension-version (push) Successful in 3s
CI / frontend-build (push) Successful in 21s
extension / lint (push) Failing after 28s
CI / backend-lint-and-test (push) Successful in 47s
CI / integration (push) Successful in 4m1s
Milestone #271 steps 2 and 3. Neither changes what gets published. STEP 2 -- shadow mode. build.yml's sign-extension and ci.yml's extension-version guard now log the version that WOULD be derived from git history alongside the hand-maintained one. Nothing reads the derived value, and neither site can fail because of it. This exists because `web-ext sign` is one-shot per version: AMO 409s on a repeat, so a wrong formula burns a real version number that cannot be reclaimed. Comparing the two across real builds is the only way to validate it at zero cost. sign-extension runs on main only, so main pushes are the sole source of truth for whether the derived number moves exactly when the shipped extension changes -- the dev-side log is a convenience, not the evidence. sign-extension now checks out with fetch-depth: 0. The derived version is a commit count and a depth-1 clone cannot produce one. STEP 3 -- XPI content verification. Every other packaging assertion checks our declaration against itself. This is the first that asks web-ext what it ACTUALLY wrote into the archive. That assumption was both unverified and fragile: `test/**` only survives to web-ext because callers `set -f` before substituting it, so losing that quoting would silently start shipping dev files with no other signal. The step builds the XPI and asserts test/, scripts/, vitest.config.js, package.json, package-lock.json, README.md and node_modules are absent -- and, because an over-matching exclusion would break the extension at runtime rather than at build time, that manifest.json, all four lib/*.js and every UI directory are present. unzip is installed only when missing; node:24-bookworm-slim may not carry it. Refs #2399, #2400 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
83 lines
3.5 KiB
YAML
83 lines
3.5 KiB
YAML
name: extension
|
|
# Lint + unit tests. The sign-and-publish dance moved into build.yml's
|
|
# `sign-extension` job (2026-05-25) — `:latest` now always bundles the XPI
|
|
# because sign-extension runs as a build-web dependency in the SAME workflow,
|
|
# eliminating the prior race between build.yml and a separate extension.yml.
|
|
# Signed XPIs are cached in Forgejo Release Assets named `ext-<version>`.
|
|
on:
|
|
push:
|
|
branches: [dev, main]
|
|
paths:
|
|
- 'extension/**'
|
|
- '.forgejo/workflows/extension.yml'
|
|
# test/version.spec.js asserts ci.yml's extension-version guard never
|
|
# ignores a file web-ext actually packages, so a ci.yml-only edit can
|
|
# break this suite and must trigger it.
|
|
- '.forgejo/workflows/ci.yml'
|
|
pull_request:
|
|
branches: [main]
|
|
paths:
|
|
- 'extension/**'
|
|
- '.forgejo/workflows/ci.yml'
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
lint:
|
|
runs-on: python-ci
|
|
container:
|
|
image: node:24-bookworm-slim
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
# Not --no-save: vitest and web-ext are both real devDependencies now,
|
|
# and the suite needs vitest resolvable from node_modules.
|
|
- name: Install dev dependencies
|
|
run: cd extension && npm install --no-audit --no-fund
|
|
- name: Lint
|
|
run: cd extension && npm run lint
|
|
# Pure-logic specs over lib/url.js and lib/platforms.js plus manifest /
|
|
# package version-consistency checks. No browser, no network.
|
|
- name: Unit tests
|
|
run: cd extension && npm run test:unit
|
|
|
|
# Everything else about packaging is asserted against our own declaration
|
|
# of what ships. This is the only check that asks web-ext what it ACTUALLY
|
|
# put in the archive. Until now that was an unverified assumption about
|
|
# glob semantics — and a fragile one: `test/**` reaches web-ext intact
|
|
# only because callers `set -f` first, so losing that quoting would
|
|
# silently start shipping dev files with no other signal.
|
|
- name: Verify XPI contents
|
|
run: |
|
|
set -eu
|
|
command -v unzip >/dev/null 2>&1 || { apt-get update -qq && apt-get install -y -qq unzip; }
|
|
cd extension
|
|
npm run build
|
|
ZIP=$(ls web-ext-artifacts/*.zip | head -1)
|
|
echo "=== packaged entries in $ZIP ==="
|
|
unzip -Z1 "$ZIP" | sort
|
|
echo "=== end ==="
|
|
ENTRIES=$(unzip -Z1 "$ZIP")
|
|
fail=0
|
|
# Must NOT ship: repo infrastructure with no business in a user's browser.
|
|
for pat in 'test/' 'scripts/' 'vitest.config.js' 'package.json' 'package-lock.json' 'README.md' 'node_modules/' 'web-ext-artifacts/'; do
|
|
if echo "$ENTRIES" | grep -q "^$pat"; then
|
|
echo "ERROR: '$pat' was packaged into the XPI but must not be"
|
|
fail=1
|
|
fi
|
|
done
|
|
# Must ship: if an exclusion pattern ever over-matches, the extension
|
|
# breaks at runtime rather than at build time, so assert presence too.
|
|
for req in 'manifest.json' 'lib/url.js' 'lib/api.js' 'lib/platforms.js' 'lib/cookies.js'; do
|
|
if ! echo "$ENTRIES" | grep -q "^$req$"; then
|
|
echo "ERROR: '$req' is missing from the XPI"
|
|
fail=1
|
|
fi
|
|
done
|
|
for dir in 'background/' 'popup/' 'options/' 'content/' 'icons/'; do
|
|
if ! echo "$ENTRIES" | grep -q "^$dir"; then
|
|
echo "ERROR: nothing from '$dir' was packaged"
|
|
fail=1
|
|
fi
|
|
done
|
|
[ "$fail" -eq 0 ] || exit 1
|
|
echo "XPI contents verified."
|