Skip to content

Feature/builds - #58

Open
JBraunsmaJr wants to merge 10 commits into
mainfrom
feature/builds
Open

Feature/builds#58
JBraunsmaJr wants to merge 10 commits into
mainfrom
feature/builds

Conversation

@JBraunsmaJr

@JBraunsmaJr JBraunsmaJr commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Closes #57

Summary by CodeRabbit

  • New Features
    • Added configurable build numbers with previews, version management, and tag filters.
    • Added Docker image publishing with tag promotion, authentication, optional source cleanup, and result reporting.
    • Added project build settings and Docker publishing configuration to the web interface.
    • Run details now display build numbers and publishing outcomes.
  • Bug Fixes
    • Improved test image handling, sharding, and condition evaluation.
    • Added clearer publishing statuses, warnings, and failure reporting.
  • Documentation
    • Added guidance for build numbering and Docker publishing configuration.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f65a94cf-f550-4e12-939c-afdcad0a0e31

📥 Commits

Reviewing files that changed from the base of the PR and between a087cec and 497350e.

📒 Files selected for processing (35)
  • .forge/main.yml
  • .forge/pipeline.yml
  • .forge/scripts/integration-tests.sh
  • .forge/scripts/unit-tests.sh
  • .forge/templates/docker-build.yml
  • .junie/memory/errors.md
  • .junie/memory/feedback.md
  • .junie/memory/language.json
  • .junie/memory/memory.version
  • .junie/memory/tasks.md
  • .junie/plans/centralized-git-cache-and-workspace-distribution.md
  • .junie/plans/migrate-to-svelte-frontend.md
  • cmd/forge/cmd_report.go
  • cmd/forge/remote.go
  • compose.yml
  • docs/Pipeline-Reference.md
  • internal/agent/agent.go
  • internal/api/types.go
  • internal/compiler/compiler.go
  • internal/compiler/compiler_test.go
  • internal/registryutil/registry.go
  • internal/registryutil/registry_test.go
  • internal/scheduler/buildnumber_handlers.go
  • internal/scheduler/evaluator.go
  • internal/scheduler/server.go
  • internal/scheduler/store.go
  • internal/scheduler/submitrun_build_vars_test.go
  • internal/scheduler/test_split.go
  • test-uses.yml
  • ui/src/lib/api.ts
  • ui/src/lib/buildNumberPreview.ts
  • ui/src/lib/components/BuildSettings.svelte
  • ui/src/lib/components/DetailsPanel.svelte
  • ui/src/lib/components/DockerPublishCard.svelte
  • ui/src/lib/components/Sidebar.svelte
 ________________________________________________________________
< KōdoUsagi Gundam is my Japanese cousin. He's a bit more mecha. >
 ----------------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
📝 Walkthrough

Walkthrough

The change adds configurable build numbers, Docker image promotion, scheduler execution, CLI and UI management, persisted publish results, and pipeline image handling.

Changes

Build numbers and management

