Skip to content

chore(ci): wire required PR/push validation workflow (#1278)#1284

Merged
ggfevans merged 4 commits intomainfrom
chore/1278-wire-required-ci-gates
Feb 25, 2026
Merged

chore(ci): wire required PR/push validation workflow (#1278)#1284
ggfevans merged 4 commits intomainfrom
chore/1278-wire-required-ci-gates

Conversation

@ggfevans
Copy link
Collaborator

@ggfevans ggfevans commented Feb 19, 2026

User description

Summary

  • add automatic pull_request and push (main) triggers to .github/workflows/test.yml
  • add workflow-level concurrency to cancel duplicate/in-flight runs on the same PR/ref
  • rename the CI job to stable check name validate and document required branch-protection check as Test / validate

Test Plan

  • npm run lint

Closes #1278


CodeAnt-AI Description

Wire required CI validation on PRs and main; preserve error causes for clearer diagnostics

What Changed

  • CI workflow now runs for pull requests targeting main and for pushes to main, providing pre-merge and post-merge validation
  • Workflow cancels in-progress duplicate runs for the same PR/ref so only the latest run continues
  • Primary CI job renamed to "validate", and documentation now instructs branch protection to require the Test / validate check
  • Several thrown errors (YAML parsing, CORS origin normalization, git metadata reading) now include the underlying error as the cause so error reports and stack traces retain root failure context

Impact

✅ Fewer duplicate CI runs
✅ Clearer branch-protection requirement for merges
✅ Better error traces when import/validation fails

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 19, 2026

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@coderabbitai
Copy link

coderabbitai bot commented Feb 19, 2026

📝 Walkthrough

Walkthrough

CI workflow now triggers automatically on pull requests and pushes to main with concurrency controls. Job renamed to "validate" with documentation updated. Error handling improved via error cause chaining in storage and script modules. Variable initialization patterns refined.

Changes

Cohort / File(s) Summary
CI Workflow Configuration
.github/workflows/test.yml
Added PR and push triggers for main branch; introduced concurrency block with dynamic group key and in-flight run cancellation; renamed job from "test" to "validate" with explicit name field.
CI Documentation
docs/guides/TESTING.md
Added "Required CI Checks" section documenting the validate check from test.yml, specifying it runs on PRs targeting main and pushes to main.
Error Handling
api/src/storage/filesystem.ts, scripts/generate-netbox-homelab-candidates.ts
Enhanced error chaining by attaching original errors as cause property when YAML parsing or async operations fail, improving error context propagation.
Variable Declarations
scripts/import-netbox-devices.ts
Removed explicit false initialization from frontImage and rearImage boolean declarations, now relying on assignment before use; added explicit type annotations.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A workflow now hops on main so bright,
With PR and push checks done just right,
Errors now chain their tales with care,
Variables lean, concurrency fair—
Validation runs without a scare! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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
Title check ✅ Passed The title clearly and concisely describes the main change: wiring required PR/push validation workflow to the CI system.
Description check ✅ Passed The description accurately relates to the changeset, detailing the addition of PR/push triggers, concurrency block, job renaming, and error handling improvements.
Linked Issues check ✅ Passed The PR fully addresses all acceptance criteria from #1278: PR/push triggers on main [.github/workflows/test.yml], concurrency block for duplicate runs, stable job name 'validate' documented as 'Test / validate' [docs/guides/TESTING.md], error cause chaining [storage/filesystem.ts, scripts/], and reuses existing workflow logic.
Out of Scope Changes check ✅ Passed All changes are in-scope: CI workflow configuration, documentation of CI requirements, and error handling improvements for better diagnostics—all directly supporting the PR objective of wiring required validation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/1278-wire-required-ci-gates

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@codeant-ai codeant-ai bot added the size:S This PR changes 10-29 lines, ignoring generated files label Feb 19, 2026
@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 19, 2026

CodeAnt AI finished reviewing your PR.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/test.yml:
- Around line 11-13: The concurrency group expression currently uses
github.event.pull_request.number || github.ref || github.run_id which misbehaves
for workflow_call and makes github.run_id unreachable; update the concurrency
group (the line that builds group: test-${{ github.workflow }}-...) to pick the
identifier based on github.event_name: use github.event.pull_request.number when
github.event_name == 'pull_request', use github.run_id when github.event_name ==
'workflow_call', and otherwise use github.ref (for push/workflow_dispatch), so
each event type uses the correct unique key and workflow_call invocations do not
cancel each other.

In `@docs/guides/TESTING.md`:
- Around line 107-116: The "### Required CI Checks" heading is incorrectly
nested under "## Environments"; move the "### Required CI Checks" section out of
the Environments block and promote it to a top-level "## Required CI Checks" (or
place it between "## Environments" and "## Philosophy") so it stands alongside
other top-level guide sections, or alternatively convert it into a note inside
the "Dev Environment" subsection; update the heading level from "###" to "##"
and adjust surrounding whitespace so the section appears at the document root
rather than as a child of "## Environments".

Comment on lines +11 to +13
concurrency:
group: test-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref || github.run_id }}
cancel-in-progress: true
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat .github/workflows/test.yml

