Skip to content

ci: path-scoped deployments gated on the full test suite - #63

Merged
bgard68 merged 2 commits into
mainfrom
claude/professional-design-styling-2fa2c5
Aug 19, 2026
Merged

ci: path-scoped deployments gated on the full test suite#63
bgard68 merged 2 commits into
mainfrom
claude/professional-design-styling-2fa2c5

Conversation

@bgard68

@bgard68 bgard68 commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Adds the two deployment workflows and the reusable test gate.

Scope is explicit, not inferred

Both deploy workflows trigger on a paths allowlist rather than paths-ignore:

Change Deploys
src/**, tests/**, solution files, Dockerfile.api API only
web/** SPA only
docs/**, any *.md nothing

Nothing deploys unless every test passes

Both call the new reusable test-suite.yml and declare needs: tests, so a deployment cannot
start unless backend units, frontend units and the end-to-end smoke test all pass for that
exact commit. Keeping the suite in one file stops the two deploys drifting on what "tests passed"
means. The web deploy is gated on the smoke test too — a SPA is useless against a broken API.

Deployment safety

  • Publishes Release to a directory outside the workspace, then audits it: any .cs,
    .csproj, .sln, .env, compose file, or .git/node_modules/src/web/tests/docs
    directory fails the run. Deploying the repo would serve source and git history from wwwroot.
  • Asserts the app dll and appsettings.json are present before shipping.
  • Polls /health after deploying and stops the web app on a 503 — a crash-looping F1 app
    silently consumes the 60 CPU-minutes/day allowance.

Credentials

Azure auth is OIDC (id-token: write), so no Azure credential is stored in GitHub. Every
action is pinned to a full commit SHA, each verified to exist against the GitHub API — one I had
written from memory turned out to be wrong.

Requires these repo settings before the first run: secrets AZURE_CLIENT_ID, AZURE_TENANT_ID,
AZURE_SUBSCRIPTION_ID, AZURE_STATIC_WEB_APPS_API_TOKEN; variables VITE_API_BASE_URL,
VITE_GOOGLE_CLIENT_ID.

🤖 Generated with Claude Code

Adds deploy-api.yml and deploy-web.yml, each triggered by an allowlist of paths
rather than paths-ignore, so scope is explicit: src/tests/solution files deploy
the API, web/** deploys the SPA, and a docs or markdown change matches neither
and deploys nothing.

Both call a new reusable test-suite.yml and declare needs: tests, so nothing
reaches Azure unless backend units, frontend units and the end-to-end smoke test
all pass for that exact commit. The suite lives in one file so the two deploys
cannot drift on what 'tests passed' means. The web deploy is gated on the smoke
test too — a SPA is useless against a broken API.

The API job publishes Release to a directory outside the workspace and audits it
before deploying: any .cs, .csproj, .sln, .env, compose file, or
.git/node_modules/src/web/tests/docs directory fails the run, and the app dll
and appsettings.json must be present. It then polls /health and stops the web
app on a 503, because a crash-looping F1 app silently consumes the 60
CPU-minutes/day allowance.

Azure auth is OIDC — id-token: write and no stored credential. Every action is
pinned to a full commit SHA, each verified to exist against the GitHub API;
one I had written from memory was wrong.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails
actions/actions/checkout 3d3c42e5aac5ba805825da76410c181273ba90b1 🟢 7
Details
CheckScoreReason
Maintained🟢 1024 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Code-Review🟢 10all changesets reviewed
Binary-Artifacts🟢 10no binaries found in the repo
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Fuzzing⚠️ 0project is not fuzzed
Packaging⚠️ -1packaging workflow not detected
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Pinned-Dependencies🟢 3dependency not pinned by hash detected -- score normalized to 3
Security-Policy🟢 9security policy file detected
SAST🟢 10SAST tool is run on all commits
Branch-Protection🟢 6branch protection is not maximal on development and all release branches
actions/actions/setup-dotnet 67a3573c9a986a3f9c594539f4ab511d57bb3ce9 🟢 6.6
Details
CheckScoreReason
Binary-Artifacts🟢 10no binaries found in the repo
Maintained🟢 1015 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Code-Review🟢 10all changesets reviewed
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Packaging⚠️ -1packaging workflow not detected
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies🟢 8dependency not pinned by hash detected -- score normalized to 8
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Security-Policy🟢 9security policy file detected
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
SAST🟢 9SAST tool is not run on all commits -- score normalized to 9

Scanned Files

  • .github/workflows/test-suite.yml

@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

Everyone now lands on a guide at / and the store moves to /store. A working
storefront is confusing without knowing it is a demo, that nothing can charge
you, and which account to use, so the guide answers those first and links into
the store from several places.

The guide leads with the payments question because it is the one that decides
whether a visitor trusts the site: checkout runs a mock gateway, no card details
are collected, no processor is contacted, and a Stripe configuration is
restricted to test mode.

Three roles existed but only two were seeded, so nothing demonstrated what
ManageCatalog actually buys you. DbSeeder now creates a Manager as well, and the
guide spells out for each role what it can and cannot do — the interesting line
being that a Manager may restock and hide a widget but not retire one.

Staff could not find an order at all: admin had only lookup-by-GUID, and nobody
has a GUID to hand. Adds GET /admin/orders with a recent-orders list, and rebuilds
the admin page around selecting from it. The item rows are loaded rather than
skipped — OrderSummary derives its item count from them, and an initial
optimisation reported every order as empty.

Receipts work on the free tier without a mail server: the hosted demo writes
email to the log, so the order detail page carries the same line items, totals,
payment and tracking, and now prints as a receipt. The print stylesheet drops the
chrome and collapses the columns.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@bgard68
bgard68 merged commit d237748 into main Aug 19, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants