Skip to content

Releases: panter/catladder

v5.1.3

Choose a tag to compare

@github-actions github-actions released this 09 Sep 19:36

Patch Changes

  • GitHub: the semantic-release release job now pushes the release commit and tag over ssh with the release deploy key (CATLADDER_RELEASE_KEY), so the push passes the merge-gating ruleset instead of failing with GH013 … Required status check "catladder ✅" is expected — the changesets path already did. The release commit carries [skip ci] on GitHub so the explicitly dispatched tagged-release run stays the only one, the generated tagged-release workflow gets a per-tag concurrency group, and project doctor reports a committed release workflow that still runs an older release image (regenerate with catenv).

v5.1.2

Choose a tag to compare

@github-actions github-actions released this 07 Sep 13:54

Patch Changes

  • Fix catci crashing with ReferenceError: __dirname is not defined in ES module scope in projects whose root package.json declares "type": "module". The generated .catladder-generated/catci/ folder now carries a sibling package.json pinning it to CommonJS, so the release guard, security audit and npm publish jobs run again on both backends.

v5.1.1

Choose a tag to compare

@github-actions github-actions released this 31 Aug 12:23

Patch Changes

  • fix(github): lowercase the GHCR image paths of mixed-case repositories

    GHCR image repository names may not contain uppercase characters, but
    ${{ github.repository }} interpolates GitHub's display casing. Any
    project whose GitHub owner or repo name has an uppercase letter (common
    for org logins like AcmeCorp) therefore failed every docker job
    client-side, before any network call:

    invalid tag "ghcr.io/AcmeCorp/nautilus/catladder/docker-build:b343b099980e":
    repository name must be lowercase
    

    catladder now resolves the repository from the git remote at generation
    time and writes the lowercased path (ghcr.io/acmecorp/nautilus) into
    both the workflow-level CL_REGISTRY_IMAGE and the jobs.<id>.container.image
    of every containerized job — the latter is resolved before any step
    runs, so it could not have been fixed from a shell step. GHCR serves the
    org under that lowercased namespace, so it is the correct address, not a
    workaround.

    All-lowercase repositories are unaffected: they keep the
    ${{ github.repository }} expression, which stays correct in forks, so
    generated output is byte-identical to before.

    Set pipelines.github.repository when generation cannot see the git
    remote:

    pipelines: { github: { repository: "AcmeCorp/Nautilus" } },

    catladder project doctor now reports a mixed-case repository whose
    generated workflows still carry the expression.

    If you worked around this by hand-editing the generated workflows,
    revert those edits after upgrading
    .envrc runs eval "$(catenv)"
    on every cd into the repo, so regeneration overwrites them anyway.

v5.1.0

Choose a tag to compare

@github-actions github-actions released this 31 Aug 11:55

Minor Changes

  • Review apps of a merge request can now be pinned so they outlive the auto-stop timer (gitlab). Review deploy jobs read their auto_stop_in from the pipeline variable CL_REVIEW_AUTO_STOP; a workflow rule sets it to never while the MR carries the pin label (default catladder::pin-review), so the pin lives on the MR and survives redeploys — unlike gitlab's per-environment pin button, which the next deploy resets. Merging or closing the MR still stops the apps. catladder mr pin / mr unpin manage the label (creating it in the project when missing) and pin triggers a pipeline so the pin takes effect immediately. The previously hardcoded lifetimes are now configurable via top-level autoStop in catladder.ts (review default "1 week", dev default "4 weeks", pinLabelfalse disables the mechanism). GitHub is unaffected: it has no auto-stop, review apps live until the pull request closes.

Patch Changes

  • Fixed the bitwarden vault dropping secrets on a partial write: it rewrote an env/component's whole yaml note from the keys of that one write, so project secrets-set dev:web API_KEY deleted every other secret of dev:web from the vault. Writes are now merged into the existing note, matching the gitlab vault's upsert semantics.
  • project setup now stores the credentials it provisions — the gcloud deploy service account key, the kubernetes deploy credentials — through the secrets vault and from there to every enabled CI backend, exactly like any other secret. Until now it wrote them straight into GitLab project variables: on a project without a GitLab pipeline the setup of a cloud run or kubernetes component died with Error: not found (a 404 from the GitLab API against a host that is not a GitLab), and on a project with a bitwarden vault the credentials silently never reached the vault. The GitLab registry deploy token that kubernetes setup creates is now skipped when no GitLab pipeline is enabled, and a 404 from the GitLab API finally says which call failed against which host.

v5.0.1

Choose a tag to compare

