Skip to content

fix: repair drift-check workflow after #75#76

Merged
palmtr3man merged 1 commit into
mainfrom
fix/drift-check-machine-identity
Jul 1, 2026
Merged

fix: repair drift-check workflow after #75#76
palmtr3man merged 1 commit into
mainfrom
fix/drift-check-machine-identity

Conversation

@palmtr3man

@palmtr3man palmtr3man commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds root package.json / lockfile so npm ci succeeds in CI
  • Rewrites scripts/drift-check.ts to compare Infisical staging /tuj keys against Netlify production env vars via API (the merged feat: add Netlify Guardrails drift check #75 script compared process.env on the GHA runner, which only has INFISICAL_TOKEN)
  • Adds scripts/parity-manifest.ts with P0/P1 keys and alias groups aligned to SEC-05 parity
  • Updates workflow to use npm run drift-check and require NETLIFY_AUTH_TOKEN + NETLIFY_SITE_ID

Prerequisites (repo settings)

Before CI passes, add in palmtr3man/thispagedoesnotexist12345:

  1. Secret INFISICAL_TOKEN — read access to Infisical staging env, path /tuj
  2. Secret NETLIFY_AUTH_TOKEN — Netlify personal access token with env read
  3. Variable NETLIFY_SITE_ID — site UUID for thispagedoesnotexist12345-app

Test plan

  • Confirm GitHub secrets/variable are set
  • Merge and verify Netlify Guardrails: Drift Check workflow passes on main
  • Optionally run workflow_dispatch and confirm drift output lists any real gaps

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Added a drift-check workflow that compares production environment variables against the expected secret set and reports missing values.
    • Added a shared list of required and parity-related environment keys to keep checks consistent.
  • Bug Fixes

    • Improved drift detection to support alias groups and clearer failure/warning behavior.
    • Added validation for required configuration so checks fail fast when setup is incomplete.
  • Chores

    • Updated ignored files and project scripts for the new check process.
    • Added TypeScript configuration for the check scripts.

Add root package.json and compare Infisical staging /tuj keys against
Netlify production env via API instead of the GHA runner process.env.

Co-authored-by: Cursor <cursoragent@cursor.com>
@netlify

netlify Bot commented Jun 27, 2026

Copy link
Copy Markdown

Deploy Preview for thispagedoesnotexist12345-app ready!

Name Link
🔨 Latest commit 9cbeb0f
🔍 Latest deploy log https://app.netlify.com/projects/thispagedoesnotexist12345-app/deploys/6a401a0f988f3b0008b7bc56
😎 Deploy Preview https://deploy-preview-76--thispagedoesnotexist12345-app.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@haystack-code-reviewer-pr-hook

Copy link
Copy Markdown

Try Haystack Code Reviewer

Want AI-powered code review for this PR? Get instant analysis, interactive visualizations, and actionable insights.

Review this PR with Haystack

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Rewrites scripts/drift-check.ts to compare Infisical staging secrets against Netlify production environment variables using a new parity-manifest.ts with P0_KEYS, P1_KEYS, and ALIAS_GROUPS. Adds package.json, tsconfig.json, .gitignore, and updates the CI workflow to pass Netlify credentials and run via npm run drift-check.

Changes

Infisical↔Netlify Drift Check Rewrite

Layer / File(s) Summary
Parity manifest constants
scripts/parity-manifest.ts
Defines P0_KEYS, P1_KEYS, ALIAS_GROUPS, and ALL_MANIFEST_KEYS as the canonical key sets for drift comparison.
Drift-check script rewrite
scripts/drift-check.ts
Replaces the prior process.env check with fetchInfisicalKeys/fetchNetlifyKeys helpers, alias-aware isKeyPresent, manifest-driven expected key construction, and reportDrift enforcing STRICTNESS via process.exit(1) or console.warn. Adds parallel fetching and fail-fast env var validation.
Project scaffolding and CI wiring
package.json, tsconfig.json, .gitignore, .github/workflows/drift-check.yml
Adds package.json with drift-check/test scripts and devDependencies (tsx, vitest, @infisical/sdk), tsconfig.json for NodeNext ESM, .gitignore, and updates the workflow to inject NETLIFY_AUTH_TOKEN/NETLIFY_SITE_ID and invoke npm run drift-check.

Sequence Diagram(s)

sequenceDiagram
  participant CI as CI Runner
  participant Script as drift-check.ts
  participant Infisical as Infisical SDK
  participant Netlify as Netlify REST API

  CI->>Script: npm run drift-check
  Script->>Infisical: fetchInfisicalKeys(token, project, env, path)
  Infisical-->>Script: secret keys[]
  Script->>Netlify: fetchNetlifyKeys(NETLIFY_AUTH_TOKEN, NETLIFY_SITE_ID)
  Netlify-->>Script: env var keys[]
  Script->>Script: build expected = P0+P1+Infisical keys
  Script->>Script: reportDrift(strictness, missingOnNetlify, missingInInfisical)
  Script-->>CI: exit 1 (fail) or console.warn
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • palmtr3man/thispagedoesnotexist12345#75: Directly precedes this PR — updates the same drift-check.yml workflow and rewrites scripts/drift-check.ts with the initial Infisical↔Netlify comparison logic and parity manifest integration.

Poem

🐇 Hop, hop — no secrets shall drift away,
Infisical and Netlify checked every day.
P0 keys hard-fail, P1 keys align,
Aliases grouped in a manifest so fine.
The bunny runs npm run drift-check with glee! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: repairing the drift-check workflow after #75.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/drift-check-machine-identity

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
scripts/parity-manifest.ts (1)

1-4: 🗄️ Data Integrity & Integration | 🔵 Trivial | 🏗️ Heavy lift

Remove the second source of truth for parity keys.

Line 3 still leaves career-navigator/scripts/sync-infisical-vault.ts PARITY_KEYS as a parallel manifest owner. If that list drifts from this file, the sync job and the drift check will enforce different key sets and produce false drift. Please have both scripts import the same exported manifest instead of relying on manual alignment.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/parity-manifest.ts` around lines 1 - 4, The parity key list still has
two owners, which can drift between the manifest and the sync job. Update
scripts/parity-manifest.ts to be the single exported source of truth and change
career-navigator/scripts/sync-infisical-vault.ts to import and use that shared
manifest instead of maintaining PARITY_KEYS separately. Make sure the drift
check and sync logic both reference the same symbols so any future key changes
only happen in one place.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@package.json`:
- Line 11: The dependency version for `@types/node` is out of sync with the
Node.js 20 runtime used by the drift-check workflow. Update the `@types/node`
entry in package.json to a Node 20-compatible major, or change the Node version
in .github/workflows/drift-check.yml to match the type package. Keep the runtime
and typings aligned so symbols like the package.json dependency and the
drift-check workflow stay on the same major version.

In `@scripts/drift-check.ts`:
- Around line 114-124: The drift check currently flattens P0 and P1 into a
single manifest set, which loses tier-specific handling in drift reporting.
Update the logic in drift-check.ts around manifestKeys/expectedOnNetlify and
reportDrift() to preserve separate P0 and P1 collections, compute drift for each
tier independently, and only allow P1 items to downgrade to warnings when
strictness is warn while keeping P0 as enforced.
- Around line 19-28: Both upstream awaits in the drift check can hang
indefinitely, so add explicit timeouts around the Infisical and Netlify requests
instead of relying on the GitHub Actions job timeout. Update fetchInfisicalKeys
and the Netlify fetch logic used by Promise.all() to go through a shared timeout
helper that fails fast with a clear error message, and apply the same pattern to
the other referenced call sites so the workflow exits promptly when either API
stalls.

---

Nitpick comments:
In `@scripts/parity-manifest.ts`:
- Around line 1-4: The parity key list still has two owners, which can drift
between the manifest and the sync job. Update scripts/parity-manifest.ts to be
the single exported source of truth and change
career-navigator/scripts/sync-infisical-vault.ts to import and use that shared
manifest instead of maintaining PARITY_KEYS separately. Make sure the drift
check and sync logic both reference the same symbols so any future key changes
only happen in one place.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0da1f2a5-caae-4dfc-9dd9-1d0801bdc689

📥 Commits

Reviewing files that changed from the base of the PR and between fb3bdbb and 9cbeb0f.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (6)
  • .github/workflows/drift-check.yml
  • .gitignore
  • package.json
  • scripts/drift-check.ts
  • scripts/parity-manifest.ts
  • tsconfig.json

Comment thread package.json
},
"devDependencies": {
"@infisical/sdk": "^5.0.2",
"@types/node": "^26.0.1",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "package.json `@types/node`:"
jq -r '.devDependencies["`@types/node`"]' package.json
echo
echo "workflow node-version:"
sed -n '17,21p' .github/workflows/drift-check.yml

Repository: palmtr3man/thispagedoesnotexist12345

Length of output: 362


🌐 Web query:

@types/node versioning follows Node.js major release types package documentation Node 20 vs Node 26 APIs

💡 Result:

The @types/node package versioning is designed to align its major version with the major version of Node.js [1][2]. To ensure type definitions accurately match your environment, you should use the @types/node major version that corresponds to your Node.js major version (e.g., use @types/node@20.x for Node.js 20 and @types/node@26.x for Node.js 26) [2]. Please note the following regarding the package: - Versioning Policy: While the major version generally aligns with Node.js, the package does not strictly adhere to SemVer in the traditional sense regarding breaking changes [3]. Updates are frequent, and breaking changes can occur within any release [3]. - Node 20 vs. Node 26 APIs: - Node 26 (Current) includes significant updates, such as the Temporal API enabled by default [4][5][6] and an upgrade to V8 14.6 [4][6]. - It removes several long-deprecated APIs that were present in Node 20, such as http.Server.prototype.writeHeader (which should be replaced with writeHead) and various legacy stream* modules [6]. - The @types/node 26.x package includes type definitions for these new APIs and removals, ensuring your TypeScript project reflects the Node 26 environment [7][6]. For projects supporting multiple Node.js versions, developers often use scripts to dynamically align the @types/node version with the active Node.js version in their development environment [2].

Citations:


🌐 Web query:

DefinitelyTyped @types/node latest major version Node 20 Node 26 compatibility

💡 Result:

Latest major version of DefinitelyTyped @types/node (as of 2026-06-27): 26.0.0 [1]. Compatibility with Node.js 20 and Node.js 26: - The DefinitelyTyped project maintains major branches/releases such that the @types/node major version should match the environment’s Node.js major version [2]. - Therefore, for Node.js 20 you should use @types/node 20.x (not the latest 26.x), and for Node.js 26 you should use @types/node 26.x [2]. Notes specific to the Node 26 @types/node major line: - The DefinitelyTyped PR updating to “node: v26” indicates that v26 will require TypeScript 5.6+ (it mentions removal of TS <=5.5 iterator helper compatibility definitions) [3]. Answer summary: - Use @types/node@20 for Node 20, and @types/node@26 for Node 26; the latest major currently is 26 [1][2].

Citations:


Align @types/node with the Node 20 runtime. package.json pins @types/node to ^26.0.1, but .github/workflows/drift-check.yml runs Node.js 20. Keep the type package on the same major as the runtime, or bump the workflow/runtime in lockstep.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 11, The dependency version for `@types/node` is out of
sync with the Node.js 20 runtime used by the drift-check workflow. Update the
`@types/node` entry in package.json to a Node 20-compatible major, or change the
Node version in .github/workflows/drift-check.yml to match the type package.
Keep the runtime and typings aligned so symbols like the package.json dependency
and the drift-check workflow stay on the same major version.

Comment thread scripts/drift-check.ts
Comment on lines +19 to 28
async function fetchInfisicalKeys(token: string): Promise<Set<string>> {
const client = new InfisicalSDK({ siteUrl: INFISICAL_SITE_URL });
await client.auth().accessToken(token);

const response = await client.secrets().listSecrets({
projectId: INFISICAL_PROJECT_ID,
environment: INFISICAL_ENV,
secretPath: INFISICAL_PATH,
viewSecretValue: false,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Add explicit timeouts around both upstream calls.

Both Infisical and Netlify requests are awaited without a deadline. If either API hangs, Promise.all() stalls the workflow until the GitHub Actions job timeout. Wrap both calls in a timeout helper so the step fails fast with a clear error.

Also applies to: 44-49, 109-112

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/drift-check.ts` around lines 19 - 28, Both upstream awaits in the
drift check can hang indefinitely, so add explicit timeouts around the Infisical
and Netlify requests instead of relying on the GitHub Actions job timeout.
Update fetchInfisicalKeys and the Netlify fetch logic used by Promise.all() to
go through a shared timeout helper that fails fast with a clear error message,
and apply the same pattern to the other referenced call sites so the workflow
exits promptly when either API stalls.

Comment thread scripts/drift-check.ts
Comment on lines +114 to +124
const manifestKeys = [...new Set([...P0_KEYS, ...P1_KEYS])];
const expectedOnNetlify = new Set([...infisicalKeys, ...manifestKeys]);

const missingOnNetlify = [...expectedOnNetlify].filter(
(key) => !isKeyPresent(key, netlifyKeys)
);
const missingInInfisical = manifestKeys.filter(
(key) => !isKeyPresent(key, infisicalKeys)
);

reportDrift(strictness, missingOnNetlify, missingInInfisical);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep P0 and P1 separate in the drift calculation.

manifestKeys = [...new Set([...P0_KEYS, ...P1_KEYS])] throws away the tiering defined in scripts/parity-manifest.ts, so reportDrift() can only apply one global policy. That makes a P0 miss degrade to a warning whenever STRICTNESS=warn, which contradicts the manifest contract. Compute and report P0/P1 drift separately, then only downgrade P1 on warn runs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/drift-check.ts` around lines 114 - 124, The drift check currently
flattens P0 and P1 into a single manifest set, which loses tier-specific
handling in drift reporting. Update the logic in drift-check.ts around
manifestKeys/expectedOnNetlify and reportDrift() to preserve separate P0 and P1
collections, compute drift for each tier independently, and only allow P1 items
to downgrade to warnings when strictness is warn while keeping P0 as enforced.

@palmtr3man palmtr3man merged commit ed4e4c8 into main Jul 1, 2026
5 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.

1 participant