Repository: RackulaLives/Rackula

Length of output: 1465


🏁 Script executed:

# Find workflows that call test.yml as a reusable workflow
rg -rn --glob "*.yml" --glob "*.yaml" "workflows/test" .github/workflows/ | head -30

Repository: RackulaLives/Rackula

Length of output: 124


🏁 Script executed:

# Check git history for test.yml to see if concurrency was recently added
git log --oneline -20 -- .github/workflows/test.yml

Repository: RackulaLives/Rackula

Length of output: 132


🏁 Script executed:

# Search for uses: directives in workflows
rg -A2 "uses:" .github/workflows/ --glob "*.yml" --glob "*.yaml" | grep -i "test" | head -40

Repository: RackulaLives/Rackula

Length of output: 722


🏁 Script executed:

# Search for any references to test.yml in workflow files using uses:
rg "uses:.*test\.yml" .github/workflows/ --glob "*.yml" --glob "*.yaml"

Repository: RackulaLives/Rackula

Length of output: 46


🏁 Script executed:

# Get more context on the git commit that added this
git show 89014b4 --stat

Repository: RackulaLives/Rackula

Length of output: 50377


🏁 Script executed:

# Search for any uses directives that reference test
rg "uses:" .github/workflows/ --glob "*.yml" --glob "*.yaml" -A 1 | grep -i "test" -A 1 -B 1

Repository: RackulaLives/Rackula

Length of output: 510


🏁 Script executed:

# Search for all uses: directives in workflow files to see the pattern
rg "uses:" .github/workflows/ --glob "*.yml" --glob "*.yaml" | grep -v "actions/" | head -20

Repository: RackulaLives/Rackula

Length of output: 2438


🏁 Script executed:

# Check if test.yml actually was previously a file (to confirm regression claim)
git log --all --full-history -- ".github/workflows/test.yml" | head -20

Repository: RackulaLives/Rackula

Length of output: 756


🏁 Script executed:

# Check all workflow files for any reference to test workflow
find .github/workflows -name "*.yml" -o -name "*.yaml" | xargs grep -l "test" | head -10

Repository: RackulaLives/Rackula

Length of output: 412


🏁 Script executed:

# Verify the actual date test.yml was added
git log --follow --format="%H %ai" -- .github/workflows/test.yml | tail -5

Repository: RackulaLives/Rackula

Length of output: 130


🏁 Script executed:

# Check if the review is accurate about regression by looking at git diff
git show 89014b4:.github/workflows/test.yml 2>/dev/null | head -20

Repository: RackulaLives/Rackula

Length of output: 435


Correct the concurrency expression to safely guard workflow_call invocations.

The concurrency group expression has a logic issue: for workflow_call events, github.event.pull_request.number is never populated (the event type is workflow_call, not pull_request), and github.ref reflects the caller's ref. This means concurrent invocations from a single caller could unnecessarily cancel each other. Additionally, github.ref is always non-empty, making the || github.run_id fallback unreachable.

While test.yml currently has no caller workflows in the repository, the workflow_call trigger is declared in the on: section. To future-proof and correctly handle all event types:

🔧 Proposed fix
 concurrency:
-  group: test-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref || github.run_id }}
+  group: test-${{ github.workflow }}-${{ github.event.pull_request.number || (github.event_name == 'workflow_call' && github.run_id) || github.ref }}
   cancel-in-progress: true

With this expression:

  • pull_request → uses PR number (deduplicates reruns on the same PR) ✅
  • push to main → uses ref (cancels superseded pushes) ✅
  • workflow_dispatch → uses ref (cancels duplicate dispatches on same branch) ✅
  • workflow_call → uses unique run_id (each invocation is independent, no mutual cancellation) ✅
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
concurrency:
group: test-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref || github.run_id }}
cancel-in-progress: true
concurrency:
group: test-${{ github.workflow }}-${{ github.event.pull_request.number || (github.event_name == 'workflow_call' && github.run_id) || github.ref }}
cancel-in-progress: true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/test.yml around lines 11 - 13, The concurrency group
expression currently uses github.event.pull_request.number || github.ref ||
github.run_id which misbehaves for workflow_call and makes github.run_id
unreachable; update the concurrency group (the line that builds group: test-${{
github.workflow }}-...) to pick the identifier based on github.event_name: use
github.event.pull_request.number when github.event_name == 'pull_request', use
github.run_id when github.event_name == 'workflow_call', and otherwise use
github.ref (for push/workflow_dispatch), so each event type uses the correct
unique key and workflow_call invocations do not cancel each other.

Comment on lines +107 to +116
### Required CI Checks

Branch protection should require the core CI validation check from `.github/workflows/test.yml`:

- **Check name:** `Test / validate`

This check runs on:

- Pull requests targeting `main` (pre-merge gate)
- Pushes to `main` (post-merge validation)
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

### Required CI Checks is a semantic mismatch inside ## Environments.

CI branch-protection check configuration is not an environment topic. As the heading hierarchy stands, this section appears as a child of ## Environments, which is about deployment targets (Local / Dev / Prod). Readers looking for branch-protection setup are unlikely to search there.

