From a7e40d8c55b29a579eda2a1f259cff54920d17f7 Mon Sep 17 00:00:00 2001 From: RelayStack <181901420+RelayStack@users.noreply.github.com> Date: Fri, 16 Oct 2026 15:05:38 +0200 Subject: [PATCH] ci: packaging smoke test + tag-driven npm release test.yml gains a `package` job that packs the tarball, installs it into a throwaway project and invokes the bins the way a user does. Unit tests import the source tree; this is the only job that would have caught a bin that silently does nothing once installed. release.yml publishes on v* tags: it verifies the tag matches package.json, runs the suite, and skips cleanly if the version is already on the registry so re-runs and back-filled tags can't fail. --- .github/workflows/release.yml | 52 +++++++++++++++++++++++++++++++++++ .github/workflows/test.yml | 26 ++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..7c62982 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,52 @@ +name: release + +on: + push: + tags: ["v*"] + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write # npm provenance (OIDC) + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + registry-url: https://registry.npmjs.org + + - name: Tag must match package.json + run: | + PKG=$(node -p "require('./package.json').version") + TAG="${GITHUB_REF_NAME#v}" + if [ "$PKG" != "$TAG" ]; then + echo "::error::tag v$TAG does not match package.json $PKG" + exit 1 + fi + + - run: npm test + - run: npm run check:skill + + # Keeps re-runs and back-filled tags from failing on a version that is + # already on the registry, which is not an error condition. + - name: Is this version already published? + id: check + run: | + if npm view "astro-seo-toolkit@${GITHUB_REF_NAME#v}" version >/dev/null 2>&1; then + echo "exists=true" >> "$GITHUB_OUTPUT" + echo "astro-seo-toolkit@${GITHUB_REF_NAME#v} is already on npm — skipping publish." + else + echo "exists=false" >> "$GITHUB_OUTPUT" + fi + + - name: Publish to npm + if: steps.check.outputs.exists == 'false' + run: npm publish --provenance --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + # Alternative to the NPM_TOKEN secret: configure a trusted publisher for + # this repo + workflow on npmjs.com, then drop the env block above. + # OIDC publishing needs no long-lived token and always carries provenance. diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ef65a67..fa634b5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,3 +16,29 @@ jobs: with: node-version: ${{ matrix.node }} - run: npm test + - run: npm run check:skill + + # Install the packed tarball and invoke the bins the way a user does. + # Catches packaging regressions (missing files, broken bin entrypoints, + # no-op CLIs) that unit tests against the source tree cannot see. + package: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + - run: npm pack + - run: | + mkdir -p /tmp/smoke && cd /tmp/smoke + npm init -y + npm install "$GITHUB_WORKSPACE"/astro-seo-toolkit-*.tgz + mkdir -p content + printf -- '---\ntitle: Smoke\ndescription: smoke\n---\n# Smoke\n' > content/a.md + npx astro-seo-toolkit --dir content --site https://example.com --out dist --llms-full + npx astro-seo-check --dir dist --site https://example.com + for f in llms.txt llms-full.txt sitemap.xml robots.txt; do + test -s "dist/$f" || { echo "missing or empty: dist/$f"; exit 1; } + done + npx astro-seo-sitemap --dir content --site https://example.com | grep -q '