Skip to content
Guides and policiesView source on GitHub ↗

Consumer CI comparison

Internal review for PR #293, recorded October 12, 2026. This compares actual bootstrap output with Forge’s native YAML and the reference website, rather than comparing only the TypeScript builders. No pipeline behavior was changed during that review. Current native GitLab admission and ownership are documented in Generated CI.

Inputs

  • Forge review branch commit 3ce4824, based on merged PR #292.
  • Fresh standalone bootstrap fixtures with both providers, selecting GitHub and GitLab separately as primary. Default Node major: 26.
  • Reference repository main commit 2b08a7f40ffb0b9afee696a83f9ecf3b8ec56070. Its current project, automation and security workflows were fetched for review; the local checkout was older by a CodeQL pin update.

Reference project workflow, security workflow, and automation workflow.

GitHub comparison

AreaGenerated consumerReference website / ForgeAssessment
Workflow boundariesProject, security, automationSame reference boundaries; Forge also has website, generator and maintenance workflowsMatches consumer scope
Source validationFormat, code/styles/Markdown lint, spelling, unused code, types, coverageReference has the same core checks with unit tests; Forge website uses coverageMatches Forge website; adds coverage relative to reference
Build graphEight source checks gate one build; browser, Lighthouse and build validation reuse itSame graph in reference and Forge websiteMatches
Site-specific outputNo generated resume Markdown checkReference validates generated resume MarkdownIntentional: template does not generate resumes
Dependency auditNo routine vulnerability audit job; unused-code audit remainsMatches both reference websites; package publication also omits vulnerability auditsAligned
Deployment gateDirect dependencies on all project validation jobsReference and Forge website also use direct dependenciesMatches
Production deploymentMain push only, validated Pages artifact, separate privileged deploy jobSame reference and Forge website behaviorMatches
Smoke testsDeployment output URL, Chromium, failure artifacts, nonempty URL check and ten-minute timeoutSame reference safeguards; current Forge website also has the timeout/URL checkMatches reference in both providers
Runtime setupInline setup-node, npm cache/install; selected major 22/24/26Reference uses a local setup action with lts/*; Forge selects explicit versions and tests compatibility separatelyIntentional single consumer runtime; no local action is required
Artifact policySeven days; browser/coverage/Lighthouse evidence uploaded alwaysReference uses fourteen days, browser evidence only on failureIntentional diagnostics/retention choice; more successful-run uploads
CodeQLActions and JS/TS, no build, extended queriesSame reference and Forge security checks; current CodeQL pin matches reference v4.38.2Matches
Dependency reviewHigh/critical findings fail the security checkMatches reference and Forge security policyMatched consumer policy; branch protection decides merge enforcement
Project triggersAll main PRs/pushesReference same; Forge website is scoped to website/docs/setup inputsIntentional: standalone consumer is the entire project
Security triggersMain PRs/pushes and weekly deterministic scheduleReference additionally covers dev; Forge covers mainIntentional default branch scope
Automation triggers.github/** and deterministic weekly scheduleReference additionally has manual dispatch and an automation summary gate; Forge has neitherMatches Forge; optional consumer convenience omitted
Aggregate checksNo project or automation aggregateReference has no project aggregate but does have an automation aggregate; Forge root Project remains deferredDirect checks retained; branch protection is consumer-owned
Pins and updatesImmutable action SHAs with version comments; consumer DependabotSame action-update model; generator mirrors bundled tested Forge pinsMatches; npm package releases carry bootstrap pin refreshes

Job IDs and command names differ where the template’s npm interface differs: unit-tests uses test:coverage, lint-styles uses lint:css, and browser-tests uses test:e2e. These commands exist in the generated package. They are naming differences, not missing checks.

GitLab comparison

GitLab renders the same twelve shared work jobs, plus deploy and smoke jobs. It uses native stages and needs, passes the build artifact to downstream checks, and publishes that artifact with Pages. The selected Node major is used in container images. Main/default-branch deployment is restricted to pushes and child pipelines; merge-request validation does not deploy. Inactive deployment and smoke jobs use rules with when: never. Inactive GitHub jobs and Pages uploads use if: false. Switching GitHub on also requires enabling its Pages upload step.

The providers are equivalent for project validation and deployment intent, but not yet equivalent across the full security and maintenance surface:

  • GitLab has no generated CodeQL-equivalent source scan, dependency-review equivalent, or workflow security/syntax scanner jobs.
  • The delivered Dependabot configuration targets GitHub Actions and npm. It does not provide automatic updates for GitLab Node image tags or a GitLab-hosted repository’s dependencies. A GitLab-native updater remains a separate decision.
  • GitLab does not configure a dependency cache. Browser jobs install their browser dependencies for each run. This affects duration, not validation coverage.
  • GitHub scopes privileged permissions per job. GitLab access depends on runner, project and token configuration; matching job graphs does not establish matching security guarantees.
  • GitLab currently emits one pipeline file, or a namespaced child pipeline file. It does not split security/automation into includes because those provider jobs have not been implemented.

Review conclusions

The generated GitHub pipeline follows the reference’s core design closely. The major intentional differences are consumer runtime selection, coverage, diagnostics retention and distributed schedules. Forge root’s compatibility, packaging and generator checks should not be shipped to consumers.

Before calling the providers fully equivalent, resolve GitLab security/updater scope. Consumer dependency review now matches the reference: high/critical findings fail the security check. Smoke timeout and empty-URL validation now match the reference in both generated providers. Remaining policy findings are documented for explicit review.

Verification limits

Both primary-provider fixtures were generated successfully. Existing provider schema tests, actionlint/security scans and hosted PR checks cover rendering and GitHub validation. No live Pages deployment, GitLab server-side CI Lint, branch protection configuration or GitLab runner setup was exercised for this comparison.

Issue #321: current GitLab reference evidence

Reviewed the reference at commit 871697a3a7984eac8df25118418a1a30c50c52b7, using its GitLab entrypoint and project jobs. Its matching main-push pipeline succeeded: all thirteen validation jobs passed. The job metadata records JUnit artifacts for unit/browser tests and a code-quality report for lint. No deployment or smoke jobs were included, consistent with GitHub being primary.

BehaviorReferenceGenerated consumerAssessment
Source gatesEight checks gate buildSame eight categoriesEquivalent; package script names differ
Build reuseOne build; browser/Lighthouse/output checks need its artifactSame graph and artifact needsEquivalent structure; reference jobs succeeded
Resume outputExtra generated-resume Markdown checkNo resume generator/checkIntentional site-specific difference
Unit evidenceUnit tests and JUnitCoverage tests, JUnit and CoberturaConsumer additionally enforces coverage
Quality evidenceGitLab code-quality reportSame report with repository-relative pathsEquivalent reporting intent
RetentionFourteen daysSeven daysIntentional consumer evidence policy
RuntimeLinux node:ltsLinux selected Node 22/24/26Consumer version is explicit; Forge qualifies platforms separately
MR admissionWorkflow admits MRs; validation jobs have no rulesExplicit job rules admit workflow-approved MRsGenerator fixes a gap also present in reference
DeploymentDeploy/smoke disabled while GitHub is primarySame native disabling conditionsMatching primary ownership

The public API returned no merge-request pipelines for the reference. Job traces required authentication, so artifact downloads were not independently inspected. Do not claim this push run proves MR execution, duplicate-push suppression, coverage report ingestion, or the new generator admission rule. Those are covered structurally by contract tests and GitLab’s documented rules; live MR evidence remains unavailable.

Automation remains provider-local: GitHub scanners inspect GitHub workflows. Website validation is not triggered across providers solely by GitHub setup-action changes. CodeQL, blocking high/critical dependency review and Dependabot remain GitHub-owned for these mirrors. Generated GitLab validation does not imply source-security or GitLab-native dependency-update parity. No new npm vulnerability audit gate is added.