@macrozone macrozone released this 13 Aug 16:44

Patch Changes

  • Changesets releases now create the release entry on the git host (gitlab /-/releases, github /releases) with the changelog as its description — previously only the tag was pushed, so the releases page stayed empty (on the semantic-release path @semantic-release/gitlab did this). The api call never fails the job: the commit and tag are already pushed when it runs, so a missing token only warns.
  • semantic-release on the github backend now creates the entry on the releases page too, via @semantic-release/github (the counterpart of the gitlab publish plugin, which is gitlab-only — on github the release used to end at the tag). Only the release is created: commenting on released pull requests/issues and labelling them stays off, so the release job keeps its contents: write-only permissions. Projects with their own .releaserc are unaffected, as before.

v5.0.0

Choose a tag to compare

@macrozone macrozone released this 13 Aug 16:16

Major Changes

  • customJobs job model: needsStages is removed in favour of semantic requirements — declare requires: [{ capability: "deployment" }] instead of needsStages: [{ stage: "deploy" }] (capabilities: build, qualityGate, deployment, with artifacts, from and strict). Job environment keys are now platform-neutral: on_stoponStop, auto_stop_inautoStopIn, and action is narrowed to start | stop | access. Requirements that consume artifacts (artifacts: true) now fail pipeline generation when no job provides them, instead of silently deploying without them.

  • Cloud Run DATABASE_URL / DATABASE_JDBC_URL now default to dbConnectionStringVariablesMode: "embedded": connection strings contain the component's final values instead of $DB_USER/$DB_PASSWORD placeholders, making them referenceable from other components (${otherComponent:DATABASE_URL}). Embedded mode also respects vars.public overrides of the DB_* vars — a component reusing another component's database via dbBaseName plus DB_PASSWORD: "${owner:DB_PASSWORD}" now gets the owner's password in its connection string (previously the component's own, usually unset, secret was embedded, producing a password-less URL). The deployed runtime values are unchanged for the common cases, since legacy placeholders were expanded at deploy time anyway — but the generated pipeline YAML changes for every project with cloudSql. Set dbConnectionStringVariablesMode: "legacy" to restore the old behaviour; that escape hatch will be removed in a future major.

  • @catladder/pipeline is no longer published to npm. It was always an implementation detail compiled into the CLI; @catladder/cli is the only published package. Projects importing @catladder/pipeline directly must switch to the @catladder/cli exports.

  • Job images are now always built from your repository (jobImages: "repo" behavior); the central image registry mode has been removed. Image definitions are materialized into .catladder-generated/images/, tagged by content hash and built by the pipeline only when missing. Projects still configured with the central mode must drop that setting and commit the materialized image definitions on the next regeneration.

  • Job images slim down. The jobs-testing-chrome image is removed and test/verify jobs now default to jobs-default: if your tests need a browser, point test.jobImage (or verify.jobImage) at an image that carries one — best the official playwright image matched to your dependency, e.g. jobImage: "mcr.microsoft.com/playwright:v1.49.0-jammy" — or declare a project image via images. The failure mode without this is a loud "browser not found" in the test job.

    jobs-default itself is trimmed: base node:22 (was the EOL node:18) with node 20/22/24 pre-installed (was 12–24). Pre-installed node versions are a cache, not a contract — a job with an .nvmrc always gets its version (pre-warmed or nvm installed at runtime), a job without one runs the shipped LTS base, which may bump in future minors. Pin with an .nvmrc if your project depends on a specific node version.

