Contributing
Prerequisites
- Bun 1.3.x (the repo pins
bun@1.3.13). dprintfor formatting (invoked viabun run fmt).
bun installMonorepo layout
Bun workspaces + Turborepo. Packages live under packages/*:
packages/
core/ @actup/core — engine, no host networking
provider-github/ @actup/provider-github
provider-gitlab/ @actup/provider-gitlab
provider-gitea/ @actup/provider-gitea
providers/ @actup/providers — host→provider registry
cli/ @actup/cli — the `actup` binaryEach package exports from ./src/index.ts, uses Node subpath imports (#* → ./src/*, #pkg → ./package.json), and depends on siblings via workspace:*. @actup/core/src/index.ts re-exports the whole public surface (action-ref, cache, caching-provider, config, discovery, engine, error, http, parser, policy, provider, resolution, version).
Quality gates
Turbo runs each task across all packages.
bun run typecheck # turbo run typecheck → tsc --noEmit per package
bun test # turbo run test → bun test per package
bun run fmt # dprint fmt .Run targeted tests during development from a package directory or with bun test <path>; prefer focused runs over the full suite.
Code standards (from CLAUDE.md)
- No
any, no non-null!, noastype assertions. The only sanctionedasis theSha40smart-constructor after its regex check. - Model domain with discriminated unions; parse inputs at boundaries.
- No lint-suppression annotations (
@ts-ignore,eslint-disable, etc.). Fix root causes. - Errors flow through the typed
Result/ActupErrormodel, not thrown control flow at boundaries.
How to add a provider
A provider is a host-metadata source implementing the Provider contract from @actup/core (packages/core/src/provider.ts):
interface Provider {
kind(): ProviderKind; // 'github' | 'gitlab' | 'gitea'
host(): string;
getVersions(repo: ActionRepoId): Promise<Result<VersionSet>>;
resolveRefToSha(repo: ActionRepoId, ref: string): Promise<Result<Sha40>>;
getDefaultBranch(repo: ActionRepoId): Promise<Result<string>>;
}Steps:
- Scaffold a package under
packages/provider-<host>/mirroring an existing one (provider-githubis the reference):package.json(@actup/provider-<host>,private,exports/importsmaps,@actup/core+zoddeps,build/typecheck/testscripts),tsconfig.json,src/index.ts,tests/index.test.ts. Add it to the workspace by virtue ofpackages/*. - Implement the contract. Construct from
ProviderOptions(host, optionalapiBase,token,maxTagsPerRepo,apiMode). Do all network access throughhttpJson(schema, opts)from@actup/core— pass a zod schema for the response, your auth headers, and aclassifyStatusfor host-specific quirks (e.g.classify429(host)for rate limits). Never throw across the boundary; returnResult. Mint SHAs only viasha40(). - Build a
VersionSetfrom fetched tags/branches (VersionSet.build(...)) soresolution.tscan evaluate refs. - Register it. In
packages/providers/src/index.ts, add the newProviderKindto themake()switch, the default token env inDEFAULT_TOKEN_ENV, and any host-label heuristics inguessKind(). TheProviderKindunion itself lives inpackages/core/src/provider.ts. - Test behavior. Add
tests/index.test.tscovering version resolution, SHA resolution, and the error mappings (auth,notFound,rateLimit,network). Tests should assert semantically correct behavior; a failing test that exposes a real bug is acceptable. - Run
bun run typecheck,bun test,bun run fmtbefore opening a PR.
VCS
Do not add bot/assistant attribution to commits or PRs. Keep changes minimal and surgical. See architecture for the data flow your provider plugs into.