Repository navigation
Conversation
Add a lint-domains job that runs ts dev lint domains --changed-vs HEAD^1 on every pull request, so the pre-commit check cannot be skipped with --no-verify or by contributors who never installed the hook. A depth-2 checkout fetches the merge commit and its parents, which makes HEAD^1 the exact base commit without cloning full history. Part of #1215 Signed-off-by: dhruv8sh <dhruv8sh@proton.me>
|
PR CI will fail until #733 is merged. |
|
Important Action needed after merge: @aram356 Once this PR merges, please add this check to the required status checks in the Until it is required, a failing red check is shown but does not block merging. |
prk-Jr
left a comment
There was a problem hiding this comment.
Summary
Adds a PR-only lint-domains job that runs ts dev lint domains --changed-vs HEAD^1, plus the matching AGENTS.md gate. The diff-base choice is correct: the linter scans against merge-base(<ref>, HEAD), and on GitHub's merge-commit checkout HEAD^1 is the base tip, so exactly the PR's added lines are scanned. Nothing blocking.
1 of the inline comments below carries a one-click GitHub
suggestion— use Commit suggestion to apply it.
Non-blocking
♻️ refactor
- Cache key is never reusable across PRs — see inline at
.github/workflows/test.yml:319
👍 praise
- Depth-2 /
HEAD^1rationale, fail-closed at depth 1 — see inline at.github/workflows/test.yml:304
Cross-cutting / body-level findings
- 📌 Gate is advisory until branch protection requires it —
ts dev lint domains (changed lines)isn't in the required-checks list (currentlyformat-docs,cargo fmt,cargo test,format-typescript), so a PR that adds a disallowed host can still merge with this check red. Worth tracking as an explicit post-merge step for a repo admin. - 🌱 The PR under test can relax its own gate — the linter is compiled from the PR's own source (the allowlist lives in
is_allowed,crates/trusted-server-cli/src/commands/dev/lint/domains.rs:239) and the workflow file comes from the PR too, so a single diff can widen the allowlist or drop the job. Both are visible in review, so this is fine for now; the repo has no CODEOWNERS, and owners oncrates/trusted-server-cli/src/commands/dev/lint/and.github/workflows/would make such edits need a specific approval.
CI Status
All checks pass, including the new ts dev lint domains (changed lines).
- cargo fmt: PASS (required)
- cargo test: PASS (required)
- format-docs: PASS (required)
- format-typescript: PASS (required)
- ts dev lint domains (changed lines): PASS
- cargo test (ts CLI, native) (ubuntu-latest / macos-latest): PASS
- cargo test (axum native), cargo test (cross-adapter parity), cargo check (cloudflare native + wasm32-unknown-unknown), cargo check/build/test (spin native + wasm32-wasip1): PASS
- integration tests, integration tests (Fastly EC lifecycle), browser integration tests, prepare integration artifacts: PASS
- vitest, CLAUDE.md symlink guard: PASS
- CodeQL, Analyze (rust / actions / javascript-typescript / python): PASS
Brings #1225 at c3a33e6. Integration decisions: - .gitignore, AGENTS.md and scripts/README.md keep both sides: #1254's lint-domains gate stays CI gate 10 and #1225's documentation proposal scripts become gate 11; the scripts table keeps #1257's check-ci-node-pin.py row beside #1225's docs-proposal rows. - The lint-domains job from #1254 now uses #1259's setup-rust action and pins Node before cargo, so #1257's check-ci-node-pin gate passes. The two PRs merged cleanly but the combination failed that gate.
Brings #1226 at 5d423a2. Integration decisions: - AGENTS.md lists #1226's wasm clock lint as CI gate 12, after #1254's lint-domains (10) and #1225's documentation proposal scripts (11). - The integration fixture builder keeps #1226's table-customizing app_config_envelope and gains #1107's trace flag as a parameter; integration_app_config_envelope_with_trace and #1226's auction fixture both build on it. - The Cloudflare environment keeps #1226's spawn_with_config_json and shared wrangler launcher, and threads #1107's readiness probe through it, so spawn_with_readiness and the default spawn path still use their own readiness checks. - scripts/lint-wasm-clock.sh passes across the RC's Cloudflare build.
Co-authored-by: prk-Jr <49094961+prk-Jr@users.noreply.github.com>
aram356
left a comment
There was a problem hiding this comment.
Summary
Adds a PR-only lint-domains job that runs ts dev lint domains --changed-vs HEAD^1 on a depth-2 checkout, plus the matching AGENTS.md gate. In a replay of the Actions merge-ref checkout, HEAD^1 behaves as described: a clean PR exits 0 and is not blamed for a host main added after the fork, a new host exits 1, and depth 1 exits 2. The cargo-cli cache key matches main's test-cli caches (env hash 80d47658), and after a test-cli-shaped build cargo run --bin ts rebuilds 22 of ~430 crates. What blocks: the branch conflicts with main, so CI hasn't run this head; the job builds the TSJS bundles with the runner's unpinned Node; and there's an open question on when the check should become required.
2 of the inline comments below carry a one-click GitHub
suggestion— use Commit suggestion (or Add suggestion to batch for several at once) to apply them as commits on the PR branch. The remaining comments describe the fix in prose because the change touches multiple files or lines outside the diff and can't be auto-applied.
Blocking
🔧 wrench
- Merge conflict with
main; CI hasn't run at this head — see inline atAGENTS.md:365 - Pin Node before building
ts— see inline at.github/workflows/test.yml:325
❓ question
- When should this check become required? — see Cross-cutting below
Non-blocking
♻️ refactor
- Add
--verboseso a green run shows what was scanned — see inline at.github/workflows/test.yml:330
📌 out of scope
- Cache key stops matching
test-clionce #1259 lands — see inline at.github/workflows/test.yml:322
🏕 camp site
- Document the gate in CONTRIBUTING.md and
/check-ci— see Cross-cutting below
Cross-cutting / body-level findings
-
❓ When should this check become required? The description says this should land after #1216, which is still open, and the follow-up comment asks for the check to be required right after merge. I replayed the gate (the linter built from this PR's head,
--changed-vs C^1withHEADat C) over the last 80 first-parent commits onmain: 24 would have failed. Of the 13 PRs merged since #733, 2 would have failed, and neither added an outbound host:- #1213:
http://127.0.0.1:$PORT/healthindocs/superpowers/plans/2026-09-25-git-version-header.md:918is reported as host127.0.0.1:$port. - #1188: a moved test line that already contained
https://test-publisher.com/auction(crates/trusted-server-core/src/auction/endpoints.rs:838).
Across all 24, the false positives fall into three classes: documentation address ranges (
192.0.2.1,2001:db8::7), loopback with a shell-variable port (127.0.0.1:$PORT,localhost:$TS_PORT), and placeholders (https://host#fin a comment,format!("https://sync.{source_domain}/pull")reported assync). The rest are real under the current policy: the APS hosts,test.comandtest-prebid.comin tests, and links to AWS docs and RFCs. Can the check stay non-required until a linter issue for those three classes is fixed and #1216 lands? Or should this PR go back to draft until then, as the description says? - #1213:
-
🏕 Document the gate in CONTRIBUTING.md and
/check-ci. CONTRIBUTING.md's "Pre-commit URL-host linter" section still presents the hook as the only check, and.claude/commands/check-ci.md("Run all CI checks locally, in order") doesn't run it. Neither file is in this diff, so this can't be a suggestion. Proposed addition after the "To scan on demand" paragraph (passes the gate-8 Prettier check):CI runs the same check on every pull request: the `lint-domains` job scans the lines the PR adds against its base branch, so `--no-verify` or a missing hook does not let a host through. Editing or moving a line that already contains a non-allowlisted host counts as adding it. Reproduce the job locally with `ts dev lint domains --changed-vs origin/main`.
Also end the suppression sentence with
in a comment (<!-- allow-domain: <host> --> in Markdown).The HTML-comment form does suppress a Markdown line. Forcheck-ci.md, add a step 8 that runscargo run --manifest-path crates/trusted-server-cli/Cargo.toml --target "$(rustc -vV | sed -n 's/host: //p')" --bin ts -- dev lint domains --changed-vs origin/main.
CI Status
- Analyze (javascript-typescript): PASS
- Analyze (python): PASS
- Run Tests, Format, Integration Tests, and CodeQL (actions, rust) workflows: not run at
7fecdbdd1. GitHub builds no merge ref while the PR conflicts withmain. The last full run, atab4c378c8, passed all 22 checks, includingts dev lint domains (changed lines).
| 7. Docs format (`cd docs && npm run format`) | ||
| 8. Markdown format outside `docs/` (requires `cd docs && npm ci` first): `docs/node_modules/.bin/prettier --config docs/.prettierrc --check "*.md" ".claude/**/*.md" ".github/**/*.md" "crates/**/*.md" "scripts/**/*.md" "tinybird/**/*.md"`; fix with `--write` in place of `--check` | ||
| 9. Native core build-digest test and lint (`cargo test -p trusted-server-core --test template_build_digest` and `cargo clippy -p trusted-server-core --test template_build_digest -- -D warnings`) | ||
| 10. URL-host linter on lines the PR adds (`lint-domains` job, PRs only); run it locally with `cargo run --manifest-path crates/trusted-server-cli/Cargo.toml --target <host-triple> --bin ts -- dev lint domains --changed-vs origin/main` |
There was a problem hiding this comment.
🔧 wrench — This conflicts with main. #1226 already took gate 10 for the wasm clock lint, so GitHub builds no merge ref and the Run Tests workflow hasn't run at 7fecdbdd1: only the two CodeQL checks reported. The cargo-cli cache change from the last round has therefore never run in CI.
Merge main, keep both lines, and renumber this one:
10. Wasm clock lint: `scripts/lint-wasm-clock.sh` (crates built into the Cloudflare Worker must use `web_time`, not the `std::time::{Instant,SystemTime}` `now`/`elapsed` methods, which panic there)
11. URL-host linter on lines the PR adds (`lint-domains` job, PRs only); run it locally with `cargo run --manifest-path crates/trusted-server-cli/Cargo.toml --target <host-triple> --bin ts -- dev lint domains --changed-vs origin/main`The resolved file passes the gate-8 Prettier check. Once CI runs, the lint-domains log should show a restore from a v0-rust-cargo-cli-Linux-Linux-x64-80d47658-… key; main holds several under that prefix.
Apply manually: a suggestion can't resolve a merge conflict.
| cache-shared-key: cargo-cli-${{ runner.os }} | ||
| cache-save-if: false | ||
|
|
||
| # The `ts` CLI is host-target only; the workspace default is wasm32-wasip1. |
There was a problem hiding this comment.
🔧 wrench — Building ts compiles trusted-server-core, and trusted-server-js's build script runs npm ci and npm run build with whatever npm is on PATH. This job never sets up Node, so the green run at ab4c378c8 built the TSJS bundles with the runner image's Node (tsjs: Building per-module bundles in the log). That's the #1204 problem, and #1257's guard rejects it: on a merge of #1257 and this PR, scripts/check-ci-node-pin.py exits 1 with job lint-domains ... compiles Rust in step Lint URL hosts on lines added by this PR before an unconditional actions/setup-node step pinned to .tool-versions. With this suggestion applied it reports ok: 21 jobs in 6 workflows pin Node before compiling Rust.
| # The `ts` CLI is host-target only; the workspace default is wasm32-wasip1. | |
| # Building `ts` compiles trusted-server-core, whose trusted-server-js | |
| # build script runs the TSJS build with the `npm` on PATH, so pin Node | |
| # first (see #1204). | |
| - name: Use Node.js for the TSJS build | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version-file: .tool-versions | |
| # The `ts` CLI is host-target only; the workspace default is wasm32-wasip1. |
(Checked with actionlint (no new findings) and #1257's guard on the merged tree. setup-node reads the nodejs 24.12.0 line from .tool-versions.)
| run: | | ||
| cargo run --manifest-path crates/trusted-server-cli/Cargo.toml \ | ||
| --target "$(rustc -vV | sed -n 's/host: //p')" --bin ts -- \ | ||
| dev lint domains --changed-vs HEAD^1 |
There was a problem hiding this comment.
♻️ refactor — On success the linter prints nothing. The green run at ab4c378c8 goes straight from Running target/x86_64-unknown-linux-gnu/debug/ts dev lint domains --changed-vs 'HEAD^1' to post-job cleanup, so the log can't show whether any lines were scanned. --verbose writes scanned N lines in <path> per file to stderr and doesn't change the exit code, which makes a vacuous pass visible.
| dev lint domains --changed-vs HEAD^1 | |
| dev lint domains --changed-vs HEAD^1 --verbose |
(In a depth-2 replay of the Actions merge-ref checkout, a clean PR printed scanned 1 lines in c.md and exited 0.)
| # Restore `test-cli`'s cache read-only. This job never runs on main, | ||
| # so a key of its own is only ever saved in PR scope, where no other | ||
| # PR can restore it. | ||
| cache-shared-key: cargo-cli-${{ runner.os }} |
There was a problem hiding this comment.
📌 out of scope — This key only matches test-cli's while both jobs hash the same installed toolchains. rust-cache puts every rustup toolchain list entry into the key; this job's log lists 1.95.0 and the image's 1.99.0 stable. #1259 removes the image's stable in test-cli through the new ./.github/actions/setup-rust, so once it lands the hashes differ and this job silently goes back to cold builds (2m31s for the build step on the last uncached run). Whichever of #1254 and #1259 merges second should move this job to the composite action and drop its Retrieve Rust version step:
- name: Set up Rust toolchain
uses: ./.github/actions/setup-rust
with:
cache-key: cargo-cli
save-cache: "false"
ChristianPavilonis
left a comment
There was a problem hiding this comment.
Approved. The dedicated lint-domains CI job adds server-side enforcement for URL hosts in changed PR lines, with the local equivalent documented in AGENTS.md.
# Conflicts: # .github/workflows/test.yml
Summary
lint-domainsCI job that runsts dev lint domains --changed-vs HEAD^1on every pull request. Today the pre-commit hook is the only enforcement, and it is skipped bygit commit --no-verify, by clones that never rants dev install-hooks, and by commits made in the GitHub web UI. An unreviewed outbound host is a supply-chain concern for an edge service, so the check has to run server-side.Changes
.github/workflows/test.ymllint-domainsjob (ubuntu,pull_requestonly): depth-2 checkout, pinned Rust toolchain with its own cache key, thencargo run … --bin ts -- dev lint domains --changed-vs HEAD^1for the host targetAGENTS.md--changed-vs origin/main)Departures from the issue
test-cli. It gets a separate check name that branch protection can require, needs no matrix special-casing, and runs in parallel instead of after the slow NSS and browser tests. The cost is one more toolchain setup. It uses its own cache key so it can't racetest-cliinto saving a cache without the test builds.--changed-vs HEAD^1withfetch-depth: 2, not$GITHUB_BASE_REFwithfetch-depth: 0. A PR checkout is GitHub's merge commit, so its first parent is the exact base commit GitHub merged against. Depth 2 fetches that parent without cloning the full history (~295 MiB) on every PR. Depth 1 does not work: the parent isn't present, so the linter exits 2 on every PR. It fails closed, never open.Note for #733's rebase
Besides textual conflicts in
crates/trusted-server-cli/Cargo.toml,commands/dev/mod.rsandlib.rs, #733 conflicts with currentmainin a way that breaks the build: it gatesoutput::info/output::warntotarget_os = "macos", butmainnow builds the dev proxy on Linux too, and the proxy calls them. Widening the gate toany(target_os = "macos", target_os = "linux")fixed it in a local merge.Closes
Part of #1215. Two done-when items are left for after merge: a real PR shown failing the gate on GitHub (needs #733 on
main), and the Stage 3 decision (clean up and gate the full audit, or use a baseline file).Test plan
cargo test-fastly && cargo test-axum: not run, no Rust changes. The base commit7a0ecb4cis green onmaincargo clippy-fastly && cargo clippy-axum: not run, same reasoncargo fmt --all -- --checkcd docs && npm run formatfastly compute serve: not applicabledocs/(CI gate 8) passes.refs/pull/N/mergemerge commit, a fetch at the given depth,tsbuilt from Add ts dev lint domains and ts dev install-hooks to block non-allowlisted URL hosts #733):HEAD^1: a PR addinghttps://unapproved.internal/…exits 1 and flags the line; a PR adding only anexample.comURL exits 0.HEAD^1andmainas the base.main+ Add ts dev lint domains and ts dev install-hooks to block non-allowlisted URL hosts #733 with this change on top, the Linux CLI steps (clippy,cargo test, real-NSS trust tests) pass. The gate exits 0 on this change and 1 on a follow-up commit adding a disallowed host.Checklist
unwrap()in production code: no Rust changestracingmacros (notprintln!): no Rust changes