Migrate from ReleaseSourceConfig¶
forge.ReleaseSourceConfig was removed in v0.12.0 and replaced by
forge.Endpoint. If your build broke on
undefined: forge.ReleaseSourceConfig, this page is the whole migration.
Two ways to finish this migration greenly and incorrectly
Most of this change fails loudly: the type is gone, so the compiler finds every call site for you. Two mistakes do not. Both compile, both lint, both pass tests, and neither produces an error at runtime.
- Passing a pre-scoped config subtree to
SettingsFromConfig. It takes your root config, because the endpoint resolves its own section. Hand it a subtree and the adapter looks forgitlab.gitlab.auth.value, finds nothing, resolves no credential, and says nothing about it. - Joining the endpoint's three fields into one string.
Hostlegitimately contains:and/, so anytype:host:namespelling collides with its own payload.
Both are covered below. If you read nothing else, read those two sections.
The short answer¶
The old type carried six fields. Three were connection identity, and they are
what Endpoint keeps. The other three were not, and went to where they already
belonged.
// before, v0.11.x
src := forge.ReleaseSourceConfig{
Type: "gitlab",
Host: "gitlab.example.com",
Owner: "acme",
Repo: "tool",
Private: true,
Params: map[string]string{"url_template": "..."},
}
// after, v0.12.0 and later
ep := forge.Endpoint{
Type: "gitlab",
Host: "gitlab.example.com",
Name: "", // which configured source of this type; see below
}
provider, err := factory(ctx, ep, cfg) // cfg is your ROOT config
rel, err := provider.GetLatestRelease(ctx, "acme", "tool")
Owner and Repo move onto the operation, which already took them.
Where each field went¶
| Was | Now | Why |
|---|---|---|
Type |
Endpoint.Type |
unchanged; it still selects the provider |
Host |
Endpoint.Host |
unchanged; empty still means the provider's default |
Owner |
a parameter of every operation | it was read by nothing. An unread second copy of a value already passed to each method |
Repo |
a parameter of every operation, plus direct's tool_name key |
read once, as direct's tool-name fallback |
Private |
gone; nothing replaces it | read once, by forge-bitbucket. See below |
Params |
the provider's own configuration subtree | read only by direct and forge-bitbucket |
| — | Endpoint.Name |
new. Selects which configured source of a type this is |
Name is the new field, and it is the reason for the change¶
Type and Host together do not always identify a connection. Two credentials
for one host are two sources, and so are two direct sources of a provider that
never looks at Host at all — which is the defect that forced this: an ordinary
configuration could not tell two direct sources apart, and the second silently
got the first one's url_template.
Name scopes the configuration subtree a provider reads: bare <type> when
empty, <type>.<name> otherwise. Leave it empty and you get the behaviour you
had.
It must not contain a dot. Endpoint.Validate rejects one, because a dotted
name nests a level deeper than intended in any config backend treating dots as
path separators.
Trap 1: SettingsFromConfig takes the ROOT config¶
This is the mistake to watch for, and forge's own guidance calls it the
second-most-common mistake against this API.
// WRONG — compiles, lints, resolves no credential, reports nothing
settings := gitlab.SettingsFromConfig(ep, forge.SubConfig(cfg, "gitlab"))
// RIGHT
settings := gitlab.SettingsFromConfig(ep, cfg)
The endpoint resolves its own section, because which subtree a source reads is
part of what the endpoint means. Pre-scope it yourself and the adapter looks
one level too deep — gitlab.gitlab.auth.value — finds nothing, and returns
settings whose credential source contributes nothing.
It can appear to work
Having resolved nothing from configuration, the credential falls through to
the well-known environment variable. So a machine that happens to have
GITLAB_TOKEN set behaves correctly, and the failure only shows up
somewhere that does not — typically CI, typically later, and typically as a
permission error rather than a configuration one.
Nothing checks this at runtime today. Verifying it is your job during the migration: after constructing a provider, confirm a credential actually resolved. Checking what resolved has the pattern.
Trap 2: never join the three fields into one string¶
// WRONG — Host contains ':' and '/', so this collides with its own payload
key := ep.Type + ":" + ep.Host + ":" + ep.Name
// RIGHT — Endpoint is comparable. Use it directly.
seen := map[forge.Endpoint]string{}
seen[ep] = "..."
Keep the three fields separate end to end: separate configuration keys, separate
flags, separate struct fields. A Host of gitlab.example.com:8443/path makes
any inline spelling ambiguous, and a sibling module hit exactly this addressing
a KMS key, where service:keyid is unusable because a key ARN is itself full of
colons.
Endpoint being comparable is the point of the change — it can be a map key, so
you do not need a string form.
Params moved into configuration¶
direct is the provider this affects most. Its seven Params keys became
ordinary configuration under its subtree, joined by tool_name, which Repo
used to supply:
[direct]
url_template = "https://example.com/{tool}/{version}/{tool}_{os}_{arch}.tar.gz"
tool_name = "mytool"
pinned_version = "v1.2.3"
version_url = "https://example.com/{tool}/latest"
version_key = "tag_name"
version_format = "json"
checksum_url_template = "https://example.com/{tool}/{version}/checksums.txt"
signature_url_template = "https://example.com/{tool}/{version}/checksums.txt.sig"
There is no compatibility window. The old Params keys are not read at all.
A tool that upgrades without migrating gets its notice from one diagnostic:
url_template is required for the direct release provider, whose hint names the
configuration key it expects and says the Params route was removed.
Two direct sources are now two endpoints with different Name values, reading
direct.<name> each, which is the case the old type could not express.
Private is gone and nothing replaces it¶
It was read by forge-bitbucket alone and ignored everywhere else, and the
check it fed moved to the operation. When a request is refused and no
credential was resolved, forge-bitbucket attaches guidance naming the
variables to set, because that is what a private repository looks like from
outside.
It is a better error, not an earlier one. Whether the repository you go on to ask about is private is not knowable at construction, because one connection serves both.
If you need to fail early, check for a credential yourself at the layer that actually knows.
A worked example¶
go-tool-base performed this migration in
!422, across
a consumer with several sources and a real configuration stack — 20 files. It
also removed props.ReleaseSource.Params outright rather than shimming it,
which is the same call this module made and for the same reason.
Its reasoning is written up as go-tool-base spec 0192, which is the better read if you are deciding how to migrate rather than copying what changed.
See also¶
- Configuration — every
Endpointfield and every provider key, with its default - Migrate from
ResolveToken— the other removal, and the credential composition this one hands you - Reuse a connection — what
Endpointbeing comparable is for - spec 0008 — D1, D2, D3 and D9, the decisions behind the removal