Skip to content

feat(#5712)!: add forge URL fields to repos.yaml manifest - #5713

Merged
ggallen merged 1 commit into
mainfrom
agent/5712-forge-url-fields
Jul 29, 2026
Merged

feat(#5712)!: add forge URL fields to repos.yaml manifest#5713
ggallen merged 1 commit into
mainfrom
agent/5712-forge-url-fields

Conversation

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor

Summary

Add explicit url fields to the forge section in repos.yaml so the manifest is fully self-contained about which forge instance it targets. This unblocks self-hosted GitLab (e.g. gitlab.cee.redhat.com) and GitHub Enterprise Server users.

  • forge.github.url defaults to https://github.com when unset
  • forge.gitlab.url is required (no default) when GitLab repos are present
  • Both URLs are validated as HTTPS in Validate()
  • ForgeClientFactory wired to use manifest URLs, with GITLAB_API_URL / GITHUB_API_URL env vars kept as fallback for callers without a manifest (e.g. repos init)
  • For GitHub Enterprise Server, the REST API URL is derived from the instance URL (<url>/api/v3)

Related Issue

Part of #5700 (forge section redesign). Follows PR #5701 which restructured the forge section.

Changes

  • internal/repos/manifest.go: Added URL field to GitHubForgeInfra and GitLabForgeInfra, validation logic in Validate(), and DefaultGitHubURL constant
  • internal/cli/forge_client.go: Updated newForgeClient and newForgeClientFactory to accept and use manifest forge URLs, with env var fallback
  • internal/cli/github_client.go: Added githubAPIURL() helper to derive GHES API URLs from instance URLs
  • internal/cli/repos.go: Updated all newForgeClientFactory call sites to pass manifest's ForgeSection
  • internal/cli/foreign.go: Updated newGitHubLiveClient calls with empty URL (no manifest available)
  • Test files: Added URL validation tests, YAML round-trip tests, and updated existing tests that use GitLab to include required URL field

Testing

  • All internal/repos/... tests pass (including new URL validation tests)
  • All forge-related CLI tests pass
  • Secret scan passed
  • go vet and go build ./... pass
  • Pre-existing TestStartFetchService_* failures confirmed unrelated (network issue in sandbox)

Closes #5712

Post-script verification

  • Branch is not main/master (agent/5712-forge-url-fields)
  • Secret scan passed (gitleaks — b5a13f80343de5574d0f7764a9ec6edc37092830..HEAD)
  • PR body secret scan passed (gitleaks — no-git)
  • Pre-commit hooks passed (authoritative run on runner)
  • Tests ran inside sandbox

@fullsend-ai-coder
fullsend-ai-coder Bot requested a review from a team as a code owner July 29, 2026 12:44
@fullsend-ai-coder fullsend-ai-coder Bot added the ready-for-review Triggers review agent dispatch label Jul 29, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 29, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 12:46 PM UTC · Completed 1:06 PM UTC
Commit: 264dfe7 · View workflow run →

@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.95402% with 7 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/cli/github_client.go 66.66% 1 Missing and 2 partials ⚠️
internal/cli/forge_client.go 90.00% 2 Missing ⚠️
internal/cli/repos.go 83.33% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review

Reason: stale-head

The review agent reviewed commit 7c713c25888196cbe5a83e637157e2ad37612c95 but the PR HEAD is now 62dcc253758da07519e2cc20718c8e802cd57d42. This review was discarded to avoid approving unreviewed code.

Previous run

Review

Findings

All prior medium/low findings from the previous review have been addressed in this revision:

  • [logic-error] (was medium) — repos init now correctly wires --forge-url into ForgeClientFactory via ForgeSectionFromURL().
  • [side-effect] (was low) — Validate() no longer mutates the receiver; uses a local variable for GitHub URL defaulting.
  • [error-handling] (was low) — buildManifest() now appends a clear TODO message and leaves the URL empty, producing a clean validation error.

Low

  • [SSRF / Missing transport-layer protection] internal/forge/github/github.go — The GitHub LiveClient.WithBaseURL() accepts any URL without scheme validation, unlike GitLab's validateBaseURL(). The manifest path is protected by Validate() which enforces HTTPS before URLs reach the client, so this is not an active vulnerability. Adding transport-layer validation to WithBaseURL() would be a defense-in-depth improvement matching the GitLab client.

  • [parameter-naming-inconsistency] internal/cli/github_client.go — The forge instance URL parameter uses different names across related functions: manifestURL in newGitHubLiveClient, baseURL in newForgeClient, and instanceURL in githubAPIURL. Each name carries distinct semantic meaning at its abstraction level, but standardizing would improve readability.

Previous run (2)

Review

Findings

All prior high/medium findings from the previous review have been addressed in this revision. Two prior low findings ([stale-docs] in repos-management.md and repos-init.md) are now also resolved — the plan docs have been updated with the new URL fields.

Medium

  • [logic-error] internal/cli/repos.go:79repos init creates the ForgeClientFactory with an empty repos.ForgeSection{}, so the --forge-url flag value is never wired into the API client used during init's own repo discovery calls. When a user runs repos init --forge gitlab --forge-url https://gitlab.example.com my-org, the discovery API calls will target gitlab.com (or whatever GITLAB_API_URL is set to) instead of the self-hosted instance, causing discovery to fail or return wrong results. The --forge-url value is correctly written into the generated manifest but not used for init's live API calls.
    Remediation: Construct a partial ForgeSection from cfg.forgeURL and cfg.forge before passing it to newForgeClientFactory.

Low

  • [side-effect] internal/repos/manifest.go:469Validate() mutates the receiver by defaulting m.Forge.GitHub.URL to DefaultGitHubURL when empty. Conventionally, a Validate method does not modify the receiver. Consider moving the defaulting to a separate ApplyDefaults step or applying it at parse time.

  • [error-handling] internal/repos/init.go:478 — When --forge-url is omitted for GitLab, buildManifest uses the placeholder "# TODO: set GitLab instance URL". This YAML comment-like string stored as a scalar value produces confusing validation errors later (forge.gitlab.url must be a valid HTTPS URL, got "# TODO: set GitLab instance URL"). A dedicated sentinel or early error would be clearer.

  • [parameter-naming-inconsistency] internal/cli/github_client.go — The forge instance URL parameter uses three different names: manifestURL in newGitHubLiveClient, baseURL in newForgeClient, and forgeURL in the factory helper. Standardizing on one name (e.g., baseURL) would improve readability.


Labels: PR adds forge URL fields to the repos.yaml manifest schema and updates CLI, install, and init code paths

Previous run (3)

Review

Findings

All prior high/medium findings from the previous review have been addressed in this revision:

  • [consumer-completeness] (was high) — buildManifest now correctly sets forge.gitlab.url when forge is GitLab, with a TODO placeholder when --forge-url is not provided.
  • [edge-case] (was medium) — githubAPIURL() now normalizes trailing slashes with strings.TrimRight before comparing against DefaultGitHubURL.
  • [stale-reference] (was medium) — TestInit_SingleRepo_GitLabForge now calls Validate() on the generated manifest.
  • [breaking-change-unmarked] (was medium) — PR title correctly carries the ! suffix.
  • [doc-comment-stale] (was medium) — Validate() doc-comment updated to reflect new URL requirements.
  • [stale-docs] (was medium ×2) — Documentation updated with forge.gitlab.url example and manifest-first guidance.

Low

  • [side-effect] internal/repos/manifest.go:472Validate() mutates the receiver by defaulting m.Forge.GitHub.URL to DefaultGitHubURL when empty. Conventionally, a Validate method does not modify the receiver. Consider moving the defaulting to a separate ApplyDefaults step or applying it at parse time.

  • [insufficient-url-validation] internal/repos/manifest.go:475 — Forge URL validation does not reject URLs containing userinfo (e.g., https://attacker@ghes.example.com), query parameters, or fragment components. The manifest author is a trusted operator, so the practical risk is low, but rejecting non-empty u.User, u.RawQuery, and u.Fragment would be good defense-in-depth.

  • [parameter-naming-inconsistency] internal/cli/github_client.go:15 — The forge instance URL parameter uses three different names: manifestURL in newGitHubLiveClient, baseURL in newForgeClient, and forgeURL in the factory helper. Standardizing on one name (e.g., instanceURL) would improve readability.

  • [yaml-struct-tag-inconsistency] internal/repos/manifest.go:63GitHubForgeInfra.URL has omitempty but GitLabForgeInfra.URL does not. The asymmetry is defensible (GitHub is optional, GitLab is required), but a brief comment explaining the rationale would help.

  • [missing-cli-validation] internal/cli/repos.go:189--forge-url is passed through without validation; the generated manifest is not validated before writing. Invalid URLs are only caught when a subsequent command loads and validates the manifest. Consider calling Validate() before writing.

  • [stale-docs] docs/plans/repos-management.md:502 — The GitHubForgeInfra struct snippet in the plan doc is missing the new URL field. The PR updates other parts of this file but leaves this snippet stale.

  • [stale-docs] docs/plans/repos-init.md:63 — The repos init plan doc flags list and InitConfig struct are missing the new --forge-url / ForgeURL field.

  • [error-handling] internal/repos/init.go:486 — When --forge-url is omitted for GitLab, buildManifest uses the placeholder "# TODO: set GitLab instance URL". This fails validation correctly, but a more explicit sentinel would be clearer.


Labels: PR adds forge URL fields to the repos.yaml manifest schema and updates CLI, install, and init code paths

Previous run (4)

Review

Findings

High

  • [consumer-completeness] internal/repos/init.go:482Init() does not set forge.gitlab.url when generating a GitLab manifest. The comment on line 482 ("GitLab uses an empty section (no required fields)") is now stale. After this PR, repos init --forge gitlab produces a manifest that immediately fails validation with "forge.gitlab.url is required when GitLab repos are present". GHES users also have no way to pass their instance URL through repos init.
    Remediation: Update init.go to accept a forge URL parameter, set manifest.Forge.GitLab.URL when forge is GitLab, and update the stale comment.

Medium

  • [breaking-change-unmarked] internal/repos/manifest.go:490 — Adding forge.gitlab.url as a required field rejects previously accepted input (existing GitLab manifests without this field). Per COMMITS.md this is a breaking change and the PR title must carry the ! suffix: feat(#5712)!: .... A BREAKING CHANGE: trailer is also required in the commit message.

  • [edge-case] internal/cli/github_client.go:23githubAPIURL() compares against the literal "https://github.com". A trailing slash ("https://github.com/") bypasses the check and incorrectly constructs an API URL instead of returning "" for github.com's default endpoint. The Validate() HTTPS check accepts trailing slashes without normalizing.
    See also: [magic-string] finding at this location — use repos.DefaultGitHubURL instead of the string literal.

  • [stale-reference] internal/repos/init_test.go:1215TestInit_SingleRepo_GitLabForge does not call Validate() on the generated manifest, masking the init.go consumer-completeness bug.

  • [doc-comment-stale] internal/repos/manifest.go:380Validate() doc-comment states "the gitlab section has no required fields" but forge.gitlab.url is now required when GitLab repos are present.

  • [stale-docs] docs/guides/getting-started/repo-management.md:70 — Multi-forge YAML example is missing the forge.gitlab section with the now-required url field.

  • [stale-docs] docs/guides/getting-started/repo-management.md:91 — Instructions recommend GITLAB_API_URL env var for self-hosted GitLab; forge.gitlab.url in the manifest is now the primary method.

Low

  • [magic-string] internal/cli/github_client.go:21 — Hard-codes "https://github.com" instead of using repos.DefaultGitHubURL.
  • [yaml-struct-tag-inconsistency] internal/repos/manifest.go:63GitHubForgeInfra.URL has omitempty but GitLabForgeInfra.URL does not.
  • [missing-docs] docs/cli/repos.md:371 — CLI reference doesn't document new forge.github.url / forge.gitlab.url fields.
  • [stale-docs] docs/plans/repos-management.md:30 — Plan doc schema example and Validate() description missing URL fields.
  • [input-validation] internal/cli/github_client.go:22githubAPIURL() does not reject forge URLs with path components that could misroute API calls.

Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR

fullsend-ai-review[bot]

This comment was marked as outdated.

@ggallen ggallen changed the title feat(#5712): add forge URL fields to repos.yaml manifest feat(#5712)!: add forge URL fields to repos.yaml manifest Jul 29, 2026
@ggallen
ggallen force-pushed the agent/5712-forge-url-fields branch from 264dfe7 to 4f77264 Compare July 29, 2026 13:17
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown

Site preview

Preview: https://7ed9c682-site.fullsend-ai.workers.dev

Commit: ed3145de77fad11decaafd737f9bad156cd6a8a9

@ggallen

ggallen commented Jul 29, 2026

Copy link
Copy Markdown
Member

/fs-review

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 29, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 1:27 PM UTC · Completed 1:43 PM UTC
Commit: 4f77264 · View workflow run →

@fullsend-ai-review
fullsend-ai-review Bot dismissed their stale review July 29, 2026 13:43

Superseded by updated review

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added ready-for-merge All reviewers approved — ready to merge component/install CLI install and app setup type/feature New capability request go Pull requests that update go code labels Jul 29, 2026
@ggallen
ggallen force-pushed the agent/5712-forge-url-fields branch from 4f77264 to b52822d Compare July 29, 2026 13:50
@ggallen

ggallen commented Jul 29, 2026

Copy link
Copy Markdown
Member

/fs-review

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 29, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 1:52 PM UTC · Completed 2:10 PM UTC
Commit: b52822d · View workflow run →

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added requires-manual-review Review requires human judgment and removed ready-for-merge All reviewers approved — ready to merge labels Jul 29, 2026
@ggallen
ggallen force-pushed the agent/5712-forge-url-fields branch from b52822d to fb60258 Compare July 29, 2026 14:21
@ggallen

ggallen commented Jul 29, 2026

Copy link
Copy Markdown
Member

/fs-review

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 29, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 2:24 PM UTC · Completed 2:40 PM UTC
Commit: fb60258 · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot added ready-for-merge All reviewers approved — ready to merge and removed requires-manual-review Review requires human judgment labels Jul 29, 2026
@ggallen

ggallen commented Jul 29, 2026

Copy link
Copy Markdown
Member

/fs-review

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 29, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 6:28 PM UTC · Completed 6:45 PM UTC
Commit: 7c713c2 · View workflow run →

@fullsend-ai-review

Copy link
Copy Markdown

/fs-review

Add explicit `url` fields to GitHubForgeInfra and GitLabForgeInfra
structs so the repos.yaml manifest is self-contained about which
forge instance it targets. This is critical for self-hosted GitLab
(e.g. gitlab.cee.redhat.com) and GitHub Enterprise Server.

- forge.github.url defaults to https://github.com in Validate()
- forge.gitlab.url is required (no default) when GitLab repos present
- Both URLs validated as HTTPS with no path, userinfo, query, or
  fragment components
- ForgeClientFactory wired to use manifest URLs, with GITLAB_API_URL
  and GITHUB_API_URL env vars kept as fallback
- GitHub Enterprise Server API URL derived from instance URL
- Init(): set forge.gitlab.url when generating GitLab manifests,
  add --forge-url CLI flag
- githubAPIURL(): normalize trailing slashes, use DefaultGitHubURL
  constant

BREAKING CHANGE: forge.gitlab.url is now required when GitLab repos are
present in the manifest. Existing GitLab manifests must add a
forge.gitlab section with the instance URL:

  forge:
    gitlab:
      url: https://gitlab.example.com

Closes #5712

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Greg Allen <gallen@redhat.com>
@ggallen
ggallen force-pushed the agent/5712-forge-url-fields branch from 62dcc25 to ed3145d Compare July 29, 2026 20:04
@ggallen
ggallen added this pull request to the merge queue Jul 29, 2026
Merged via the queue into main with commit fa3c959 Jul 29, 2026
17 of 20 checks passed
@ggallen
ggallen deleted the agent/5712-forge-url-fields branch July 29, 2026 20:57
ggallen pushed a commit that referenced this pull request Jul 30, 2026
Add --forge-url examples and GitLab onboarding guidance to the
getting-started repo management guide. The guide previously showed
only GitHub examples for repos init; now includes a GitLab example
with --forge-url and explains the flag is required for GitLab
(no default URL, unlike GitHub which defaults to
https://github.com). The Multi-forge manifests section now shows
how to use --forge-url when initializing a GitLab manifest.

Add a cross-reference annotation to ADR 0057 linking to PR #5713
which added forge URL fields (forge.github.url, forge.gitlab.url)
to the manifest schema.

Note: repos add does not have --forge-url in the code (it reads
the forge URL from the existing manifest), so the plan doc change
requested in the issue was skipped to avoid incorrect docs.

Note: pre-commit could not run in the sandbox (network error
fetching hooks). The post-script runs authoritative pre-commit.

Closes #5740
ggallen added a commit that referenced this pull request Jul 30, 2026
Add --forge-url examples and GitLab onboarding guidance to the
getting-started repo management guide. The guide previously showed
only GitHub examples for repos init; now includes a GitLab example
with --forge-url and explains the flag is required for GitLab
(no default URL, unlike GitHub which defaults to
https://github.com). The Multi-forge manifests section now shows
how to use --forge-url when initializing a GitLab manifest.

Add a cross-reference annotation to ADR 0057 linking to PR #5713
which added forge URL fields (forge.github.url, forge.gitlab.url)
to the manifest schema.

Note: repos add does not have --forge-url in the code (it reads
the forge URL from the existing manifest), so the plan doc change
requested in the issue was skipped to avoid incorrect docs.

Note: pre-commit could not run in the sandbox (network error
fetching hooks). The post-script runs authoritative pre-commit.

Closes #5740

Signed-off-by: Greg Allen <gallen@redhat.com>
Signed-off-by: Claude <noreply@anthropic.com>
Signed-off-by: Greg Allen <gallen@redhat.com>
ggallen added a commit that referenced this pull request Jul 30, 2026
Add --forge-url examples and GitLab onboarding guidance to the
getting-started repo management guide. The guide previously showed
only GitHub examples for repos init; now includes a GitLab example
with --forge-url and explains the flag is required for GitLab
(no default URL, unlike GitHub which defaults to
https://github.com). The Multi-forge manifests section now shows
how to use --forge-url when initializing a GitLab manifest.

Add a cross-reference annotation to ADR 0057 linking to PR #5713
which added forge URL fields (forge.github.url, forge.gitlab.url)
to the manifest schema.

Note: repos add does not have --forge-url in the code (it reads
the forge URL from the existing manifest), so the plan doc change
requested in the issue was skipped to avoid incorrect docs.

Note: pre-commit could not run in the sandbox (network error
fetching hooks). The post-script runs authoritative pre-commit.

Closes #5740

Signed-off-by: Greg Allen <gallen@redhat.com>
Signed-off-by: Claude <noreply@anthropic.com>
Signed-off-by: Greg Allen <gallen@redhat.com>
ggallen added a commit that referenced this pull request Jul 30, 2026
Add --forge-url examples and GitLab onboarding guidance to the
getting-started repo management guide. The guide previously showed
only GitHub examples for repos init; now includes a GitLab example
with --forge-url and explains the flag is required for GitLab
(no default URL, unlike GitHub which defaults to
https://github.com). The Multi-forge manifests section now shows
how to use --forge-url when initializing a GitLab manifest.

Add a cross-reference annotation to ADR 0057 linking to PR #5713
which added forge URL fields (forge.github.url, forge.gitlab.url)
to the manifest schema.

Update cli-internals.md command tree with --forge-url and three
new flags from PR #5747 (--mint-url, --inference-region,
--fullsend-ref).

Note: repos add does not have --forge-url in the code (it reads
the forge URL from the existing manifest), so the plan doc change
requested in the issue was skipped to avoid incorrect docs.

Closes #5740

Signed-off-by: Greg Allen <gallen@redhat.com>
Signed-off-by: Claude <noreply@anthropic.com>
Signed-off-by: Greg Allen <gallen@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/install CLI install and app setup go Pull requests that update go code ready-for-merge All reviewers approved — ready to merge ready-for-review Triggers review agent dispatch type/feature New capability request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

repos.yaml: add forge URL fields for self-hosted instance support

1 participant