Layer / File(s) Summary
Build-number format and persistence
internal/buildnumber/*, internal/scheduler/store.go, internal/store/*, internal/api/types.go
Adds validated formats, scoped counters, version metadata, immutable run numbers, and environment propagation.
Build-number management interfaces
internal/scheduler/buildnumber_handlers.go, cmd/forge/*, ui/src/lib/*, ui/src/lib/components/BuildSettings.svelte
Adds API, CLI, and UI support for formats, versions, tag filters, and previews.
Build-number presentation
ui/src/lib/components/DAG.svelte, docs/Pipeline-Reference.md
Displays run build numbers and documents build-number behavior.

Docker publishing

Layer / File(s) Summary
Docker publish contracts and compilation
internal/api/types.go, internal/compiler/*, internal/pipeline/types.go, ui/src/lib/components/PipelineEditor.svelte
Adds the docker_publish step type, validation, interpolation, YAML serialization, and editor controls.
Registry promotion and scheduler execution
internal/registryutil/*, internal/scheduler/*, internal/store/*
Adds authenticated manifest promotion, source-tag deletion, job leasing, credential lookup, result persistence, and status handling.
Docker publish results
ui/src/lib/components/DetailsPanel.svelte, ui/src/lib/components/DockerPublishCard.svelte, ui/src/lib/components/DAGNodes.svelte, ui/src/lib/components/EditorDAG.svelte
Adds publish status labels, editor visualization, and result details for tags, digests, deletion, and warnings.

Pipeline integration

Layer / File(s) Summary
Test image build and promotion
.forge/*, tests/integration/suite_test.go, compose.yml
Builds a test image before tests, passes FORGE_IMAGE, preserves supplied image values, and promotes registry tags.
Workspace-based pipeline compilation
internal/scheduler/webhook.go
Compiles the pipeline after source extraction using the workspace-qualified path.
Pipeline documentation
docs/Pipeline-Reference.md
Documents build numbers, Docker publishing, and the containerization example.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Pipeline
  participant BuildImage
  participant TestSteps
  participant DockerPublish
  participant Registry
  Pipeline->>BuildImage: build numbered test image
  BuildImage->>TestSteps: provide FORGE_IMAGE
  TestSteps->>BuildImage: pull test image
  Pipeline->>DockerPublish: submit promotion job
  DockerPublish->>Registry: fetch and promote manifest
  DockerPublish->>Registry: delete source tag
Loading

Possibly related PRs

  • JBraunsmaJr/Forge#52: Both changes modify the unit and integration test scripts; this change extends the test image flow introduced by that PR.

Suggested labels: documentation, enhancement, Frontend, Backend

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title refers to builds but is too broad to identify the primary changes in build numbers and Docker image publishing. Use a specific title such as "Add build numbers and Docker image promotion support".
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The changes implement build numbers, format and version management, propagation, docker_publish, CLI/UI support, persistence, and documentation for issue #57.
Out of Scope Changes check ✅ Passed The changes support the linked objectives, including image reuse, local execution, webhook compilation, and configurable Forge images.
✨ 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 feature/builds

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 20

🤖 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 @.forge/main.yml:
- Line 18: Update the secrets flow-style list in the YAML configuration to
remove the spaces immediately inside its brackets, preserving the existing
REGISTRY_USERNAME and REGISTRY_PASSWORD entries.

In @.forge/pipeline.yml:
- Around line 81-83: Update the Docker promotion configuration around the source
and tags entries to use a Docker-tag-safe normalized form of env.FORGE_BRANCH,
replacing the raw branch value while preserving the existing build-number
source.

In @.forge/templates/docker-build.yml:
- Line 4: Remove the inner spaces from all affected flow-style YAML sequences:
update .forge/templates/docker-build.yml lines 4-4, and .forge/pipeline.yml
lines 32-32, 43-43, 56-56, 76-76, and 77-77. Preserve the existing sequence
values while formatting each list without spaces immediately inside its
brackets.

In `@cmd/forge/remote.go`:
- Around line 310-318: Update the Docker publish output around
DockerPublishResult to always display both SourceDigest and SourceDeleted,
alongside the existing tags-applied information. Remove the conditional omission
so the false deletion state is explicitly shown, while preserving the warning
output.
- Around line 316-317: Sanitize each warning in the r.Warnings loop before
passing it to fmt.Printf, removing or escaping embedded control characters and
newlines while preserving readable text. Update the warning-output logic in the
DeleteTag response handling without changing warning collection or other output
behavior.

In `@docs/Pipeline-Reference.md`:
- Line 515: Update the Authentication section’s condition for omitting
REGISTRY_USERNAME and REGISTRY_PASSWORD: credentials are optional only when the
registry permits all required docker_publish operations, including image push
and any optional deletion, not merely anonymous pulls.

In `@internal/compiler/compiler.go`:
- Around line 522-527: Deep-copy cloned.DockerPublish.Tags before the matrix
interpolation loop so each matrix combination operates on an independent slice
rather than mutating the shared js.DockerPublish.Tags backing array. Update the
compiler flow around the DockerPublish cloning block and add a regression test
covering a target tag containing a ${{ matrix.* }} expression, verifying every
matrix combination receives its own interpolated tag.

In `@internal/registryutil/registry.go`:
- Around line 168-188: Update Client.DeleteTag in
internal/registryutil/registry.go to delete the source tag by name using the
registry’s tag-specific endpoint, rather than deleting by manifest digest;
return ErrDeletionUnsupported when tag deletion is unavailable so callers retain
the source tag and record a warning. Update the tag-to-digest alias behavior in
internal/registryutil/registry_test.go lines 105-110. Remove delete_source: true
from .forge/main.yml line 26 and docs/Pipeline-Reference.md lines 499-517 until
safe cleanup is supported.
- Around line 63-70: Require HTTPS for all credential-bearing requests in
fetchToken and the client created by NewClient: reject non-HTTPS parsed realms
before sending Basic credentials, and configure the shared HTTP client to reject
redirects that are non-HTTPS (including HTTPS-to-HTTP transitions). Add
regression tests covering both a non-HTTPS realm and a redirect to HTTP.

In `@internal/scheduler/buildnumber_handlers.go`:
- Around line 66-69: Update the handler containing the SetBuildFormat call to
validate req.Format before attempting persistence, returning 400 for invalid
format values; then map SetBuildFormat failures to HTTP 500, matching
handleSetVersion and handleSetVersionTagFilter. Keep SetBuildFormat’s internal
Parse validation unchanged so direct callers remain protected.

In `@internal/scheduler/server.go`:
- Around line 1011-1018: Update the docker_publish drain loop around
LeaseDockerPublishJob and executeDockerPublish to bound concurrent workers with
a semaphore, stop leasing when ctx is canceled, and track all launched
goroutines with a sync.WaitGroup. Ensure shutdown waits for tracked workers
before Start returns, and propagate ctx through executeDockerPublish into the
registryutil operations so in-flight promotions are canceled.
- Around line 1118-1133: Replace the destructive `client.DeleteTag(repository,
manifest.Digest)` call in the `DeleteSource` cleanup block with the interim
unsupported behavior: do not issue manifest deletion, append a warning
explaining that source-tag deletion is unsupported because deleting the digest
would remove promoted tags, and log that warning without failing promotion.
Remove any now-unused `errors` or `registryutil.ErrDeletionUnsupported` imports.

In `@internal/scheduler/store.go`:
- Around line 306-318: The build-format read path drops the persisted version
tag filter. In internal/scheduler/store.go:306-318, update loadBuildFormat,
getBuildFormat, GetBuildFormat, and the assignBuildNumber call site around line
246 to select, return, and propagate tagFilter, returning an empty value in
no-row and error branches; in internal/scheduler/buildnumber_handlers.go:35-44,
receive the value from GetBuildFormat and assign it to
api.BuildFormatInfo.VersionTagFilter.
- Around line 280-294: Correct the misleading locking comment near
incrementBuildCounter/assignBuildNumber to state that the counter upsert
acquires the scope row lock and holds it until transaction commit, covering the
remainder of SubmitRun. Do not change the counter behavior or transaction
boundaries; document that this introduces contention across concurrent
submissions for the same project, pipeline, and version scope.

In `@ui/src/lib/buildNumberPreview.ts`:
- Around line 24-25: Update the counter-token parsing near pad and the format
handling at line 44 to consume the complete width token, rejecting malformed
values such as “8junk” or “8:9”. Validate the parsed width against the server’s
bounded width range before passing it to pad, so oversized values cannot trigger
enormous padding.

In `@ui/src/lib/components/BuildSettings.svelte`:
- Around line 26-45: Update the BuildSettings load/state flow around load() to
capture the trimmed requested pipeline and a load generation, invalidating
loaded editor state whenever the input changes. Apply responses only when both
the generation and requested pipeline still match the current input; ignore
stale responses and keep loaded false for null results so save actions at the
affected handlers cannot submit another pipeline’s values.

In `@ui/src/lib/components/DAG.svelte`:
- Around line 144-149: The run list currently omits build_number outside
DAG.svelte. Extend the /api/v1/runs query and RunSummary/list response, add
build_number to the UI Run type, and render it in Sidebar.svelte alongside the
existing run metadata; use the list value directly and do not substitute
RunStatus.BuildNumber, which belongs to the separate polling endpoint.

In `@ui/src/lib/components/DetailsPanel.svelte`:
- Around line 240-243: Update the Publish tab in DetailsPanel and the
DockerPublishCard component to accept and render the selected job status
alongside config and result. Pass $selectedJob.status from the publish-tab call
site, and ensure queued, running, and early-failed jobs display that status even
when docker_publish_result is absent.
- Around line 153-158: Update the selected-job tab state in DetailsPanel so
activeTab resets to logs whenever the job has neither docker_publish_result nor
docker_publish. Keep the Publish button visibility condition and existing
publish behavior unchanged, and ensure the reset occurs when selection changes
so the Publish view cannot render for unavailable jobs.

In `@ui/src/lib/components/DockerPublishCard.svelte`:
- Around line 13-22: Update DockerPublishCard’s displayed registry, repository,
and source values so they are not presented as effective publish values when
they still contain unexpanded build-variable tokens. Prefer using resolved
values persisted in DockerPublishResult; if only configured values are
available, explicitly label the fields as configured values rather than changing
scheduler interpolation behavior.
🪄 Autofix

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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d3e3db07-60e8-42de-824d-e775f153d9f4

📥 Commits

Reviewing files that changed from the base of the PR and between 4b87534 and 66b0d90.

⛔ Files ignored due to path filters (1)
  • ui/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (34)
  • .forge/main.yml
  • .forge/pipeline.yml
  • .forge/scripts/integration-tests.sh
  • .forge/scripts/unit-tests.sh
  • .forge/templates/docker-build.yml
  • cmd/forge/helpers.go
  • cmd/forge/local.go
  • cmd/forge/management.go
  • cmd/forge/remote.go
  • docs/Pipeline-Reference.md
  • internal/api/types.go
  • internal/buildnumber/format.go
  • internal/buildnumber/format_test.go
  • internal/compiler/compiler.go
  • internal/compiler/lint.go
  • internal/pipeline/types.go
  • internal/registryutil/registry.go
  • internal/registryutil/registry_test.go
  • internal/scheduler/buildnumber_handlers.go
  • internal/scheduler/server.go
  • internal/scheduler/store.go
  • internal/store/db.go
  • internal/store/models.go
  • tests/integration/suite_test.go
  • ui/src/lib/api.ts
  • ui/src/lib/buildNumberPreview.ts
  • ui/src/lib/components/BuildSettings.svelte
  • ui/src/lib/components/DAG.svelte
  • ui/src/lib/components/DAGNodes.svelte
  • ui/src/lib/components/DetailsPanel.svelte
  • ui/src/lib/components/DockerPublishCard.svelte
  • ui/src/lib/components/EditorDAG.svelte
  • ui/src/lib/components/PipelineEditor.svelte
  • ui/src/lib/components/ProjectsView.svelte

Comment thread .forge/main.yml Outdated
Comment thread .forge/pipeline.yml Outdated
Comment thread .forge/templates/docker-build.yml Outdated
Comment thread cmd/forge/remote.go
Comment thread cmd/forge/remote.go Outdated
Comment thread ui/src/lib/components/BuildSettings.svelte Outdated
Comment thread ui/src/lib/components/DAG.svelte
Comment thread ui/src/lib/components/DetailsPanel.svelte
Comment thread ui/src/lib/components/DetailsPanel.svelte
Comment on lines +13 to +22
{#if config}
<span class="pc-target">{config.registry}/{config.repository}</span>
{/if}
</div>

{#if config}
<div class="pc-source">
<span class="pc-label">Source</span>
<code>{config.source}</code>
</div>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Do not label unexpanded templates as effective Docker publish values.

The component displays config.registry, config.repository, and config.source directly. internal/scheduler/server.go Lines 1034-1145 interpolates these fields before execution. With build-variable tokens, the card can show ${FORGE_IMAGE} while source_digest and tags_applied describe the resolved tag. Persist resolved values in DockerPublishResult, or label these fields as configured values.

Minimal safe fix
-            <span class="pc-label">Source</span>
+            <span class="pc-label">Configured source</span>
🤖 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 `@ui/src/lib/components/DockerPublishCard.svelte` around lines 13 - 22, Update
DockerPublishCard’s displayed registry, repository, and source values so they
are not presented as effective publish values when they still contain unexpanded
build-variable tokens. Prefer using resolved values persisted in
DockerPublishResult; if only configured values are available, explicitly label
the fields as configured values rather than changing scheduler interpolation
behavior.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/scheduler/webhook.go`:
- Around line 372-376: Add regression coverage around SubmitRun and the webhook
step conversion to verify both build variables are injected after expansion and
before job insertion. Cover webhook, rerun, child-pipeline, and matrix run
paths, and assert the resulting variables on each generated step while
preserving the existing ToAPIStep(nil) behavior.
🪄 Autofix

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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e2e7be54-7ae1-4acb-a56a-da6d5773d735

📥 Commits

Reviewing files that changed from the base of the PR and between 66b0d90 and 1faf0f7.

📒 Files selected for processing (1)
  • internal/scheduler/webhook.go

Comment on lines +372 to +376
steps := make([]api.StepDef, len(pipeline.Steps))
for i, s := range pipeline.Steps {
steps[i] = s.ToAPIStep(nil)
injectSCMMetadata(steps[i].Env, meta)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

fd -e go -e ts -e svelte . -x rg -n -C 8 \
  'FORGE_BUILD_(NUMBER|COUNTER)|buildNumber|buildCounter|ToAPIStep\(|SubmitRun\(' {}

Repository: JBraunsmaJr/Forge

Length of output: 28273


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- candidate files ---'
fd -e go . | rg '(internal/(scheduler|api|compiler)|webhook|store|run)' | head -80

echo '--- ToAPIStep implementation and callers ---'
rg -n -C 18 'func \(s \*Step\) ToAPIStep|ToAPIStep\(' --glob '*.go' .

echo '--- SubmitRun stamping and expansion ---'
rg -n -C 28 'func \(s \*Store\) SubmitRun|FORGE_BUILD_NUMBER|FORGE_BUILD_COUNTER|expand|matrix' --glob '*.go' internal

echo '--- webhook submission path ---'
sed -n '330,455p' internal/scheduler/webhook.go

echo '--- rerun and child submission parameters ---'
rg -n -C 24 'func rerunParams|ParentRunID|ParentJobID|SubmitRun\(' --glob '*.go' internal

Repository: JBraunsmaJr/Forge

Length of output: 50374


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path

files = list(Path(".").rglob("*.go"))
needles = ("FORGE_BUILD_NUMBER", "FORGE_BUILD_COUNTER", "func (s *Store) SubmitRun",
           "func rerunParams", "ParentRunID", "ParentJobID", "ToAPIStep(")

for path in files:
    text = path.read_text(errors="replace")
    if any(n in text for n in needles):
        lines = text.splitlines()
        print(f"--- {path} ---")
        for i, line in enumerate(lines):
            if any(n in line for n in needles):
                lo, hi = max(0, i-3), min(len(lines), i+4)
                print(f"{lo+1}-{hi}")
                print("\n".join(f"{j+1}: {lines[j]}" for j in range(lo, hi)))
PY

Repository: JBraunsmaJr/Forge

Length of output: 16730


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- build-number and environment tests ---'
rg -n -C 12 \
  'FORGE_BUILD_(NUMBER|COUNTER)|BuildNumber|BuildCounterValue|ParentRunID|ParentJobID|matrix|webhook' \
  internal/scheduler/*_test.go internal/agent/*_test.go internal/pipeline/*_test.go

echo '--- webhook submission tests ---'
sed -n '1,260p' internal/scheduler/webhook_submission_test.go

echo '--- webhook handler submission call ---'
sed -n '405,455p' internal/scheduler/webhook.go

echo '--- rerun parameter construction ---'
sed -n '2280,2320p' internal/scheduler/server.go

echo '--- child-pipeline submission call ---'
sed -n '2570,2620p' internal/agent/agent.go

Repository: JBraunsmaJr/Forge

Length of output: 9355


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path

checks = {
    "submit_stamps_number": ("internal/scheduler/store.go", 'step.Env["FORGE_BUILD_NUMBER"] = buildNumber'),
    "submit_stamps_counter": ("internal/scheduler/store.go", 'step.Env["FORGE_BUILD_COUNTER"] = strconv.FormatInt(buildCounterValue, 10)'),
    "submit_expands_before_stamping": ("internal/scheduler/store.go", "steps = expandedSteps"),
    "webhook_submits_steps": ("internal/scheduler/webhook.go", "Steps:            steps"),
    "rerun_sets_parent": ("internal/scheduler/server.go", "ParentRunID:      parentRunID"),
    "child_sets_parent_run": ("internal/agent/agent.go", "ParentRunID:      spec.RunID"),
    "child_sets_parent_job": ("internal/agent/agent.go", "ParentJobID:      spec.JobID"),
}

for name, (filename, needle) in checks.items():
    text = Path(filename).read_text()
    print(f"{name}: {'present' if needle in text else 'MISSING'}")

store = Path("internal/scheduler/store.go").read_text()
expand_pos = store.find("steps = expandedSteps")
stamp_pos = store.find('step.Env["FORGE_BUILD_NUMBER"] = buildNumber')
print("expansion_precedes_stamping:", expand_pos >= 0 and stamp_pos > expand_pos)

test_text = "\n".join(p.read_text(errors="replace") for p in Path("internal").rglob("*_test.go"))
for term in ("FORGE_BUILD_NUMBER", "FORGE_BUILD_COUNTER"):
    print(f"tests_mention_{term}: {term in test_text}")
PY

Repository: JBraunsmaJr/Forge

Length of output: 491


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- webhook SubmitRun call ---'
sed -n '405,445p' internal/scheduler/webhook.go

echo '--- SubmitRun job serialization ---'
sed -n '107,165p' internal/scheduler/store.go

echo '--- ToAPIStep environment merge ---'
sed -n '130,205p' internal/pipeline/types.go

echo '--- all scheduler test names ---'
rg -n '^func Test' internal/scheduler/*_test.go

echo '--- build-variable assertions in tests ---'
rg -n -i 'forge[_-]?build|build[_-]?counter|build[_-]?number' --glob '*_test.go' . || true

Repository: JBraunsmaJr/Forge

Length of output: 7982


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path

webhook = Path("internal/scheduler/webhook.go").read_text()
store = Path("internal/scheduler/store.go").read_text()

submit_start = webhook.find("s.store.SubmitRun(")
submit_end = webhook.find("\n\t})", submit_start)
print("webhook_submit_call_found:", submit_start >= 0)
print("webhook_passes_steps:", submit_start >= 0 and "steps" in webhook[submit_start:submit_end])

stamp = store.find('step.Env["FORGE_BUILD_NUMBER"] = buildNumber')
job_insert = store.find("INSERT INTO jobs")
expand = store.find("steps = expandedSteps")
print("expansion_before_stamp:", 0 <= expand < stamp)
print("stamp_before_job_insert:", 0 <= stamp < job_insert)

tests = "\n".join(p.read_text(errors="replace") for p in Path(".").rglob("*_test.go"))
for path, term in [
    ("webhook_tests", "SubmitWebhookRun"),
    ("rerun_tests", "rerun"),
    ("child_pipeline_tests", "ParentJobID"),
    ("matrix_tests", "Matrix"),
]:
    print(f"{path}:", term in tests)
print("build_env_assertions:", "FORGE_BUILD_NUMBER" in tests or "FORGE_BUILD_COUNTER" in tests)
PY

Repository: JBraunsmaJr/Forge

Length of output: 386


Add regression coverage for build-variable injection. SubmitRun stamps both variables after expansion and before job insertion, so ToAPIStep(nil) is safe. Assert the variables for webhook, rerun, child-pipeline, and matrix 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 `@internal/scheduler/webhook.go` around lines 372 - 376, Add regression
coverage around SubmitRun and the webhook step conversion to verify both build
variables are injected after expansion and before job insertion. Cover webhook,
rerun, child-pipeline, and matrix run paths, and assert the resulting variables
on each generated step while preserving the existing ToAPIStep(nil) behavior.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.forge/pipeline.yml (1)

68-74: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Security Misconfiguration (CWE-732): Incorrect Permission Assignment for Critical Resource

Reachability: External · Exploitability: Moderate

Restrict registry promotion to trusted refs.

The GitHub webhook submits pull-request commits for execution. !branch(main) allows those refs to reach credentialed docker_publish, which can promote the image and delete its source tag. Gate promotion on trusted events or refs, or withhold registry secrets from untrusted refs.

🤖 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 @.forge/pipeline.yml around lines 68 - 74, Update the promote-on-branch
docker_publish step so credentialed registry promotion cannot run for
pull-request or otherwise untrusted refs. Gate the step using the pipeline’s
trusted event/ref condition, or ensure REGISTRY_USERNAME and REGISTRY_PASSWORD
are withheld on untrusted executions, while preserving promotion for approved
trusted refs.
🤖 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 @.forge/pipeline.yml:
- Line 32: Update the depends_on declaration in the pipeline configuration to
use YAMLlint-compliant flow-sequence spacing by removing the spaces inside the
brackets around build-ui, while preserving the dependency value.
- Line 35: Update the unit-tests and integration-tests steps to set FORGE_IMAGE
to the resolved image reference
ghcr.io/jbraunsmajr/forge/forge:test-${FORGE_BUILD_NUMBER}, matching the image
used by the build and push commands and preventing either step from building a
fallback image.
- Line 35: Validate every rendered Docker tag, including the test- prefixed tag,
against Docker tag constraints before build-number assignment and promotion; do
not rely solely on buildnumber.Parse token validation. Reject slash-containing
formats such as release/%counter% and renders exceeding 128 bytes, while
preserving valid Calendar and SemVer formats and the existing requirement that
normal configured renders include %counter%.

---

Outside diff comments:
In @.forge/pipeline.yml:
- Around line 68-74: Update the promote-on-branch docker_publish step so
credentialed registry promotion cannot run for pull-request or otherwise
untrusted refs. Gate the step using the pipeline’s trusted event/ref condition,
or ensure REGISTRY_USERNAME and REGISTRY_PASSWORD are withheld on untrusted
executions, while preserving promotion for approved trusted refs.
🪄 Autofix

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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f550ea57-460a-47d6-a52a-64b425080efd

📥 Commits

Reviewing files that changed from the base of the PR and between 1faf0f7 and 46d5cad.

📒 Files selected for processing (1)
  • .forge/pipeline.yml

Comment thread .forge/pipeline.yml Outdated
Comment thread .forge/pipeline.yml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.forge/scripts/integration-tests.sh:
- Around line 8-13: The FORGE_IMAGE derivation currently overrides externally
supplied images and mishandles an absent FORGE_BUILD_NUMBER. In
.forge/scripts/integration-tests.sh lines 8-13 and .forge/scripts/unit-tests.sh
lines 6-8, update the conditional export to use safe defaults for both
variables, derive the image only when FORGE_IMAGE is unset and
FORGE_BUILD_NUMBER is available, and otherwise leave FORGE_IMAGE unset.
🪄 Autofix

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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4ad6a56e-7eeb-4f37-9aea-8fded8755978

📥 Commits

Reviewing files that changed from the base of the PR and between 46d5cad and a087cec.

📒 Files selected for processing (3)
  • .forge/scripts/integration-tests.sh
  • .forge/scripts/unit-tests.sh
  • tests/integration/suite_test.go

Comment thread .forge/scripts/integration-tests.sh Outdated
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.

Build variables

1 participant