Build your integrationReleases

Publish from a monorepo

Keep several independently versioned Typeship Targets beside your application code and publish each package from one repository workflow.

Several Targets can share one repository while keeping separate versions and releases. Give each Target a non-overlapping directory, then configure the repository's publishing workflow for each package.

You need a Project, write access to the destination repository, the GitHub App installed there, and permission to configure the packages' trusted publishers. Start with Publish your packages for the release model.

Choose a repository layout

Typeship supports three common layouts. The release model is identical in each; only the Delivery repository and directory change.

LayoutUse it whenExample
Source and generated packages togetherThe API team owns application and SDK changes in one review graph.apps/api, packages/sdk, packages/cli
Dedicated generated-products monorepoOne platform team owns every public client, separate from application deploys.packages/typescript, packages/python, tools/cli
One repository per TargetPackage permissions, release cadence, or external contributors differ.acme/sdk-ts, acme/sdk-python, acme/cli

Do not split repositories merely to get independent versions. Target identity, not repository identity, is the release boundary.

apps/api/                 # your source application
openapi.yaml              # the Definition entrypoint
packages/typescript/      # Target A
packages/python/          # Target B
tools/acme/               # Target C (CLI)
.typeship/targets/        # one manifest per Target
.github/workflows/typeship-release.yml

Configure non-overlapping Deliveries

[
  {
    "name": "Acme TypeScript SDK",
    "generator": "typescript-sdk",
    "deliveries": [{
      "kind": "repository",
      "repository": {"provider": "github", "identifier": "acme/platform"},
      "directory": "packages/typescript",
      "package_name": "@acme/sdk",
      "publish_on_merge": true
    }]
  },
  {
    "name": "Acme Python SDK",
    "generator": "python-sdk",
    "deliveries": [{
      "kind": "repository",
      "repository": {"provider": "github", "identifier": "acme/platform"},
      "directory": "packages/python",
      "package_name": "acme-python",
      "publish_on_merge": true
    }]
  }
]

A Target owns its generated directory. Typeship rejects the repository root beside any other Target, identical directories, and parent/child overlaps such as packages plus packages/python. Sibling paths are safe.

Review and merge independently

Each changed Target has one rolling Draft PR. Several Definition commits may update it before the team is ready to release. Merge only the package you want to make Current; the others continue accumulating changes against their own Current releases.

For example, suppose the TypeScript SDK is Current at 2.4.0 and the Python SDK is Current at 1.8.2:

EventTypeScript TargetPython Target
Monday: add paginationDraft becomes 2.5.0Draft becomes 1.9.0
Tuesday: improve pagination docsSame Draft updates; still 2.5.0Same Draft updates; still 1.9.0
Wednesday: remove a response fieldSame Draft now requires 3.0.0Same Draft now requires 2.0.0
Thursday: merge only TypeScript3.0.0 becomes Current and publishes1.8.2 remains Current; Draft 2.0.0 stays open
Next Tuesday: merge PythonNo change2.0.0 becomes Current and publishes

The three source commits became one reviewed TypeScript release, not three package releases. Python used the same source history but kept its own review date, version, and registry outcome.

The first publish-enabled Draft installs the root release and republish workflows plus VERSIONING.md. Those files then belong to the repository: Typeship leaves existing copies alone, so a sibling Draft cannot roll back a team's workflow customization. Each later Draft changes only its own .typeship/targets/<target-id>.json manifest and generated directory. After GitHub records the merge, Typeship dispatches one release run with that exact Target, version, and accepted commit; publishing uses that accepted commit.

Integrate the workspace

Add generated JavaScript packages to the root workspaces/pnpm/Yarn configuration and keep the lockfile at the repository root if that is already the monorepo convention. The publishing workflow runs inside the Target directory, so package-local build and test scripts remain the contract. Python and Go Targets can coexist without joining the JavaScript workspace.

Shared lockfiles, workspace configuration, and root build orchestration remain repository-owned. Typeship snapshots and merges each Target directory; it does not infer that a package dependency also requires a root lockfile change. Commit a required shared-file update normally on that Target's rolling Draft, and configure the root workspace install, build, or policy status in checks.repository_required. The exact Draft cannot become ready until each named status reports success.

Required checks are evaluated per Target head. A shared dependency failure blocks the affected Target even when a sibling is green, and a failure on one Target does not make another Target's evidence reusable. Configure the same named repository check on every Target that depends on it.

When a sibling Draft merges, the destination default branch advances. Typeship re-integrates other rolling Drafts from that new default commit, while continuing to snapshot only their own Target directories. This updates their starting commit and reruns their checks without claiming the merged sibling package, shared lockfile, or root configuration as generated files.

Avoid regeneration loops: point the Project Definition at authored API source, never at a generated package file; ignore typeship/update-* branches in source-trigger automation; and do not make a package publish update the Definition version. OpenAPI info.version is API metadata, not the Target's package version.

When one source change affects several Targets, Typeship updates each rolling Draft independently. Teams can merge those PRs together in a release train or across different days. There is no cross-Target version transaction: a failed Python publication does not block a successful TypeScript publication.

Configure trusted publishers

Registry trust is attached to the repository and workflow filename, not to Typeship:

  1. Configure each npm or PyPI package to trust acme/platform and typeship-release.yml.
  2. Protect the typeship-release environment. Use required reviewers when publication needs a human gate after merge.
  3. Require package tests and Typeship – release readiness before merging each Draft.
  4. Keep custom application and orchestration code outside generated Target directories.

Go submodules use directory-prefixed tags such as packages/go/v1.4.0. The generated workflow derives the prefix from the Target manifest.

For AI agents

List all Targets before choosing a directory. Reuse a Target when package identity and release history should remain the same; create another Target only for an independent product. Never resolve a directory conflict by moving or deleting an existing Target without explicit authorization.

Move from separate repositories

Changing a Delivery repository or directory opens an updated rolling Draft and invalidates the old destination candidate. It does not rewrite release history. Configure trusted publishers for the new repository before enabling publish on merge, then merge the first Draft there to establish the new destination baseline.

Troubleshoot one Target

  • No workflow after the first merge: open the Target and retry the pending Publication. Typeship dispatches the installed republish workflow with the exact accepted commit.
  • Wrong package selected: compare the Target's manifest directory and package_name with the Delivery; never edit the manifest as configuration.
  • Workspace install fails: run the package's normal root workspace install locally and commit any repository-owned lockfile change in a follow-up review.
  • Version already exists: compare the reported artifact digest. Identical bytes are idempotent success; different bytes require a new version.
  • Only one Target should release: merge only that Target's Draft. Unmerged siblings continue accumulating against their own Current.

Require workspace checks

Keep shared lockfiles, workspace configuration, and repository workflows outside the Target’s directory. Configure package checks to require existing workspace checks on every relevant Draft head. Customer commands run inside the Target’s package directory; repository-required checks must already have a workflow. Preserve the complete checks value when adding a requirement.

On this page