Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ on:
force:
description: Force a release even when there are release-blockers (optional)
required: false
workspace:
description: Named Craft release workspace to prepare and publish
required: false

# For external repos to call this workflow
workflow_call:
Expand Down Expand Up @@ -51,6 +54,10 @@ on:
type: string
required: false
default: '.'
workspace:
description: Named Craft release workspace to prepare and publish
type: string
required: false
craft_config_from_merge_target:
description: Use the craft config from the merge target branch
type: string
Expand Down Expand Up @@ -122,6 +129,7 @@ jobs:
with:
version: ${{ github.event.inputs.version }}
force: ${{ github.event.inputs.force }}
workspace: ${{ github.event.inputs.workspace }}

# For external repos: use published action
- name: Prepare release
Expand All @@ -139,4 +147,5 @@ jobs:
git_user_name: ${{ inputs.git_user_name }}
git_user_email: ${{ inputs.git_user_email }}
path: ${{ inputs.path }}
workspace: ${{ inputs.workspace }}
craft_config_from_merge_target: ${{ inputs.craft_config_from_merge_target }}
33 changes: 30 additions & 3 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ inputs:
description: The path that Craft will run inside
required: false
default: '.'
workspace:
description: Named Craft release workspace to prepare and publish
required: false
craft_config_from_merge_target:
description: Use the craft config from the merge target branch
required: false
Expand Down Expand Up @@ -68,6 +71,21 @@ outputs:
runs:
using: 'composite'
steps:
- name: Validate workspace
shell: bash
env:
PATH_INPUT: ${{ inputs.path }}
WORKSPACE: ${{ inputs.workspace }}
run: |
if [[ -n "$WORKSPACE" && "$PATH_INPUT" != '.' ]]; then
echo "::error::The path and workspace inputs cannot be used together."
exit 1
fi
if [[ -n "$WORKSPACE" ]] && ! node -e 'process.exit(/^(?!\.{1,2}$)(?!__proto__$)(?!-)[A-Za-z0-9_.-]+$/.test(process.env.WORKSPACE) ? 0 : 1)'; then
echo "::error::Workspace names must use only ASCII letters, digits, periods, underscores, and hyphens."
exit 1
fi

- id: killswitch
name: Check release blockers
shell: bash
Expand Down Expand Up @@ -162,6 +180,7 @@ runs:
CRAFT_CONFIG_FROM_MERGE_TARGET: ${{ inputs.craft_config_from_merge_target }}
MERGE_TARGET: ${{ inputs.merge_target }}
VERSION: ${{ inputs.version }}
WORKSPACE: ${{ inputs.workspace }}
working-directory: ${{ inputs.path }}
run: |
# Ensure we have origin/HEAD set
Expand All @@ -172,6 +191,9 @@ runs:
if [[ "$CRAFT_CONFIG_FROM_MERGE_TARGET" == 'true' && -n "$MERGE_TARGET" ]]; then
CRAFT_ARGS=(--config-from "$MERGE_TARGET")
fi
if [[ -n "$WORKSPACE" ]]; then
CRAFT_ARGS+=("--workspace=$WORKSPACE")
fi

# Version is optional - if not provided, Craft uses versioning.policy from config
VERSION_ARG=()
Expand All @@ -187,8 +209,13 @@ runs:
working-directory: ${{ inputs.path }}
env:
CRAFT_LOG_LEVEL: Warn
WORKSPACE: ${{ inputs.workspace }}
run: |
targets=$(craft targets | jq -r '.[]|" - [ ] \(.)"')
CRAFT_ARGS=()
if [[ -n "$WORKSPACE" ]]; then
CRAFT_ARGS=("--workspace=$WORKSPACE")
fi
targets=$(craft targets "${CRAFT_ARGS[@]}" | jq -r '.[]|" - [ ] \(.)"')

# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
echo "targets<<EOF" >> "$GITHUB_OUTPUT"
Expand All @@ -211,6 +238,7 @@ runs:
SUBDIRECTORY: ${{ inputs.path != '.' && format('/{0}', inputs.path) || '' }}
MERGE_TARGET: ${{ inputs.merge_target || '(default)' }}
PUBLISH_REPO: ${{ inputs.publish_repo || format('{0}/publish', github.repository_owner) }}
WORKSPACE: ${{ inputs.workspace }}
run: |
# Resolve "self" to the current repository
if [[ "$PUBLISH_REPO" == "self" ]]; then
Expand All @@ -221,7 +249,6 @@ runs:
echo "::error::Craft did not output a version. This is unexpected."
exit 1
fi

# Read changelog from file to avoid E2BIG.
# Produced by craft >= 2.22.0; older versions don't produce the file
# and the publish issue will be created without a changelog section.
Expand All @@ -238,7 +265,7 @@ runs:
CHANGELOG="${CHANGELOG:0:$MAX_CHANGELOG_CHARS}"$'\n\n---\n*Changelog truncated for issue body.*'
fi

title="publish: ${GITHUB_REPOSITORY}${SUBDIRECTORY}@${RESOLVED_VERSION}"
title="publish: ${GITHUB_REPOSITORY}${SUBDIRECTORY}${WORKSPACE:+/$WORKSPACE}@${RESOLVED_VERSION}"

# Check if issue already exists by listing all open issues and filtering by exact title match.
# We avoid GitHub search API to bypass indexing delays and query syntax edge cases.
Expand Down
36 changes: 32 additions & 4 deletions docs/src/content/docs/targets/github.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,40 @@ targets:

Releasing `1.2.3` for each product then produces the tags `cli@1.2.3` / `mcp@1.2.3` on release branches `release/cli/1.2.3` / `release/mcp/1.2.3` — no collisions.

:::note[Coming soon: first-class workspaces]
A single, target-agnostic top-level `workspaces:` model (with an explicit `--workspace` selector) is planned so that all of a repo's products can be managed from one `.craft.yml`. It will supersede the per-file convention above. Track progress in [getsentry/craft#842](https://github.com/getsentry/craft/issues/842).
:::
## Release Workspaces

Use top-level `workspaces:` to define independently versioned release units in
one repository. Select one explicitly with `--workspace <name>` or
`CRAFT_WORKSPACE`:

```yaml
minVersion: 2.29.0
github:
owner: getsentry
repo: toolkit
workspaces:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should allow defining workspaces with directory patterns like pnpm, npm, yarn etc allows

cli:
releaseBranchPrefix: release/cli
targets:
- name: github
tagPrefix: "cli@"
mcp:
releaseBranchPrefix: release/mcp
targets:
- name: github
tagPrefix: "mcp@"
```

Workspace names use ASCII letters, digits, periods, underscores, and hyphens.
They are release units, not npm package workspaces. A workspace cannot use
`github.projectPath`, and a workflow cannot provide both a `path` and a
workspace. This keeps each publish request unambiguous.

The `craft workspace list` command prints the exact configured workspace names
as a JSON array for automation.

:::caution
Declaring **multiple** `github` targets with **different** `tagPrefix` values in a *single* config is currently ambiguous: Craft uses the first prefix for read-path operations and logs a warning. Until workspaces land, use a separate `.craft.yml` per product.
Declaring **multiple** `github` targets with **different** `tagPrefix` values in a single release unit is ambiguous: Craft uses the first prefix for read-path operations and logs a warning. Use separate release workspaces for independent products.
:::

:::note[Known limitation: the GitHub "Latest" badge is repo-wide]
Expand Down
Loading
Loading