Skip to content

SDK Install Check (public npm) #34

SDK Install Check (public npm)

SDK Install Check (public npm) #34

name: SDK Install Check (public npm)
# Verifies that `@qvac/sdk` and all of its `@qvac/*` runtime dependencies are
# reachable on the public npm registry the way an end user would install them.
# Catches visibility regressions (e.g. a package accidentally re-published as
# private) before users hit "404 Not Found" during `npm install @qvac/sdk`.
#
# A single `npm install @qvac/sdk@latest` transitively pulls every `@qvac/*`
# runtime dep under the range pinned in `packages/sdk/package.json`, so any
# private-republish or 404 on any one of them fails this job. No matrix, no
# duplicated package list to keep in sync.
on:
schedule:
- cron: "0 6 * * *" # daily 06:00 UTC, after EU mornings
workflow_dispatch:
permissions:
contents: read
jobs:
install-check:
name: npm install @qvac/sdk@latest
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # 6.3.0
with:
node-version: lts/*
- name: Configure public npm registry
run: |
# Deliberately no NPM_TOKEN: every `@qvac/*` runtime dep is supposed
# to be reachable to anonymous end users, which is exactly the
# failure mode of the original `@qvac/translation-nmtcpp` 404 bug.
#
# `foreground-scripts=true` ensures any lifecycle script output is
# captured and visible in the runner log (rather than buffered or
# dropped behind npm's default background-runner). It is a no-op
# for the install step below thanks to `--ignore-scripts`, but
# protects any future debugging step that disables `--ignore-scripts`
# to inspect a real failure.
mkdir -p /tmp/install-check
printf '%s\n' \
'registry=https://registry.npmjs.org/' \
'@qvac:registry=https://registry.npmjs.org/' \
'foreground-scripts=true' \
> /tmp/install-check/.npmrc
- name: Install @qvac/sdk@latest in fresh dir
working-directory: /tmp/install-check
run: |
set -eo pipefail
npm init -y > /dev/null
# `--ignore-scripts` keeps this check focused on registry visibility
# and tarball download. Many @qvac/* packages have native postinstall
# steps (vcpkg/CMake) that we explicitly do NOT want to exercise here
# — those are covered by per-addon prebuild + integration workflows.
# Any 404 / accidentally-private re-publish on the SDK or any of its
# transitive @qvac/* deps fails this step.
npm install --no-fund --no-audit --ignore-scripts "@qvac/sdk@latest"
- name: Smoke require
working-directory: /tmp/install-check
run: |
# Pure-JS load of the SDK entry point. Catches "installs but fails
# to load" regressions (bad `exports`, broken transpile output) on
# top of the registry-visibility check the install step provides.
node -e "require('@qvac/sdk'); console.log('require ok')"
notify-on-failure:
name: Open or update tracking issue
needs: install-check
# Only the scheduled trigger should spam the issue tracker. Manual
# `workflow_dispatch` runs (used for testing) intentionally stay silent.
if: failure() && github.event_name == 'schedule'
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
- name: Open or update tracking issue
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # 8.0.0
with:
script: |
const title = 'SDK install-check failing on public npm';
const label = 'npm-visibility';
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
const body = [
`Scheduled SDK install-check failed.`,
``,
`- Run: ${runUrl}`,
`- Triage: open the failed run; the install log identifies the offending \`@qvac/*\` package.`,
`- Likely cause: package was re-published as private, or a release PR to \`release-*\` did not land, leaving \`packages/sdk/package.json\` pinned to a range that npm cannot resolve.`,
`- Fix: re-publish from the appropriate \`release-*\` branch with public access (\`publish-library-to-npm\` action, see \`docs/gitflow.md\`).`,
].join('\n');
const { data: existing } = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
labels: label,
per_page: 5,
});
if (existing.length > 0) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: existing[0].number,
body,
});
core.info(`Appended comment to existing issue #${existing[0].number}`);
} else {
const created = await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title,
body,
labels: [label],
});
core.info(`Opened new issue #${created.data.number}`);
}