Minor Changes

  • Agent skills: catladder ships agent-facing documentation as skills (catladder-config, catladder-builds, catladder-deploys, catladder-secrets, catladder-releases, catladder-pipelines, catladder-cli with a generated command reference). They are materialized into .claude/skills/ on every generation (cross-agent .agents/skills/ opt-in), so AI coding agents always see documentation matching the installed catladder version.

  • catci, catladder's CI companion: a tree-shaken bundle materialized into .catladder-generated/catci/ on generation, running the release, security-audit and npm-publish logic in CI with plain node. Job images no longer need catladder installed, and CI always runs exactly the version that generated the pipeline.

  • catenv is interactive when a human runs it: attached to a terminal it can now run the gitlab token setup and vault unlock prompts, instead of aborting with a NonInteractiveError mid-wizard. Under direnv, turbo or CI (stdout not a TTY) it stays non-interactive automatically, and --non-interactive forces that on a terminal too. In non-interactive runs a missing gitlab token now fails fast with the remedy ("run catenv once in a terminal") rather than starting a prompt it cannot answer, and the bitwarden unlock prompt is suppressed as well.

  • The catladder store: .catladder-store/store.yml is a committed, non-secret record of machine-fetched facts (currently gcloud project numbers), populated by catladder project setup. It makes Cloud Run URLs deterministic at generation time, so generating a pipeline no longer requires cloud access or authentication.

  • Changesets guardrails: merge-request pipelines get a 🦋 changeset check job reporting what merging would release (changesets added by the MR, everything pending, the resulting version with a changelog preview) — as a warning-only job with an exposed artifact on GitLab (sticky MR comment when GL_TOKEN is available to MR pipelines) and a sticky PR comment on GitHub. The ⚠️ force create release job now releases a patch bump even without pending changesets, as the recovery path for changes merged without one.

  • The github review workflow gains a generated catladder ✅ job that succeeds exactly when every other review job succeeded (needs: all of them, if: always(), skipped counts as failed; continue-on-error jobs like the audit stay non-blocking). It exists to be the one required status check in branch protection: requiring real job names goes stale on every component change — a renamed required job blocks its own PR forever, a new component's jobs are silently not required — while this context never changes. Combined with the repo's "Allow auto-merge" setting this restores gitlab's built-in "merge when pipeline succeeds" on github.

  • GitHub Actions backend: pipelines: { gitlab: true, github: true } generates workflows for both CI systems in parallel from one config, including build, deploy, review-environment and release jobs. Job scripts are externalized into committed files instead of being inlined into the workflow yaml.

  • GitHub environment secrets: secrets are scoped per environment instead of per repository, so stage and prod can hold different values for the same variable. secrets-sync-github takes an --env filter to sync a single environment.

  • Manual gates on GitHub: manually gated jobs (e.g. a prod deploy) and their build closure are routed into a workflow_dispatch "manual tasks" workflow, where each gated job becomes a dropdown choice — GitLab's manual jobs without needing GitHub Environments (Enterprise-only approvals).

  • The pages deploy type now works on the github backend. The deploy job hands the built site to actions/upload-pages-artifact + actions/deploy-pages, targets the github-pages environment and reports the published url from the deploy step, with pages: write / id-token: write granted on the job. The repository's Pages source must be set to "GitHub Actions" once. Per-merge-request previews stay gitlab-only: github serves one site per repository and deploy-pages replaces all of it, so review environments log why they were skipped instead of generating a deploy job.

  • Two new agent skills guide migrations that used to be tribal knowledge: catladder-migrate-release-method walks a project from semantic-release to changesets (or back), including backfilling changesets for everything merged since the last release tag so the changelog and version bump stay correct — asking how to group the changes when the history is large or ambiguous. catladder-migrate-ci-backend guides a move between GitLab CI and GitHub Actions: the blockers to check up front, running both backends in parallel via pipelines, mirroring secrets, the vault and registry consequences, and the manual cleanup a cut-over needs.

  • New npmPackage deploy type: publishes a component to npm, deriving version and dist-tag from the pipeline trigger — tagged releases publish the tag version as latest, branches and merge requests publish 0.0.0-<slug>-<sha> canaries (with next/beta branches getting their own dist-tag). Works in workspace monorepos and authenticates via the NPM_TOKEN secret.

  • npmPackage components can publish to npm without a stored token, using npm trusted publishing (OIDC). On github the publish job now declares id-token: write, and when the workflow can mint an OIDC token catladder skips the .npmrc entirely and lets npm exchange the token for short-lived credentials — provenance is attested automatically. NPM_TOKEN stays supported and still wins when it is set, so gitlab and untrusted workflows are unaffected.

    Publishing moved to its own npm-publish job image, because trusted publishing needs npm >= 11.5.1, which the jobs-default node does not carry.

    To use it, register the package's trusted publisher on npmjs.com with the repository and the workflow filename that publishes it (catladder-release.yml for tagged releases). npm allows one trusted publisher per package, so canary publishes from the main-branch and review workflows still need NPM_TOKEN.

  • New agent skill catladder-migrate-package-manager guides a project from yarn to pnpm (or back). It covers what catladder switches on its own once it detects the package manager — install commands, caches, docker prod install, audit and build/start defaults — and, more importantly, the repository work it does not do: the blockers to check first (meteor is yarn-only, Yarn PnP, yarn plugins), writing pnpm-workspace.yaml before pnpm import so the resolved versions survive the migration, and the fallout to fix locally rather than in a pipeline round-trip. A reference page maps every yarn command and config key to its pnpm equivalent and catalogs the behavi...

Read more