Skip to content

Commit 3783f9f

Browse files
authored
feat(meta): publish @node-core/* packages (#7776)
* feat(meta): publish @node-core/* packages * add slack notif, add doc * _always_ verify commit * fixup
1 parent d261c9f commit 3783f9f

File tree

2 files changed

+162
-0
lines changed

2 files changed

+162
-0
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
name: Publish Packages
2+
3+
# This workflow publishes packages to NPM when changes are merged to main branch or when manually triggered.
4+
# It runs automatically after successful tests or can be run manually for specific packages.
5+
6+
on:
7+
workflow_run:
8+
# Only run after linting and tests have passed on main branch
9+
workflows: ['Linting and Tests']
10+
types: [completed]
11+
# For security reasons, this should never be set to anything but `main`
12+
branches: [main]
13+
workflow_dispatch:
14+
inputs:
15+
package:
16+
description: 'Specific package to publish (leave empty for all packages)'
17+
required: false
18+
type: string
19+
20+
permissions:
21+
contents: read
22+
23+
env:
24+
# Use the SHA from the workflow run that triggered this or the current SHA for manual runs
25+
COMMIT_SHA: ${{ github.event.workflow_run.head_sha || github.sha }}
26+
27+
jobs:
28+
prepare-packages:
29+
runs-on: ubuntu-latest
30+
# Only run if manually triggered or if the triggering workflow succeeded from a push event
31+
if: github.event_name == 'workflow_dispatch' || (
32+
github.event.workflow_run.conclusion == 'success' &&
33+
github.event.workflow_run.event == 'push' &&
34+
github.repository == 'nodejs/nodejs.org')
35+
outputs:
36+
# Output the matrix of packages to publish for use in the publish job
37+
matrix: ${{ steps.generate-matrix.outputs.matrix }}
38+
steps:
39+
- name: Harden Runner
40+
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
41+
with:
42+
egress-policy: audit
43+
44+
- name: Verify commit authenticity
45+
env:
46+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
47+
run: |
48+
# Get commit data from GitHub API to verify its authenticity
49+
COMMIT_DATA=$(gh api repos/${{ github.repository }}/commits/$COMMIT_SHA)
50+
# Check if commit signature is verified (GPG signed)
51+
VERIFIED=$(echo "$COMMIT_DATA" | jq -r '.commit.verification.verified')
52+
# Check if commit was made through GitHub's web interface (merge queue)
53+
COMMITTER=$(echo "$COMMIT_DATA" | jq -r '.commit.committer.email')
54+
55+
# Security checks to ensure we only publish from verified and trusted sources
56+
if [[ "$VERIFIED" != "true" ]]; then
57+
echo "❌ Unverified commit! Aborting."
58+
exit 1
59+
fi
60+
61+
if [[ "$COMMITTER" != "noreply@github.com" ]]; then
62+
echo "❌ Not merged with the merge queue! Aborting."
63+
exit 1
64+
fi
65+
66+
echo "✅ Commit is verified and trusted."
67+
68+
- name: Checkout repository
69+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
70+
with:
71+
fetch-depth: 2 # Need at least 2 commits to detect changes between commits
72+
73+
- name: Generate package matrix
74+
id: generate-matrix
75+
env:
76+
PACKAGE: ${{ github.event.inputs.package }}
77+
EVENT_NAME: ${{ github.event_name }}
78+
run: |
79+
if [ -n "$PACKAGE" ]; then
80+
# If a specific package is requested via workflow_dispatch, just publish that one
81+
echo "matrix={\"package\":[\"$PACKAGE\"]}" >> $GITHUB_OUTPUT
82+
else
83+
# Otherwise, identify all packages with changes since the last commit
84+
CHANGED_PACKAGES=()
85+
for pkg in $(ls -d packages/*); do
86+
PKG_NAME=$(basename "$pkg")
87+
# For manual runs, include all packages. For automatic runs, only include packages with changes
88+
if [ "$EVENT_NAME" == "workflow_dispatch" ] || ! git diff --quiet $COMMIT_SHA~1 $COMMIT_SHA -- "$pkg/"; then
89+
CHANGED_PACKAGES+=("$PKG_NAME")
90+
fi
91+
done
92+
93+
# Format the output for GitHub Actions matrix using jq
94+
PACKAGES_JSON=$(jq -n '$ARGS.positional' --args "${CHANGED_PACKAGES[@]}" -c)
95+
echo "matrix={\"package\":$PACKAGES_JSON}" >> $GITHUB_OUTPUT
96+
fi
97+
98+
publish:
99+
needs: prepare-packages
100+
runs-on: ubuntu-latest
101+
# Use the dynamic matrix from prepare-packages job to create parallel jobs for each package
102+
strategy:
103+
matrix: ${{ fromJson(needs.prepare-packages.outputs.matrix) }}
104+
fail-fast: false # Continue publishing other packages even if one fails
105+
steps:
106+
- name: Harden Runner
107+
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
108+
with:
109+
egress-policy: audit
110+
111+
- name: Checkout repository
112+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
113+
114+
- name: Set up pnpm
115+
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
116+
with:
117+
cache: true
118+
119+
- name: Setup Node.js
120+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
121+
with:
122+
node-version-file: '.nvmrc'
123+
registry-url: 'https://registry.npmjs.org'
124+
cache: pnpm
125+
126+
- name: Publish
127+
working-directory: packages/${{ matrix.package }}
128+
env:
129+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
130+
run: |
131+
# Create a unique version using the commit SHA as a prerelease identifier
132+
# This ensures we can publish multiple times from the same codebase with unique versions
133+
npm version --no-git-tag-version 0.0.0-$COMMIT_SHA
134+
# Publish the package to the npm registry with public access flag
135+
pnpm publish --access public
136+
137+
- name: Notify on Manual Release
138+
if: ${{ github.event_name == 'workflow_dispatch' }}
139+
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # 2.3.3
140+
env:
141+
SLACK_COLOR: '#43853D'
142+
SLACK_ICON: https://github.com/nodejs.png?size=48
143+
SLACK_TITLE: ':rocket: Package Published: ${{ matrix.package }}'
144+
SLACK_MESSAGE: |
145+
:package: *Package*: `${{ matrix.package }}` (<https://www.npmjs.com/package/${{ steps.package-info.outputs.name }}|View on npm>)
146+
:bust_in_silhouette: *Published by*: ${{ github.triggering_actor }}
147+
:octocat: *Commit*: <https://github.com/${{ github.repository }}/commit/${{ env.COMMIT_SHA }}|${{ env.COMMIT_SHA }}>
148+
SLACK_USERNAME: nodejs-bot
149+
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}

COLLABORATOR_GUIDE.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
- [General Guidelines for Unit Tests](#general-guidelines-for-unit-tests)
2121
- [General Guidelines for Playwright E2E Tests](#general-guidelines-for-playwright-e2e-tests)
2222
- [General Guidelines for Storybooks](#general-guidelines-for-storybooks)
23+
- [Publishing Packages](#publishing-packages)
2324
- [Remarks on Technologies used](#remarks-on-technologies-used)
2425
- [Seeking additional clarification](#seeking-additional-clarification)
2526

@@ -487,6 +488,18 @@ export default { component: NameOfComponent } as Meta;
487488
- We recommend reading previous Storybooks from the codebase for inspiration and code guidelines.
488489
- If you need to decorate/wrap your Component/Story with a Container/Provider, please use [Storybook Decorators](https://storybook.js.org/docs/react/writing-stories/decorators)
489490

491+
## Publishing Packages
492+
493+
The Node.js Website uses a multi-package workspace architecture where individual packages are published to the npm registry. This section outlines the process for publishing packages and the best practices to follow.
494+
495+
The package publishing process is automated through GitHub Actions and can be triggered in two ways:
496+
497+
1. **Automatically after successful tests**:
498+
When changes are merged to the main branch, the "Publish Packages" workflow runs after the "Linting and Tests" workflow completes successfully. Commits must come through GitHub's merge queue (committer must be verified from noreply@github.com)
499+
500+
2. **Manually via workflow dispatch**:
501+
You can manually trigger publishing for specific packages through the GitHub Actions interface. When manually triggering publishing, ensure the commit hasn't already been published and is safe to do so. In the event of a manual trigger, a Slack notification will be sent to `#nodejs-website`.
502+
490503
## Remarks on Technologies Used
491504

492505
The Node.js Website is a somewhat complex application and at times non-trivial solutions have been implemented to solve certain technical challenges.

0 commit comments

Comments
 (0)