Skip to content

Use the direct provider

Not every download source is a forge. A tool distributed from a plain web server, an internal artefact store, or a CDN has releases but no API to ask about them. The direct provider covers that case, and ships inside this module because it is the one provider that will never need a vendor SDK.

It is also the reference implementation: it takes the same credential path, uses the same config layout, and runs the same conformance harness a third-party provider should.

import _ "gitlab.com/phpboyscout/go/forge/direct"

Compose the download URL

There is no API, so the asset URL is built from a template. Only url_template is required:

release_source:
  type: direct
  params:
    url_template: "https://dl.example.com/{tool}/{version}/{tool}_{os}_{arch}.{ext}"

Placeholders:

Placeholder Expands to Example
{version} The version as given v1.2.3
{version_bare} Version without a leading v 1.2.3
{os} runtime.GOOS, title-cased Linux
{arch} runtime.GOARCH, with amd64x86_64 x86_64
{tool} The tool name, defaulting to ReleaseSource.Repo mytool
{ext} Archive extension tar.gz

The amd64x86_64 substitution matches what GoReleaser and most release pipelines actually publish, rather than what Go calls the architecture.

Tell it how to find the latest version

With no API, "what is the latest release?" needs an answer from somewhere. Two options — and configuring neither is an error, because silently assuming a version would be worse:

Pin it. Useful for a fixed internal distribution:

params:
  pinned_version: "v1.2.3"

Point at a version endpoint. Plain text by default; JSON, YAML and XML are parsed when version_format says so:

params:
  version_url: "https://dl.example.com/mytool/latest.json"
  version_format: "json"      # json | yaml | xml; omit for plain text
  version_key: "tag_name"     # which field holds the version

Without either, version checks return ErrVersionUnknown — a sentinel that lives in the direct package rather than the shared contract, because it names config keys no forge-backed provider has.

The version endpoint response is capped at 1 MiB.

Checksums and signatures

Because there is no asset listing to search, direct composes those URLs too, opting into both optional capability interfaces:

params:
  checksum_url_template: "https://dl.example.com/{tool}/{version}/checksums.txt"
  signature_url_template: "https://dl.example.com/{tool}/{version}/checksums.txt.sig"

Leave either unset and the provider returns ErrNotSupported for it, so the caller falls back or applies its own policy. Both reads are bounded by the caller-supplied maxBytes.

Credentials

The standard chain applies, with DIRECT_TOKEN as the well-known fallback:

direct:
  auth:
    env: MY_ARTEFACT_TOKEN   # preferred: names a variable

The legacy direct.token scalar still works, mapped onto the literal tier, but the standard layout wins when both are present. See authenticate.

What it does not do

ListReleases returns ErrNotSupported — a URL template cannot be enumerated. GetReleaseByTag synthesises a release for any tag you ask for, because with no API there is nothing to check against; a wrong tag surfaces as a 404 at download time rather than at lookup.