Skip to content

Commit f850d00

Browse files
christian-byrneclaudeactions-user
authored
feat: add npm publish workflow for @comfyorg/design-system (#14080)
## Summary Add a GitHub Actions publish workflow and proper package.json metadata so `@comfyorg/design-system` can be published to npm and consumed by external repos. ## Changes - **What**: New `.github/workflows/publish-design-system.yaml` — manual (`workflow_dispatch`) and composable (`workflow_call`) publish workflow for `@comfyorg/design-system`; adds `files`, `exports` (icons), `publishConfig`, `license`, `repository`, `homepage`, `author` to `packages/design-system/package.json` - **Dependencies**: None new ## Review Focus Workflow follows the existing `publish-desktop-bridge-types` pattern exactly: semver validation → version/npm existence check → publish with `NPM_TOKEN`. The `files` field scopes the tarball to `src/css` and `src/icons` only (no tsconfig, no devDependencies, no root package.json noise). To trigger a first publish: bump `version` in `packages/design-system/package.json`, then run "Publish Design System" from Actions with that version. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: GitHub Action <action@github.com>
1 parent 2842bc4 commit f850d00

7 files changed

Lines changed: 401 additions & 1 deletion

File tree

.github/actions/comment-release-links/action.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ runs:
6363
MARKER='desktop-release-summary'
6464
LINKS_VALUE='npm desktop UI|https://www.npmjs.com/package/@comfyorg/desktop-ui/v/{{version}}'
6565
;;
66+
packages/design-system/package.json)
67+
MARKER='design-system-release-summary'
68+
LINKS_VALUE='npm design-system|https://www.npmjs.com/package/@comfyorg/design-system/v/{{version}}'
69+
;;
6670
esac
6771
6872
DIFF_PREFIX='v'
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: 'CI: Design System Pack Check'
2+
3+
on:
4+
pull_request:
5+
branches-ignore: [wip/*, draft/*, temp/*]
6+
paths:
7+
- 'packages/design-system/**'
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
permissions:
14+
contents: read
15+
16+
jobs:
17+
verify-pack-contents:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@v6
21+
22+
- name: Setup frontend
23+
uses: ./.github/actions/setup-frontend
24+
25+
- name: Typecheck
26+
run: pnpm -C packages/design-system typecheck
27+
28+
- name: Verify packed tarball only contains src/css and src/icons
29+
shell: bash
30+
run: |
31+
set -euo pipefail
32+
UNEXPECTED=$(
33+
pnpm -C packages/design-system pack --dry-run --json |
34+
jq -r '
35+
.files[].path
36+
| select(
37+
. != "package.json"
38+
and . != "LICENSE"
39+
and (startswith("src/css/") | not)
40+
and (startswith("src/icons/") | not)
41+
)
42+
'
43+
)
44+
if [ -n "$UNEXPECTED" ]; then
45+
echo "::error title=Unexpected files in tarball::Packed tarball contains files outside src/css and src/icons:" >&2
46+
echo "$UNEXPECTED" >&2
47+
exit 1
48+
fi
49+
echo 'Packed tarball contains only expected files.'
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
name: Publish Design System on PR Merge
2+
3+
on:
4+
pull_request:
5+
types: ['closed']
6+
branches: [main, core/*]
7+
paths:
8+
- 'packages/design-system/package.json'
9+
10+
jobs:
11+
resolve:
12+
name: Resolve Version and Dist Tag
13+
runs-on: ubuntu-latest
14+
if: >
15+
github.event.pull_request.merged == true &&
16+
contains(github.event.pull_request.labels.*.name, 'Release')
17+
outputs:
18+
version: ${{ steps.get_version.outputs.version }}
19+
dist_tag: ${{ steps.dist.outputs.dist_tag }}
20+
steps:
21+
- name: Checkout code
22+
uses: actions/checkout@v6
23+
with:
24+
ref: ${{ github.event.pull_request.merge_commit_sha }}
25+
persist-credentials: false
26+
27+
- name: Read design-system version
28+
id: get_version
29+
shell: bash
30+
run: |
31+
set -euo pipefail
32+
VERSION=$(node -p "require('./packages/design-system/package.json').version")
33+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
34+
35+
- name: Determine dist-tag
36+
id: dist
37+
env:
38+
VERSION: ${{ steps.get_version.outputs.version }}
39+
shell: bash
40+
run: |
41+
set -euo pipefail
42+
if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+- ]]; then
43+
echo "dist_tag=next" >> "$GITHUB_OUTPUT"
44+
else
45+
echo "dist_tag=latest" >> "$GITHUB_OUTPUT"
46+
fi
47+
48+
publish:
49+
name: Publish Design System to npm
50+
needs: resolve
51+
uses: ./.github/workflows/publish-design-system.yaml
52+
with:
53+
version: ${{ needs.resolve.outputs.version }}
54+
dist_tag: ${{ needs.resolve.outputs.dist_tag }}
55+
ref: ${{ github.event.pull_request.merge_commit_sha }}
56+
secrets:
57+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
58+
59+
comment_design_system_publish:
60+
name: Comment Design System Publish Summary
61+
needs:
62+
- resolve
63+
- publish
64+
if: success()
65+
runs-on: ubuntu-latest
66+
permissions:
67+
contents: read
68+
issues: write
69+
pull-requests: write
70+
steps:
71+
- name: Checkout merge commit
72+
uses: actions/checkout@v6
73+
with:
74+
ref: ${{ github.event.pull_request.merge_commit_sha }}
75+
fetch-depth: 2
76+
77+
- name: Post design-system release summary comment
78+
uses: ./.github/actions/comment-release-links
79+
with:
80+
issue-number: ${{ github.event.pull_request.number }}
81+
version_file: packages/design-system/package.json
82+
83+
notify_slack:
84+
name: Notify Slack
85+
needs:
86+
- resolve
87+
- publish
88+
if: success()
89+
runs-on: ubuntu-latest
90+
permissions:
91+
contents: read
92+
steps:
93+
- name: Post to Slack
94+
continue-on-error: true
95+
env:
96+
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
97+
SLACK_CHANNEL_ID: 'C09A24D4692' # #product-design
98+
VERSION: ${{ needs.resolve.outputs.version }}
99+
PR_URL: ${{ github.event.pull_request.html_url }}
100+
PR_NUMBER: ${{ github.event.pull_request.number }}
101+
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
102+
run: |
103+
set -euo pipefail
104+
TEXT=":package: *@comfyorg/design-system@${VERSION}* published to npm — <${PR_URL}|#${PR_NUMBER}> by ${PR_AUTHOR}. <https://www.npmjs.com/package/@comfyorg/design-system/v/${VERSION}|View on npm>"
105+
BODY=$(jq -n --arg ch "$SLACK_CHANNEL_ID" --arg text "$TEXT" '{channel: $ch, text: $text}')
106+
RESPONSE=$(curl -sS -X POST \
107+
--connect-timeout 10 \
108+
--max-time 30 \
109+
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
110+
-H "Content-Type: application/json" \
111+
-d "$BODY" \
112+
https://slack.com/api/chat.postMessage)
113+
echo "$RESPONSE" | jq -e '.ok == true' >/dev/null
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
name: Publish Design System
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: 'Version to publish (e.g., 1.0.1)'
8+
required: true
9+
type: string
10+
dist_tag:
11+
description: 'npm dist-tag to use'
12+
required: true
13+
default: latest
14+
type: string
15+
ref:
16+
description: 'Git ref to checkout (commit SHA, tag, or branch)'
17+
required: false
18+
type: string
19+
workflow_call:
20+
inputs:
21+
version:
22+
required: true
23+
type: string
24+
dist_tag:
25+
required: false
26+
type: string
27+
default: latest
28+
ref:
29+
required: false
30+
type: string
31+
secrets:
32+
NPM_TOKEN:
33+
required: true
34+
35+
concurrency:
36+
group: publish-design-system-${{ inputs.version }}
37+
cancel-in-progress: false
38+
39+
jobs:
40+
publish_design_system:
41+
name: Publish @comfyorg/design-system
42+
runs-on: ubuntu-latest
43+
permissions:
44+
contents: read
45+
steps:
46+
- name: Determine ref to checkout
47+
id: resolve_ref
48+
env:
49+
REF: ${{ inputs.ref }}
50+
DEFAULT_REF: ${{ github.ref_name }}
51+
shell: bash
52+
run: |
53+
set -euo pipefail
54+
if [ -z "$REF" ]; then
55+
REF="$DEFAULT_REF"
56+
fi
57+
if ! git check-ref-format --allow-onelevel "$REF"; then
58+
echo "::error title=Invalid ref::Ref '$REF' fails git check-ref-format validation." >&2
59+
exit 1
60+
fi
61+
echo "ref=$REF" >> "$GITHUB_OUTPUT"
62+
63+
- name: Checkout repository
64+
uses: actions/checkout@v6
65+
with:
66+
ref: ${{ steps.resolve_ref.outputs.ref }}
67+
fetch-depth: 1
68+
persist-credentials: false
69+
70+
- name: Install pnpm
71+
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
72+
73+
- name: Setup Node.js
74+
uses: actions/setup-node@v6
75+
with:
76+
node-version-file: '.nvmrc'
77+
cache: 'pnpm'
78+
registry-url: https://registry.npmjs.org
79+
80+
- name: Install dependencies
81+
run: pnpm install --frozen-lockfile --ignore-scripts
82+
env:
83+
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1'
84+
85+
- name: Validate dist-tag
86+
env:
87+
DIST_TAG: ${{ inputs.dist_tag }}
88+
shell: bash
89+
run: |
90+
set -euo pipefail
91+
if [ -z "$DIST_TAG" ]; then
92+
echo "::error title=Invalid dist-tag::dist_tag must not be empty" >&2
93+
exit 1
94+
fi
95+
if ! node -e "process.exit(require('semver').validRange(process.argv[1]) ? 1 : 0)" "$DIST_TAG"; then
96+
echo "::error title=Invalid dist-tag::Tag '$DIST_TAG' must not parse as a valid SemVer version or range (npm rejects such tags)" >&2
97+
exit 1
98+
fi
99+
100+
- name: Verify package
101+
id: pkg
102+
env:
103+
INPUT_VERSION: ${{ inputs.version }}
104+
shell: bash
105+
run: |
106+
set -euo pipefail
107+
PACKAGE_JSON=packages/design-system/package.json
108+
NAME=$(node -p "require('./${PACKAGE_JSON}').name")
109+
VERSION=$(node -p "require('./${PACKAGE_JSON}').version")
110+
if [ "$NAME" != "@comfyorg/design-system" ]; then
111+
echo "::error title=Package name mismatch::${PACKAGE_JSON} name '$NAME' is not '@comfyorg/design-system'" >&2
112+
exit 1
113+
fi
114+
if [ "$VERSION" != "$INPUT_VERSION" ]; then
115+
echo "::error title=Version mismatch::${PACKAGE_JSON} version $VERSION does not match input $INPUT_VERSION" >&2
116+
exit 1
117+
fi
118+
echo "name=$NAME" >> "$GITHUB_OUTPUT"
119+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
120+
121+
- name: Check if version already on npm
122+
id: check_npm
123+
env:
124+
NAME: ${{ steps.pkg.outputs.name }}
125+
VER: ${{ steps.pkg.outputs.version }}
126+
shell: bash
127+
run: |
128+
set -euo pipefail
129+
STATUS=0
130+
OUTPUT=$(npm view "${NAME}@${VER}" --json 2>&1) || STATUS=$?
131+
if [ "$STATUS" -eq 0 ]; then
132+
echo "exists=true" >> "$GITHUB_OUTPUT"
133+
echo "::warning title=Already published::${NAME}@${VER} already exists on npm. Skipping publish."
134+
else
135+
if echo "$OUTPUT" | grep -q "E404"; then
136+
echo "exists=false" >> "$GITHUB_OUTPUT"
137+
else
138+
echo "::error title=Registry lookup failed::$OUTPUT" >&2
139+
exit "$STATUS"
140+
fi
141+
fi
142+
143+
- name: Publish package
144+
if: steps.check_npm.outputs.exists == 'false'
145+
env:
146+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
147+
DIST_TAG: ${{ inputs.dist_tag }}
148+
run: pnpm publish --access public --tag "$DIST_TAG" --no-git-checks --ignore-scripts
149+
working-directory: packages/design-system
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: Version Bump Design System
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version_type:
7+
description: 'Version increment type'
8+
required: true
9+
default: 'patch'
10+
type: 'choice'
11+
options: [patch, minor, major, prepatch, preminor, premajor, prerelease]
12+
pre_release:
13+
description: Pre-release ID (suffix)
14+
required: false
15+
default: ''
16+
type: string
17+
18+
jobs:
19+
bump-version-design-system:
20+
runs-on: ubuntu-latest
21+
permissions:
22+
contents: write
23+
pull-requests: write
24+
25+
steps:
26+
- name: Checkout repository
27+
uses: actions/checkout@v6
28+
with:
29+
ref: main
30+
fetch-depth: 0
31+
persist-credentials: false
32+
33+
- name: Install pnpm
34+
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
35+
36+
- name: Setup Node.js
37+
uses: actions/setup-node@v6
38+
with:
39+
node-version-file: '.nvmrc'
40+
cache: 'pnpm'
41+
42+
- name: Bump design-system version
43+
id: bump-version
44+
env:
45+
VERSION_TYPE: ${{ github.event.inputs.version_type }}
46+
PRE_RELEASE: ${{ github.event.inputs.pre_release }}
47+
shell: bash
48+
run: |
49+
set -euo pipefail
50+
pnpm -C packages/design-system version "$VERSION_TYPE" --preid "$PRE_RELEASE" --no-git-tag-version
51+
NEW_VERSION=$(node -p "require('./packages/design-system/package.json').version")
52+
echo "NEW_VERSION=$NEW_VERSION" >> "$GITHUB_OUTPUT"
53+
54+
- name: Create Pull Request
55+
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
56+
with:
57+
token: ${{ secrets.PR_GH_TOKEN }}
58+
commit-message: '[release] Increment design-system to ${{ steps.bump-version.outputs.NEW_VERSION }}'
59+
title: design-system ${{ steps.bump-version.outputs.NEW_VERSION }}
60+
body: |
61+
${{ github.event.inputs.version_type }} version increment for @comfyorg/design-system to ${{ steps.bump-version.outputs.NEW_VERSION }}
62+
branch: design-system-version-bump-${{ steps.bump-version.outputs.NEW_VERSION }}
63+
base: main
64+
labels: |
65+
Release

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ yarn.lock
1717
.prettiercache
1818
.stylelintcache
1919
.fallow/
20+
*.tsbuildinfo
2021

2122
node_modules
2223
.pnpm-store

0 commit comments

Comments
 (0)