Consider either promoting it to a top-level ## section (e.g., between ## Environments and ## Philosophy) or grouping it under the adjacent "Dev Environment" flow as a note rather than a sibling heading.

As per coding guidelines: docs/**/*.md — "Organize documentation by purpose: ARCHITECTURE.md for high-level overview, guides/ for testing and accessibility patterns, reference/ for specifications and technical details, planning/ for roadmap."

🧰 Tools
🪛 LanguageTool

[uncategorized] ~109-~109: The official name of this software platform is spelled with a capital “H”.
Context: ...quire the core CI validation check from .github/workflows/test.yml: - Check name:...

(GITHUB)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/guides/TESTING.md` around lines 107 - 116, The "### Required CI Checks"
heading is incorrectly nested under "## Environments"; move the "### Required CI
Checks" section out of the Environments block and promote it to a top-level "##
Required CI Checks" (or place it between "## Environments" and "## Philosophy")
so it stands alongside other top-level guide sections, or alternatively convert
it into a note inside the "Dev Environment" subsection; update the heading level
from "###" to "##" and adjust surrounding whitespace so the section appears at
the document root rather than as a child of "## Environments".

Fix 4 preserve-caught-error violations by adding { cause } to rethrown
errors, and 3 no-useless-assignment violations by removing unnecessary
initial values. These pre-existing issues on main were exposed when
PR #1284 wired up lint validation on PRs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 25, 2026

CodeAnt AI is running Incremental review


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai bot added size:S This PR changes 10-29 lines, ignoring generated files and removed size:S This PR changes 10-29 lines, ignoring generated files labels Feb 25, 2026
@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 25, 2026

Sequence Diagram

This PR wires the repository CI to run the "Test" workflow for pull requests targeting main and pushes to main, adds concurrency to cancel duplicate runs, and renames the primary job to "validate" (used as the required branch-protection check). The diagram shows the core success path from a developer push/PR through GitHub Actions to the validation result.

sequenceDiagram
    participant Developer
    participant GitHub
    participant Actions
    participant Runner

    Developer->>GitHub: Open PR targeting main / Push to main
    GitHub->>Actions: Trigger "Test" workflow (on: pull_request / push)
    Actions->>Actions: Enforce concurrency (cancel duplicate runs)
    Actions->>Runner: Run "validate" job (checkout, lint, tests)
    Runner-->>Actions: Job result (success/failure)
    Actions-->>GitHub: Report "Test / validate" check status
    GitHub-->>Developer: Display status (pass/fail)
Loading

Generated by CodeAnt AI

@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 25, 2026

CodeAnt AI Incremental review completed.

@ggfevans ggfevans merged commit 77cfe82 into main Feb 25, 2026
7 of 9 checks passed
@ggfevans ggfevans deleted the chore/1278-wire-required-ci-gates branch February 25, 2026 09:31
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api/src/storage/filesystem.ts`:
- Line 338: Replace the inconsistent non-Error fallback in the throw statement
so it matches the explicit String(e) pattern used in saveLayout: update the
throw in filesystem.ts (the "throw new Error(`Invalid YAML: ${e instanceof Error
? e.message : e}`..." occurrence) to use String(e) for the non-Error branch
(i.e., keep e instanceof Error ? e.message : String(e)) so the thrown Error
message construction is consistent with saveLayout's error handling.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 59e8fd5 and 1e33342.

📒 Files selected for processing (1)
  • api/src/storage/filesystem.ts

parsed = yaml.load(yamlContent, { schema: yaml.JSON_SCHEMA });
} catch (e) {
throw new Error(`Invalid YAML: ${e instanceof Error ? e.message : e}`);
throw new Error(`Invalid YAML: ${e instanceof Error ? e.message : e}`, { cause: e });
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Align non-Error fallback with the explicit String(e) pattern used in saveLayout.

Line 338 uses implicit template-literal coercion for the non-Error branch (${... : e}), while line 470 uses the explicit String(e). They're functionally equivalent for all values, but the inconsistency is unnecessary.

♻️ Proposed alignment
-    throw new Error(`Invalid YAML: ${e instanceof Error ? e.message : e}`, { cause: e });
+    const message = e instanceof Error ? e.message : String(e);
+    throw new Error(`Invalid YAML: ${message}`, { cause: e });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
throw new Error(`Invalid YAML: ${e instanceof Error ? e.message : e}`, { cause: e });
const message = e instanceof Error ? e.message : String(e);
throw new Error(`Invalid YAML: ${message}`, { cause: e });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/src/storage/filesystem.ts` at line 338, Replace the inconsistent
non-Error fallback in the throw statement so it matches the explicit String(e)
pattern used in saveLayout: update the throw in filesystem.ts (the "throw new
Error(`Invalid YAML: ${e instanceof Error ? e.message : e}`..." occurrence) to
use String(e) for the non-Error branch (i.e., keep e instanceof Error ?
e.message : String(e)) so the thrown Error message construction is consistent
with saveLayout's error handling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S This PR changes 10-29 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chore(ci): wire required PR/push validation workflow

1 participant