From 89171bd20644f5da893dc547ee5e8c4906260264 Mon Sep 17 00:00:00 2001 From: Elizabeth Craig Date: Wed, 5 Aug 2026 03:36:05 -0700 Subject: [PATCH 1/4] Update beachball to v3 alpha --- .agents/skills/beachball-change-file/SKILL.md | 148 ++++++++++++ .agents/skills/change/SKILL.md | 47 ---- .github/instructions/copilot.instructions.md | 7 +- .github/workflows/check-packages.yml | 9 +- .vscode/settings.json | 10 +- AGENTS.md | 24 +- ...ipelines.release-headless-experimental.yml | 4 +- ...e-pipelines.release-vnext-experimental.yml | 4 +- azure-pipelines.release-vnext-nightly.yml | 4 +- azure-pipelines.release-vnext.yml | 3 +- azure-pipelines.release.headless.yml | 3 +- ...e-pipelines.release.tools-experimental.yml | 4 +- azure-pipelines.release.tools.yml | 3 +- azure-pipelines.release.web-components.yml | 3 +- azure-pipelines.release.yml | 3 +- beachball.config.js | 2 +- ...-a417f93b-a140-4c40-a4e9-074fab196688.json | 7 - ...-2a88231d-0358-4d1a-bb01-9f602e9306ec.json | 7 - docs/workflows/contributing.md | 10 +- package.json | 11 +- scripts/beachball/base.config.json | 28 --- scripts/beachball/src/base.config.js | 33 +++ scripts/beachball/src/config.test.ts | 5 +- scripts/beachball/src/customRenderers.ts | 3 + scripts/beachball/src/shared.config.ts | 15 +- scripts/beachball/src/utils.ts | 4 +- scripts/beachball/tsconfig.json | 3 +- .../src/changelogsAndTags.ts | 2 +- scripts/update-release-notes/src/index.ts | 2 +- .../update-release-notes/src/pullRequests.ts | 4 +- .../prepare-initial-release/index.spec.ts | 8 +- .../prepare-initial-release/index.ts | 2 +- yarn.lock | 221 +++++++----------- 33 files changed, 344 insertions(+), 299 deletions(-) create mode 100644 .agents/skills/beachball-change-file/SKILL.md delete mode 100644 .agents/skills/change/SKILL.md delete mode 100644 change/fluentui-eslint-plugin-a417f93b-a140-4c40-a4e9-074fab196688.json delete mode 100644 change/fluentui-theme-designer-2a88231d-0358-4d1a-bb01-9f602e9306ec.json delete mode 100644 scripts/beachball/base.config.json create mode 100644 scripts/beachball/src/base.config.js diff --git a/.agents/skills/beachball-change-file/SKILL.md b/.agents/skills/beachball-change-file/SKILL.md new file mode 100644 index 00000000000000..24cb968fdd6625 --- /dev/null +++ b/.agents/skills/beachball-change-file/SKILL.md @@ -0,0 +1,148 @@ +--- +description: How to create a Beachball change file. ONLY use this skill when the user asks to generate change files, before pushing a branch, or before creating a PR. +license: MIT +metadata: + github-path: skills/beachball-change-file + github-ref: refs/heads/main + github-repo: https://github.com/microsoft/beachball + github-tree-sha: 5198ce6d081a41c46a6a1bbf211418972596ef33 + source: https://github.com/microsoft/beachball/blob/main/skills/beachball-change-file/SKILL.md + version: 1.0.6 +name: beachball-change-file +--- + +[Beachball](https://microsoft.github.io/beachball/) is a tool used for managing versioning and changelogs for JS/TS codebases. Every pull request must include a Beachball change file. Change files include the list of packages with public-facing changes in the branch, with the description and semver change type for each package. After the PR is checked in and a release is run, the change files are used to determine version bumps and update changelogs. + +Beachball normally uses a CLI with an interactive prompt to create change files, but they can also be created manually using the standardized JSON format detailed below. + +## Prerequisites + +- Determine the root directory: this is almost always the git root, but the user might specify a different folder. (The root usually contains `beachball.config.*` or `.beachballrc.*` or has a `"beachball"` key in `package.json`.) +- Determine the package manager for the repo (`npm`, `yarn`, `pnpm`). The example commands below assume `yarn`, but substitute the appropriate command runner syntax for a different package manager. +- Check the root `package.json` `scripts` for scripts that run `beachball change` and `beachball check`. + - The examples below assume `scripts` called `change` and `checkchange` respectively, but substitute the appropriate script names if found. + - Using `scripts` if defined is preferred since they may add extra arguments, but it's possible to run the commands directly: `yarn beachball change` and `yarn beachball check` (substituting appropriate command runner) +- Use `beachball config get` to check the following settings (note: `beachball config get` only exists in versions `>= 2.64.0`) + - `yarn beachball config get changeDir`: where to put the change files + - `yarn beachball config get branch`: target branch name + - `yarn beachball config get groupChanges`: whether grouped change files are enabled (true/false/undefined) + +## Creating and validating a change file + +Usually, an AI agent should create a change file manually following the standardized format detailed below. + +### 1. Validate repo state + +Beachball only considers staged and committed files, so you should check for unstaged or untracked changes before proceeding: + +1. Get file paths with unstaged changes (`git ls-files -m`) and untracked changes (`git ls-files -o --exclude-standard`) +2. If there are any unstaged or untracked changes, ask the user whether they would like to stage all files or continue without staging. If they choose to stage, run `git add .` before proceeding. + +### 2. Get changed packages + +Run `yarn checkchange --verbose` to get the list of changed packages and files considered by `beachball`: + +- The list of changed packages is under "Found changes in the following packages" -- you must ONLY include these packages in the change file! (beachball has various settings to ignore packages or files) +- The list of changed files is under "changed files in current branch". IGNORE any files with `~~` strikethrough formatting. + +DO NOT manually check for existing change files. + +### 3. Create the change file(s) + +Change files are located under ``. There are two possible structures for change files, determined by the `groupChanges` setting. + +When checking diffs to generate change files, DO NOT merge with the target branch; just use the local merge-base. + +#### Case 1: Non-grouped format (`groupChanges` is `false` or unset) + +If `groupChanges` is `false` or unset, you should create a separate change file for each package. + +For each changed package **as listed by beachball**: + +1. Generate a random GUID: `node -e "console.log(crypto.randomUUID())"` +2. Create a change file under `/-.json` with the following format. See [Change entry values](#change-entry-values) below for the proper values of each field. + +```json +{ + "packageName": "", + "type": "", + "dependentChangeType": "", + "comment": "", + "email": "" +} +``` + +#### Case 2: Grouped format (`groupChanges: true`) + +If `groupChanges` is `true`, you should create a single change file. + +1. Generate a random GUID: `node -e "console.log(crypto.randomUUID())"` +2. Create a single change file under `/change-.json` with the following format. The `changes` array should have an entry for each changed package **as listed by beachball**. See [Change entry values](#change-entry-values) below for the proper values of each field. + +```json +{ + "changes": [ + { + "packageName": "", + "type": "", + "dependentChangeType": "", + "comment": "", + "email": "" + } + ] +} +``` + +### 4. Validate the change file(s) + +Run `git add `, then re-run `yarn checkchange` to verify. + +## Change entry values + +Each package's entry has the following values: + +- `packageName`: The name of the changed package, e.g. `just-task` +- `type`: The semantic versioning change type for the package. See [Determining a package's change type](#determining-a-packages-change-type) below. +- `dependentChangeType`: Change type for packages that depend on this package. If `type` is `"none"`, this should be `"none"`. Otherwise, this should be `"patch"` (beachball internally handles this for the special case of prerelease packages). +- `comment` (`--message` CLI arg): A concise description of the changes made to the package. Tips: + - This will go in the changelog, so it should focus on user-facing changes (especially any API changes) rather than implementation details. + - Markdown formatting is allowed, so any references to names from code should be wrapped with backticks. +- `email`: User's email from `git config user.email`, or `"email not defined"` if not available. Do NOT invent an email. + +### Determining a package's change type + +The `type` field is the semantic versioning change type for the package, determined based on the diff content of changed files in that package. There are different options depending on whether the package's current version contains a prerelease suffix or not, and the `disallowedChangeTypes` setting may modify which change types are allowed. + +If you're still uncertain about the change type after following the instructions below, ask the user to choose. + +For each package, start by checking: + +- The current `version` in `package.json` +- `disallowedChangeTypes` for the specific package: `yarn beachball config get disallowedChangeTypes --package ` +- Whether the package has a file `/etc/*.api.md`. If so, the diff of this file will show whether any public API signatures changed. + +#### Case 1: Version is 1.0.0 or greater and NOT prerelease + +If the package's current version is 1.0.0 or greater and does NOT have a prerelease suffix, the typical options are `` (but you MUST respect `disallowedChangeTypes`): + +- `"patch"`: Bug fixes or other changes that don't impact exported API signatures. +- `"minor"`: New exported APIs, non-breaking signature changes to exported APIs, or more significant changes to internal logic. (If the package has a `/etc/*.api.md` file, checking its diff is the easiest way to see exported API changes.) +- `"major"`: Breaking changes to exported APIs (removals or breaking signature changes), critical dependency updates, or behavior changes that might be breaking for the consumer. You MUST confirm with the user before choosing `"major"`. +- `"none"`: None of the changes will impact consumers of the package (e.g. the changes are only to non-exported test-specific files or documentation). If you're not certain, prefer `"patch"`. +- There are additional options `prerelease|premajor|preminor|prepatch`, but you should only use one of these if explicitly requested by the user. + +#### Case 2: Version is 0.x.y and NOT prerelease + +If the package's major version is 0 and does NOT have a prerelease suffix, this is similar to case 1. However, version 0 packages follow different conventions for semantic versioning (you MUST still respect `disallowedChangeTypes`): + +- Use `"minor"` for breaking changes (do NOT use `"major"` unless specifically requested) +- Use `"patch"` for any other changes that impact consumers of the package +- Use `"none"` in the same circumstances as case 1 + +#### Case 3: Version IS prerelease + +ONLY if the package's current version includes a prerelease suffix, the typical options are `` (but you MUST respect `disallowedChangeTypes`): + +- `"prerelease"`: Any changes that impact consumers of the package +- `"none"`: None of the changes will impact consumers of the package (e.g. the changes are only to non-exported test-specific files or documentation). If you're not certain, prefer `"prerelease"`. +- There are additional options `premajor|preminor|prepatch`, but you should only use one of these if explicitly requested by the user or all other change types are disallowed. diff --git a/.agents/skills/change/SKILL.md b/.agents/skills/change/SKILL.md deleted file mode 100644 index 7a0570b27d2a77..00000000000000 --- a/.agents/skills/change/SKILL.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -name: change -description: Create a beachball change file for the current changes. Determines change type (patch/minor) and generates a description from the diff. -disable-model-invocation: true -allowed-tools: Bash Read Grep Glob ---- - -# Create a Beachball Change File - -Generate a change file for the current branch's modifications using the repo's beachball setup. - -## Steps - -1. **Determine the change type:** - - - `patch` — bug fixes, internal refactors, test-only changes - - `minor` — new features, new exports, new component variants - - `none` — changes that don't affect the published package (stories, docs, tests only) - - Never use `major` without explicit user approval - -2. **Generate a descriptive message** following the format: `fix(package-name): description` or `feat(package-name): description` - -3. **Run the repo's change script** to create the change file: - - ```bash - yarn change - ``` - - This runs `beachball change --no-commit` (configured in root `package.json`). - Beachball automatically detects which packages need change files. - - For non-interactive usage with a specific type and message: - - ```bash - yarn beachball change --no-commit --type --message "" - ``` - -4. **Verify** the change file was created: - - ```bash - yarn check:change - ``` - -## Rules - -- Always use `yarn change` or `yarn beachball change` — never manually create change files -- The message should describe the user-facing impact, not the implementation detail diff --git a/.github/instructions/copilot.instructions.md b/.github/instructions/copilot.instructions.md index 0cea69b329340f..ff2470c88cac2b 100644 --- a/.github/instructions/copilot.instructions.md +++ b/.github/instructions/copilot.instructions.md @@ -69,9 +69,6 @@ yarn nx run :start # Start Storybook for component # Component generation (v9 only) yarn create-component # Interactive component generator -# Release management -yarn change # Create beachball change file (required for PRs) - # Show project targets yarn nx show projects # List all projects ``` @@ -85,7 +82,7 @@ yarn nx show projects # List all projects 3. Follow hook-based architecture pattern exactly 4. Add comprehensive tests and Storybook stories 5. Run `yarn nx run :generate-api` to update API docs -6. Create change file with `yarn change` before PR +6. Create change file with `/beachball-change-file` skill before PR **For v8 components** (maintenance only): @@ -463,7 +460,7 @@ The repository uses a triage bot that automatically assigns labels and assignees 1. Labels are automatically applied based on changed files 2. Focus on clear PR titles and descriptions 3. Reference related issues with proper syntax (`Fixes #123`) -4. Create change files for breaking changes (`yarn change`) +4. Create change files for changes impacting published code (`/beachball-change-file` skill) **For Maintainers**: diff --git a/.github/workflows/check-packages.yml b/.github/workflows/check-packages.yml index 216e2ba2c7dd45..2d488b5c44ed02 100644 --- a/.github/workflows/check-packages.yml +++ b/.github/workflows/check-packages.yml @@ -30,11 +30,10 @@ jobs: run: | echo "yarn.lock changed! Verifying package deduplication ..." - yarn run dedupe --check --json - - if [[ $? -ne 0 ]]; then - echo "Your changes introduced package duplication 🚨" - echo "Run 'yarn run dedupe' to fix those." + if ! yarn run dedupe --check; then + echo + echo "::error::Your changes introduced package duplication - run 'yarn run dedupe' to fix." + exit 1 else echo "No duplicate packages introduced ✅" fi diff --git a/.vscode/settings.json b/.vscode/settings.json index 41454c24a61a1a..c0e8e7a492731c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -69,12 +69,10 @@ "[handlebars]": { "editor.formatOnSave": false }, - "javascript.preferences.importModuleSpecifier": "relative", - "javascript.preferences.importModuleSpecifierEnding": "index", - "typescript.preferences.importModuleSpecifier": "relative", - "typescript.preferences.importModuleSpecifierEnding": "index", - "typescript.tsdk": "./node_modules/typescript/lib", - "typescript.reportStyleChecksAsWarnings": false, + "js/ts.preferences.importModuleSpecifier": "relative", + "js/ts.preferences.importModuleSpecifierEnding": "index", + "js/ts.tsdk.path": "./node_modules/typescript/lib", + "js/ts.reportStyleChecksAsWarnings": false, "cSpell.words": ["beachball", "borderless", "fluentui", "griffel", "spinbutton", "tabster"], "nxConsole.generateAiAgentRules": true, // Maximum number of requests for the chat agent - Prevents AI agents from stopping mid-session diff --git a/AGENTS.md b/AGENTS.md index ba571e028485b6..f92f43788dbe1f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,7 +22,7 @@ from existing code without verifying they match these instructions. 2. **Never use `React.FC`.** Always use `ForwardRefComponent` with `React.forwardRef`. 3. **Never access `window`, `document`, or `navigator` directly.** In v9 components, use `useFluent_unstable()` to get `targetDocument` and `targetDocument.defaultView` instead of `document`/`window`. For non-component code, use `canUseDOM()` from `@fluentui/react-utilities`. 4. **Never add dependencies between component packages.** `react-button` must not depend on `react-menu`. Shared logic goes in `react-utilities` or `react-shared-contexts`. See [docs/architecture/layers.md](docs/architecture/layers.md). -5. **Never skip beachball change files** for published package changes. Run `yarn beachball change`. +5. **Never skip beachball change files** for published package changes. Use the `/beachball-change-file` skill. ## V9 Component Template (the correct pattern) @@ -91,17 +91,17 @@ state.root.className = mergeClasses( ## Skills (Slash Commands) -| Skill | Command | Purpose | -| ------------------- | -------------------- | -------------------------------------------------------------------- | -| `v9-component` | `/v9-component Name` | Scaffold a new v9 component with all required files | -| `change` | `/change` | Create beachball change file from current diff | -| `lint-check` | `/lint-check [pkg]` | Run lint, parse errors, and auto-fix common issues | -| `token-lookup` | `/token-lookup val` | Find the design token for a hardcoded CSS value | -| `package-info` | `/package-info pkg` | Quick lookup: path, deps, owner, tests, structure | -| `visual-test` | `/visual-test Name` | Visually verify a component via Storybook + playwright-cli | -| `review-pr` | `/review-pr #123` | Review a PR with confidence scoring and category checks | -| `triage-issues` | `/triage-issues` | Walk the Needs-Triage queue and recommend labels/assignee | -| `dependabot-rollup` | `/dependabot-rollup` | Dry-run and optionally roll up at most 11 Dependabot patch/minor PRs | +| Skill | Command | Purpose | +| ----------------------- | ------------------------ | -------------------------------------------------------------------- | +| `v9-component` | `/v9-component Name` | Scaffold a new v9 component with all required files | +| `beachball-change-file` | `/beachball-change-file` | Create beachball change file from current diff | +| `lint-check` | `/lint-check [pkg]` | Run lint, parse errors, and auto-fix common issues | +| `token-lookup` | `/token-lookup val` | Find the design token for a hardcoded CSS value | +| `package-info` | `/package-info pkg` | Quick lookup: path, deps, owner, tests, structure | +| `visual-test` | `/visual-test Name` | Visually verify a component via Storybook + playwright-cli | +| `review-pr` | `/review-pr #123` | Review a PR with confidence scoring and category checks | +| `triage-issues` | `/triage-issues` | Walk the Needs-Triage queue and recommend labels/assignee | +| `dependabot-rollup` | `/dependabot-rollup` | Dry-run and optionally roll up at most 11 Dependabot patch/minor PRs | ## Package Layout diff --git a/azure-pipelines.release-headless-experimental.yml b/azure-pipelines.release-headless-experimental.yml index 5ecde8859c6860..f0f7491c6a63a5 100644 --- a/azure-pipelines.release-headless-experimental.yml +++ b/azure-pipelines.release-headless-experimental.yml @@ -125,10 +125,12 @@ extends: displayName: test - script: | - yarn beachball publish -b origin/$(validation.branchPath) --access public -y -n $(npmToken) --no-push --tag experimental --config scripts/beachball/src/release-headless.config.js + yarn beachball publish -b origin/$(validation.branchPath) --no-push --tag experimental --config scripts/beachball/src/release-headless.config.js git reset --hard origin/$(validation.branchPath) displayName: Publish changes and bump versions condition: and(succeeded(), not(${{ parameters.dryRun }})) + env: + NPM_TOKEN: $(npmToken) - template: .devops/templates/cleanup.yml@self parameters: diff --git a/azure-pipelines.release-vnext-experimental.yml b/azure-pipelines.release-vnext-experimental.yml index b327c25135edaf..be0e54ae30bfa0 100644 --- a/azure-pipelines.release-vnext-experimental.yml +++ b/azure-pipelines.release-vnext-experimental.yml @@ -118,10 +118,12 @@ extends: displayName: test - script: | - yarn beachball publish -b origin/$(validation.branchPath) --access public -y -n $(npmToken) --no-push --tag experimental --config scripts/beachball/src/release-vNext.config.js + yarn beachball publish -b origin/$(validation.branchPath) --no-push --tag experimental --config scripts/beachball/src/release-vNext.config.js git reset --hard origin/$(validation.branchPath) displayName: Publish changes and bump versions condition: and(succeeded(), not(${{ parameters.dryRun }})) + env: + NPM_TOKEN: $(npmToken) - template: .devops/templates/cleanup.yml@self parameters: diff --git a/azure-pipelines.release-vnext-nightly.yml b/azure-pipelines.release-vnext-nightly.yml index b2a0642d680f96..f80c50372ca3c0 100644 --- a/azure-pipelines.release-vnext-nightly.yml +++ b/azure-pipelines.release-vnext-nightly.yml @@ -103,10 +103,12 @@ extends: displayName: test - script: | - yarn publish:beachball -b origin/$(Build.SourceBranchName) -n $(npmToken) --no-push --tag nightly --config scripts/beachball/src/release-vNext.config.js + yarn beachball publish -b origin/$(Build.SourceBranchName) --no-push --tag nightly --config scripts/beachball/src/release-vNext.config.js git reset --hard origin/$(Build.SourceBranchName) displayName: Publish changes and bump versions condition: not(${{ parameters.dryRun }}) + env: + NPM_TOKEN: $(npmToken) - template: .devops/templates/cleanup.yml@self parameters: diff --git a/azure-pipelines.release-vnext.yml b/azure-pipelines.release-vnext.yml index 95193a420b71af..831d2d45b3748b 100644 --- a/azure-pipelines.release-vnext.yml +++ b/azure-pipelines.release-vnext.yml @@ -95,10 +95,11 @@ extends: condition: not(${{ parameters.dryRun }}) - script: | - yarn publish:beachball -n $(npmToken) --config scripts/beachball/src/release-vNext.config.js --message 'release: applying package updates - react-components' + yarn beachball publish --config scripts/beachball/src/release-vNext.config.js --message 'release: applying package updates - react-components' git reset --hard origin/master env: GITHUB_PAT: $(githubPAT) + NPM_TOKEN: $(npmToken) displayName: Publish changes and bump versions condition: not(${{ parameters.dryRun }}) diff --git a/azure-pipelines.release.headless.yml b/azure-pipelines.release.headless.yml index 9058a6fcb17a0f..9fad65c70cd948 100644 --- a/azure-pipelines.release.headless.yml +++ b/azure-pipelines.release.headless.yml @@ -84,10 +84,11 @@ extends: displayName: lint - script: | - yarn publish:beachball -n $(npmToken) --config scripts/beachball/src/release-headless.config.js --message 'release: applying package updates - react-headless' + yarn beachball publish --config scripts/beachball/src/release-headless.config.js --message 'release: applying package updates - react-headless' git reset --hard origin/master env: GITHUB_PAT: $(githubPAT) + NPM_TOKEN: $(npmToken) displayName: Publish changes and bump versions condition: not(${{ parameters.dryRun }}) diff --git a/azure-pipelines.release.tools-experimental.yml b/azure-pipelines.release.tools-experimental.yml index 86a09c8e65add0..518fe3874503e9 100644 --- a/azure-pipelines.release.tools-experimental.yml +++ b/azure-pipelines.release.tools-experimental.yml @@ -117,10 +117,12 @@ extends: displayName: test - script: | - yarn beachball publish -b origin/$(validation.branchPath) --access public -y -n $(npmToken) --no-push --tag experimental --config scripts/beachball/src/release-tools.config.js + yarn beachball publish -b origin/$(validation.branchPath) --no-push --tag experimental --config scripts/beachball/src/release-tools.config.js git reset --hard origin/$(validation.branchPath) displayName: Publish changes and bump versions condition: and(succeeded(), not(${{ parameters.dryRun }})) + env: + NPM_TOKEN: $(npmToken) - template: .devops/templates/cleanup.yml@self parameters: diff --git a/azure-pipelines.release.tools.yml b/azure-pipelines.release.tools.yml index f7d7f42bab4609..cb1701fd804418 100644 --- a/azure-pipelines.release.tools.yml +++ b/azure-pipelines.release.tools.yml @@ -83,10 +83,11 @@ extends: displayName: lint - script: | - yarn publish:beachball -n $(npmToken) --config scripts/beachball/src/release-tools.config.js --message 'release: applying package updates - tools' + yarn beachball publish --config scripts/beachball/src/release-tools.config.js --message 'release: applying package updates - tools' git reset --hard origin/master env: GITHUB_PAT: $(githubPAT) + NPM_TOKEN: $(npmToken) displayName: Publish changes and bump versions condition: not(${{ parameters.dryRun }}) diff --git a/azure-pipelines.release.web-components.yml b/azure-pipelines.release.web-components.yml index de2d9bc1ee07a9..7e7fd8d0a0fae0 100644 --- a/azure-pipelines.release.web-components.yml +++ b/azure-pipelines.release.web-components.yml @@ -81,10 +81,11 @@ extends: displayName: Build, Test, Lint - script: | - yarn publish:beachball -n $(npmToken) --config scripts/beachball/src/release-web-components.config.js --message 'release: applying package updates - web-components' + yarn beachball publish --config scripts/beachball/src/release-web-components.config.js --message 'release: applying package updates - web-components' git reset --hard origin/master env: GITHUB_PAT: $(githubPAT) + NPM_TOKEN: $(npmToken) displayName: Publish changes and bump versions condition: not(${{ parameters.dryRun }}) diff --git a/azure-pipelines.release.yml b/azure-pipelines.release.yml index ecabd7c10955ad..6bfc06bedbe290 100644 --- a/azure-pipelines.release.yml +++ b/azure-pipelines.release.yml @@ -127,11 +127,12 @@ extends: displayName: verify packaged assets - script: | - yarn publish:beachball -n $(npmToken) --config scripts/beachball/src/release-v8.config.js --message 'release: applying package updates - react v8' + yarn beachball publish --config scripts/beachball/src/release-v8.config.js --message 'release: applying package updates - react v8' git reset --hard origin/master condition: and(succeeded(), not(${{ parameters.dryRun }})) env: GITHUB_PAT: $(githubPAT) + NPM_TOKEN: $(npmToken) displayName: Publish changes and bump versions - script: | diff --git a/beachball.config.js b/beachball.config.js index 472e34ca7deee2..e1a1b88e474958 100644 --- a/beachball.config.js +++ b/beachball.config.js @@ -1 +1 @@ -module.exports = require('./scripts/beachball/base.config.json'); +module.exports = require('./scripts/beachball/src/base.config'); diff --git a/change/fluentui-eslint-plugin-a417f93b-a140-4c40-a4e9-074fab196688.json b/change/fluentui-eslint-plugin-a417f93b-a140-4c40-a4e9-074fab196688.json deleted file mode 100644 index c6f73ed4930d92..00000000000000 --- a/change/fluentui-eslint-plugin-a417f93b-a140-4c40-a4e9-074fab196688.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "minor", - "comment": "chore: enforce consistent type imports in react packages", - "packageName": "@fluentui/eslint-plugin", - "email": "copilot@microsoft.com", - "dependentChangeType": "patch" -} diff --git a/change/fluentui-theme-designer-2a88231d-0358-4d1a-bb01-9f602e9306ec.json b/change/fluentui-theme-designer-2a88231d-0358-4d1a-bb01-9f602e9306ec.json deleted file mode 100644 index 6c9c934700c162..00000000000000 --- a/change/fluentui-theme-designer-2a88231d-0358-4d1a-bb01-9f602e9306ec.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "none", - "comment": "chore: enforce consistent type imports", - "packageName": "@fluentui/theme-designer", - "email": "copilot@microsoft.com", - "dependentChangeType": "none" -} diff --git a/docs/workflows/contributing.md b/docs/workflows/contributing.md index 34494467790d51..dc0dddee813911 100644 --- a/docs/workflows/contributing.md +++ b/docs/workflows/contributing.md @@ -9,7 +9,7 @@ yarn clean # Clean build artifacts # Development yarn start # Interactive project selector -yarn nx run :build # Build specific project +yarn nx run :build # Build specific project yarn nx run :start # Start Storybook for component yarn nx run :test # Run unit tests yarn nx run :test -u # Update snapshots @@ -27,13 +27,9 @@ yarn create-component # Interactive generator ## PR Checklist -1. **Change file** — Required for any published package change: +1. **Change file** — Run `yarn change` to interactively generate change files for any published package changes. (AI agents should use the `/beachball-change-file` skill instead.) - ```bash - yarn beachball change --type patch --message "fix(react-button): description" - ``` - - Use `patch` for fixes, `minor` for features. Never `major` without approval. + Use `patch` for fixes, `minor` for features (or see [more info about choosing a change type](https://microsoft.github.io/beachball/concepts/change-types.html)). Never use `major` without approval. 2. **Tests pass** — `yarn nx run :test` diff --git a/package.json b/package.json index ac69f9009b53f1..fafcde6b47d35b 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ }, "scripts": { "dedupe": "yarn dedupe --strategy highest", - "change": "beachball change --no-commit", + "change": "beachball change", "check:change": "beachball check", "check:modified-files": "node -r ./scripts/ts-node/src/register ./scripts/executors/src/check-for-modified-files", "check:affected": "node ./scripts/executors/src/checkIfPackagesAffected.js", @@ -23,7 +23,6 @@ "generate-version-files": "node -r ./scripts/ts-node/src/register ./scripts/generators/src/generate-version-files", "postinstall": "husky && node ./scripts/package-manager/src/postinstall.js", "preinstall": "node ./scripts/package-manager/src/preinstall.js", - "publish:beachball": "beachball publish -b origin/master --access public -y", "start": "node -r ./scripts/ts-node/src/register ./scripts/executors/src/start", "generate": "node -r ./scripts/ts-node/src/register ./scripts/executors/src/generate-ui", "clean": "nx run-many -t clean --verbose", @@ -163,7 +162,6 @@ "@types/webpack-env": "1.18.8", "@types/webpack-hot-middleware": "2.25.9", "@types/yargs": "13.0.11", - "@types/yargs-unparser": "2.0.1", "@typescript-eslint/eslint-plugin": "8.46.2", "@typescript-eslint/rule-tester": "^8.46.2", "autoprefixer": "10.2.1", @@ -176,7 +174,7 @@ "babel-plugin-module-resolver": "5.0.3", "babel-plugin-react-compiler": "1.0.0", "babel-plugin-tester": "10.1.0", - "beachball": "2.31.0", + "beachball": "3.0.0-alpha.7", "chalk": "4.1.0", "chrome-remote-interface": "0.28.2", "ci-info": "3.9.0", @@ -281,7 +279,6 @@ "react-shadow": "20.3.0", "react-test-renderer": "19.2.0", "react-window": "^1.8.6", - "read-pkg-up": "7.0.1", "remark-gfm": "4.0.1", "replace-in-file": "6.1.0", "resolve": "1.22.8", @@ -329,10 +326,8 @@ "webpack-dev-server": "4.15.2", "webpack-hot-middleware": "2.26.1", "webpack-merge": "5.10.0", - "workspace-tools": "0.29.1", "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "2.0.0" + "yargs-parser": "13.1.2" }, "dependencies": { "@fluentui/react-icons-northstar": "0.66.5", diff --git a/scripts/beachball/base.config.json b/scripts/beachball/base.config.json deleted file mode 100644 index a4666c0fdd9e5f..00000000000000 --- a/scripts/beachball/base.config.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "disallowedChangeTypes": ["major"], - "tag": "latest", - "generateChangelog": true, - "ignorePatterns": [ - "**/*.{shot,snap}", - "**/*.{test,spec,cy}.{ts,tsx}", - "**/*.stories.{ts,tsx}", - "**/.eslintrc.*", - "**/eslint.config.*", - "**/rit.config.js", - "**/__fixtures__/**", - "**/__mocks__/**", - "**/docs/**", - "**/stories/**", - "**/.storybook/**", - "**/bundle-size/**", - "**/common/isConformant.ts", - "**/src/testing/**", - "**/src/e2e/**", - "**/config/tests.js", - "**/jest.config.js", - "**/SPEC*.md", - "**/tests/**" - ], - "scope": ["!packages/fluentui/*"], - "changehint": "Run 'yarn change' to generate a change file" -} diff --git a/scripts/beachball/src/base.config.js b/scripts/beachball/src/base.config.js new file mode 100644 index 00000000000000..30e9ab201b5279 --- /dev/null +++ b/scripts/beachball/src/base.config.js @@ -0,0 +1,33 @@ +/** @satisfies {import('beachball').BeachballConfig} */ +const config = { + access: 'public', + commit: false, + disallowedChangeTypes: ['major'], + tag: 'latest', + generateChangelog: true, + ignorePatterns: [ + '**/*.{shot,snap}', + '**/*.{test,spec,cy}.{ts,tsx}', + '**/*.stories.{ts,tsx}', + '**/.eslintrc.*', + '**/eslint.config.*', + '**/rit.config.js', + '**/__fixtures__/**', + '**/__mocks__/**', + '**/docs/**', + '**/stories/**', + '**/.storybook/**', + '**/bundle-size/**', + '**/common/isConformant.ts', + '**/src/testing/**', + '**/src/e2e/**', + '**/config/tests.js', + '**/jest.config.js', + '**/SPEC*.md', + '**/tests/**', + ], + scope: ['!packages/fluentui/*'], + changehint: "Run 'yarn change' to generate a change file", +}; + +module.exports = config; diff --git a/scripts/beachball/src/config.test.ts b/scripts/beachball/src/config.test.ts index 6ffbfdb4342815..2e6e44062504da 100644 --- a/scripts/beachball/src/config.test.ts +++ b/scripts/beachball/src/config.test.ts @@ -28,7 +28,10 @@ describe(`beachball configs`, () => { it(`should generate shared config`, () => { expect(sharedConfig).toEqual({ + access: 'public', + branch: 'origin/master', changehint: "Run 'yarn change' to generate a change file", + commit: false, disallowedChangeTypes: ['major'], generateChangelog: true, hooks: { @@ -135,7 +138,7 @@ describe(`beachball configs`, () => { expect(vNextConfig.changelog.groups).toEqual([ { changelogPath: 'packages/react-components/react-components', - masterPackageName: '@fluentui/react-components', + mainPackageName: '@fluentui/react-components', include: includeScopes, }, ]); diff --git a/scripts/beachball/src/customRenderers.ts b/scripts/beachball/src/customRenderers.ts index 2b0bd0a2db3e35..90a68739e4ca47 100644 --- a/scripts/beachball/src/customRenderers.ts +++ b/scripts/beachball/src/customRenderers.ts @@ -42,6 +42,9 @@ export async function renderEntry(entry: ChangelogEntry): Promise { } async function _getPrNumber(entry: ChangelogEntry): Promise { + if (!entry.commit || entry.commit === 'not available') { + return undefined; + } // Look for (presumably) the PR number at the end of the first line of the commit try { // Get the actual commit message which should contain the PR number diff --git a/scripts/beachball/src/shared.config.ts b/scripts/beachball/src/shared.config.ts index 29ec60a5248963..f3cbb71bdca776 100644 --- a/scripts/beachball/src/shared.config.ts +++ b/scripts/beachball/src/shared.config.ts @@ -1,17 +1,18 @@ import { execSync } from 'child_process'; -import * as fs from 'fs'; -import * as path from 'path'; import type { BeachballConfig } from 'beachball'; import { renderEntry, renderHeader } from './customRenderers'; +import baseConfig from './base.config'; -const baseConfig: typeof import('../base.config.json') = JSON.parse( - fs.readFileSync(path.resolve(__dirname, '../base.config.json'), { encoding: 'utf8' }), -); - -export const config: typeof baseConfig & Required> = { +/** + * Shared Beachball release config. + */ +export const config: typeof baseConfig & Required> = { ...baseConfig, + // This can't be in the base config because people might use different names for remotes, + // but it should be safe in release pipelines. + branch: 'origin/master', changelog: { customRenderers: { renderHeader, diff --git a/scripts/beachball/src/utils.ts b/scripts/beachball/src/utils.ts index 350e347d384b76..204683f655972f 100644 --- a/scripts/beachball/src/utils.ts +++ b/scripts/beachball/src/utils.ts @@ -14,7 +14,7 @@ export function getConfig({ version }: { version: 'headless' }): { scope: string export function getConfig({ version }: { version: 'vNext' }): { scope: string[]; groupConfig: { - masterPackageName: string; + mainPackageName: string; changelogPath: string; include: string[]; }; @@ -26,7 +26,7 @@ export function getConfig({ version }: { version: 'v8' | 'vNext' | 'web-componen return { scope: [...vNextPaths], groupConfig: { - masterPackageName: '@fluentui/react-components', + mainPackageName: '@fluentui/react-components', changelogPath: 'packages/react-components/react-components', include: vNextPaths, }, diff --git a/scripts/beachball/tsconfig.json b/scripts/beachball/tsconfig.json index cd12b9358f4bc9..a95e1d6f4a43cc 100644 --- a/scripts/beachball/tsconfig.json +++ b/scripts/beachball/tsconfig.json @@ -7,8 +7,7 @@ "allowJs": true, "checkJs": true, "sourceMap": true, - "noUnusedLocals": true, - "resolveJsonModule": true + "noUnusedLocals": true }, "include": [], "files": [], diff --git a/scripts/update-release-notes/src/changelogsAndTags.ts b/scripts/update-release-notes/src/changelogsAndTags.ts index a07f20f83e9d2f..efd9a24125fbad 100644 --- a/scripts/update-release-notes/src/changelogsAndTags.ts +++ b/scripts/update-release-notes/src/changelogsAndTags.ts @@ -26,7 +26,7 @@ export function getTagToChangelogMap(maxAgeDays?: number): Map { const { commit, author: authorEmail } = entry; - + if (!commit || commit === 'not available') { + return undefined; + } const pr = await getPullRequestForCommit({ commit, github, diff --git a/tools/workspace-plugin/src/generators/prepare-initial-release/index.spec.ts b/tools/workspace-plugin/src/generators/prepare-initial-release/index.spec.ts index edbf880cf8e81e..b74e66a0a4b2d0 100644 --- a/tools/workspace-plugin/src/generators/prepare-initial-release/index.spec.ts +++ b/tools/workspace-plugin/src/generators/prepare-initial-release/index.spec.ts @@ -173,7 +173,7 @@ describe('prepare-initial-release generator', () => { expect(execCalls.length).toEqual(1); expect(execCalls[0].cmd).toMatchInlineSnapshot( - `"yarn change --message 'feat: release compat package' --type patch --package @proj/react-one-compat"`, + `"yarn change --message \\"feat: release compat package\\" --type patch --package @proj/react-one-compat"`, ); expect(execCalls[0].args).toMatchInlineSnapshot( { cwd: expect.any(String) }, @@ -273,7 +273,7 @@ describe('prepare-initial-release generator', () => { expect(execCalls.length).toEqual(1); expect(execCalls[0].cmd).toMatchInlineSnapshot( - `"yarn change --message 'feat: release preview package' --type minor --package @proj/react-one-preview"`, + `"yarn change --message \\"feat: release preview package\\" --type minor --package @proj/react-one-preview"`, ); expect(execCalls[0].args).toMatchInlineSnapshot( { cwd: expect.any(String) }, @@ -548,7 +548,7 @@ describe('prepare-initial-release generator', () => { expect(execCalls.length).toEqual(3); expect(execCalls[0].cmd).toMatchInlineSnapshot( - `"yarn change --message 'feat: release stable' --type minor --package @proj/react-one"`, + `"yarn change --message \\"feat: release stable\\" --type minor --package @proj/react-one"`, ); expect(execCalls[0].args).toMatchInlineSnapshot( { cwd: expect.any(String) }, @@ -561,7 +561,7 @@ describe('prepare-initial-release generator', () => { ); expect(execCalls[1].cmd).toMatchInlineSnapshot( - `"yarn change --message 'feat: add @proj/react-one to suite' --type minor --package @proj/react-components"`, + `"yarn change --message \\"feat: add @proj/react-one to suite\\" --type minor --package @proj/react-components"`, ); expect(execCalls[1].args).toMatchInlineSnapshot( { cwd: expect.any(String) }, diff --git a/tools/workspace-plugin/src/generators/prepare-initial-release/index.ts b/tools/workspace-plugin/src/generators/prepare-initial-release/index.ts index e5ae740281b08f..a1b4b544b3fa02 100644 --- a/tools/workspace-plugin/src/generators/prepare-initial-release/index.ts +++ b/tools/workspace-plugin/src/generators/prepare-initial-release/index.ts @@ -444,7 +444,7 @@ function generateChangefileTask( projectName: string, options: { changeType: 'minor' | 'patch'; message: string }, ) { - const cmd = `yarn change --message '${options.message}' --type ${options.changeType} --package ${projectName}`; + const cmd = `yarn change --message "${options.message}" --type ${options.changeType} --package ${projectName}`; return execSync(cmd, { cwd: workspaceRoot, stdio: 'inherit' }); } diff --git a/yarn.lock b/yarn.lock index f653926088cf89..af96d47db13f2b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2871,7 +2871,6 @@ __metadata: "@types/webpack-env": "npm:1.18.8" "@types/webpack-hot-middleware": "npm:2.25.9" "@types/yargs": "npm:13.0.11" - "@types/yargs-unparser": "npm:2.0.1" "@typescript-eslint/eslint-plugin": "npm:8.46.2" "@typescript-eslint/rule-tester": "npm:^8.46.2" autoprefixer: "npm:10.2.1" @@ -2884,7 +2883,7 @@ __metadata: babel-plugin-module-resolver: "npm:5.0.3" babel-plugin-react-compiler: "npm:1.0.0" babel-plugin-tester: "npm:10.1.0" - beachball: "npm:2.31.0" + beachball: "npm:3.0.0-alpha.7" chalk: "npm:4.1.0" chrome-remote-interface: "npm:0.28.2" ci-info: "npm:3.9.0" @@ -2990,7 +2989,6 @@ __metadata: react-shadow: "npm:20.3.0" react-test-renderer: "npm:19.2.0" react-window: "npm:^1.8.6" - read-pkg-up: "npm:7.0.1" remark-gfm: "npm:4.0.1" replace-in-file: "npm:6.1.0" resolve: "npm:1.22.8" @@ -3038,10 +3036,8 @@ __metadata: webpack-dev-server: "npm:4.15.2" webpack-hot-middleware: "npm:2.26.1" webpack-merge: "npm:5.10.0" - workspace-tools: "npm:0.29.1" yargs: "npm:13.3.2" yargs-parser: "npm:13.1.2" - yargs-unparser: "npm:2.0.0" languageName: unknown linkType: soft @@ -10624,13 +10620,6 @@ __metadata: languageName: node linkType: hard -"@types/normalize-package-data@npm:^2.4.0": - version: 2.4.0 - resolution: "@types/normalize-package-data@npm:2.4.0" - checksum: 10c0/f5504a9fe5cb6b82d9d2fb7982e4681f51bd31dc6c4750f833ca6499a2372294e58c0e2e0f5d78066f3c212c553c85cdbf653c5d6035f902d00822e7f3590c28 - languageName: node - linkType: hard - "@types/parse-json@npm:^4.0.0": version: 4.0.0 resolution: "@types/parse-json@npm:4.0.0" @@ -10638,6 +10627,13 @@ __metadata: languageName: node linkType: hard +"@types/parse-path@npm:^7.0.0": + version: 7.0.3 + resolution: "@types/parse-path@npm:7.0.3" + checksum: 10c0/8344b6c7acba4e4e5a8d542f56f53c297685fa92f9b0c085d7532cc7e1b661432cecfc1c75c76cdb0d161c95679b6ecfe0573d9fef7c836962aacf604150a984 + languageName: node + linkType: hard + "@types/parse5@npm:^5.0.0": version: 5.0.3 resolution: "@types/parse5@npm:5.0.3" @@ -11063,13 +11059,6 @@ __metadata: languageName: node linkType: hard -"@types/yargs-unparser@npm:2.0.1": - version: 2.0.1 - resolution: "@types/yargs-unparser@npm:2.0.1" - checksum: 10c0/fdb85acc6d530e3d980f110588f5f48ae51e9e8477f056d539c70401a3e95d53a0c03c712292a683b63048a3c2033eab6c0fc06bd2541b4f03f046f177028ee7 - languageName: node - linkType: hard - "@types/yargs@npm:13.0.11": version: 13.0.11 resolution: "@types/yargs@npm:13.0.11" @@ -11561,6 +11550,13 @@ __metadata: languageName: node linkType: hard +"@vercel/detect-agent@npm:^1.2.1": + version: 1.2.3 + resolution: "@vercel/detect-agent@npm:1.2.3" + checksum: 10c0/12eb2e11603b0e9ff2fe89f969eac2327315a0f71b68acba2e4fe71f2ee6d282c519ccb7aa3b43e9b748a6db00517b88aa93628a20dbdab9ef6d8a003f8980e9 + languageName: node + linkType: hard + "@vitest/expect@npm:3.2.4": version: 3.2.4 resolution: "@vitest/expect@npm:3.2.4" @@ -13355,25 +13351,21 @@ __metadata: languageName: node linkType: hard -"beachball@npm:2.31.0": - version: 2.31.0 - resolution: "beachball@npm:2.31.0" +"beachball@npm:3.0.0-alpha.7": + version: 3.0.0-alpha.7 + resolution: "beachball@npm:3.0.0-alpha.7" dependencies: - cosmiconfig: "npm:^7.0.0" - execa: "npm:^5.0.0" - fs-extra: "npm:^10.0.0" - lodash: "npm:^4.17.15" - minimatch: "npm:^3.0.4" - p-limit: "npm:^3.0.2" - prompts: "npm:^2.1.0" - semver: "npm:^7.0.0" - toposort: "npm:^2.0.2" - uuid: "npm:^9.0.0" - workspace-tools: "npm:^0.27.0" - yargs-parser: "npm:^21.0.0" + "@vercel/detect-agent": "npm:^1.2.1" + commander: "npm:^14.0.3" + nano-spawn: "npm:^2.1.0" + p-graph: "npm:^3.0.0-alpha.4" + p-limit: "npm:^3.1.0" + prompts: "npm:^2.4.2" + semver: "npm:^7.7.4" + workspace-tools: "npm:^0.42.0" bin: beachball: bin/beachball.js - checksum: 10c0/355ad1f7f252e320f9e900bb68a4774cc39a86e9771b1df9dc4078b99eae60f8125134aa87724642120d2673e09ffeab0f09801c17e48622a0fe621249e71bbd + checksum: 10c0/5f4bd3f00bf5c99dcd40887fcc099ef808f80f4c939066fed0c2ff12217e65a644f53dac1f3f08babac52e3d82970ce9cbac67890886a5a8fde1d2748f54f41c languageName: node linkType: hard @@ -14754,6 +14746,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^14.0.3": + version: 14.0.3 + resolution: "commander@npm:14.0.3" + checksum: 10c0/755652564bbf56ff2ff083313912b326450d3f8d8c85f4b71416539c9a05c3c67dbd206821ca72635bf6b160e2afdefcb458e86b317827d5cb333b69ce7f1a24 + languageName: node + linkType: hard + "commander@npm:^2.20.0": version: 2.20.3 resolution: "commander@npm:2.20.3" @@ -18128,7 +18127,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.0.3, fast-glob@npm:^3.1.1, fast-glob@npm:^3.2.5, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.2": +"fast-glob@npm:^3.0.3, fast-glob@npm:^3.1.1, fast-glob@npm:^3.2.5, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.2, fast-glob@npm:^3.3.3": version: 3.3.3 resolution: "fast-glob@npm:3.3.3" dependencies: @@ -19232,22 +19231,22 @@ __metadata: languageName: node linkType: hard -"git-up@npm:^7.0.0": - version: 7.0.0 - resolution: "git-up@npm:7.0.0" +"git-up@npm:^8.1.0": + version: 8.1.1 + resolution: "git-up@npm:8.1.1" dependencies: is-ssh: "npm:^1.4.0" - parse-url: "npm:^8.1.0" - checksum: 10c0/a3fa02e1a63c7c824b5ebbf23f4a9a6b34dd80031114c5dd8adb7ef53493642e39d3d80dfef4025a452128400c35c2c138d20a0f6ae5d7d7ef70d9ba13083d34 + parse-url: "npm:^9.2.0" + checksum: 10c0/2cc4461d8565a3f7a1ecd3d262a58ddb8df0a67f7f7d4915df2913c460b2e88ae570a6ea810700a6d22fb3b9e4bea8dd10a8eb469900ddc12e35c62208608c03 languageName: node linkType: hard -"git-url-parse@npm:^13.0.0": - version: 13.1.0 - resolution: "git-url-parse@npm:13.1.0" +"git-url-parse@npm:^16.1.0": + version: 16.1.0 + resolution: "git-url-parse@npm:16.1.0" dependencies: - git-up: "npm:^7.0.0" - checksum: 10c0/2ef6126c42d999e240dbcdf1e96172cf7a2044ffa1ef78a518acf823df9bbe2a1ea9e6b443d42948e3c581e4d899559afc4c1de024b3eaa8eb6a4229f73285aa + git-up: "npm:^8.1.0" + checksum: 10c0/b8f5ebcbd5b2baf9f1bb77a217376f0247c47fe1d42811ccaac3015768eebb0759a59051f758e50e70adf5c67ae059d1975bf6b750164f36bfd39138d11b940b languageName: node linkType: hard @@ -19448,7 +19447,7 @@ __metadata: languageName: node linkType: hard -"globby@npm:11.1.0, globby@npm:^11.0.0, globby@npm:^11.0.1, globby@npm:^11.1.0": +"globby@npm:11.1.0, globby@npm:^11.0.1, globby@npm:^11.1.0": version: 11.1.0 resolution: "globby@npm:11.1.0" dependencies: @@ -22045,25 +22044,25 @@ __metadata: linkType: hard "js-yaml@npm:^3.10.0, js-yaml@npm:^3.13.1": - version: 3.13.1 - resolution: "js-yaml@npm:3.13.1" + version: 3.15.0 + resolution: "js-yaml@npm:3.15.0" dependencies: argparse: "npm:^1.0.7" esprima: "npm:^4.0.0" bin: js-yaml: bin/js-yaml.js - checksum: 10c0/6a4f78b998d2eb58964cc5e051c031865bf292dc3c156a8057cf468d9e60a8739f4e8f607a267e97f09eb8d08263b8262df57eddb16b920ec5a04a259c3b4960 + checksum: 10c0/ca966bd354ac5b1b7a4694ebdba46526796aa3a6a99529fa540af2abf85918bd155a50ccc0166b413130a00622999973754458ec01e7095bc902177bfdbd5b64 languageName: node linkType: hard -"js-yaml@npm:^4.0.0, js-yaml@npm:^4.1.0": - version: 4.1.0 - resolution: "js-yaml@npm:4.1.0" +"js-yaml@npm:^4.0.0, js-yaml@npm:^4.1.0, js-yaml@npm:^4.2.0": + version: 4.3.0 + resolution: "js-yaml@npm:4.3.0" dependencies: argparse: "npm:^2.0.1" bin: js-yaml: bin/js-yaml.js - checksum: 10c0/184a24b4eaacfce40ad9074c64fd42ac83cf74d8c8cd137718d456ced75051229e5061b8633c3366b8aada17945a7a356b337828c19da92b51ae62126575018f + checksum: 10c0/058b30473d6915ca5b4feb11e2f7d4d97242f98d00a798ed48dd90b46b7c640398afe9128c5db22c5300f8c6528fe2a174b9a93f351a70ebc28c6203938d8bff languageName: node linkType: hard @@ -24875,6 +24874,13 @@ __metadata: languageName: node linkType: hard +"nano-spawn@npm:^2.1.0": + version: 2.1.0 + resolution: "nano-spawn@npm:2.1.0" + checksum: 10c0/3becc67ed9ab630b6572feab69a4ef468891ad1f89d5c8643f14a2044cf32ba64533033506208039b1e3d9ddcb2f5f4f87ec360f13b3c4f0774304aedf0f0290 + languageName: node + linkType: hard + "nano-staged@npm:0.9.0": version: 0.9.0 resolution: "nano-staged@npm:0.9.0" @@ -25158,7 +25164,7 @@ __metadata: languageName: node linkType: hard -"normalize-package-data@npm:^2.3.2, normalize-package-data@npm:^2.5.0": +"normalize-package-data@npm:^2.3.2": version: 2.5.0 resolution: "normalize-package-data@npm:2.5.0" dependencies: @@ -25660,6 +25666,13 @@ __metadata: languageName: node linkType: hard +"p-graph@npm:^3.0.0-alpha.4": + version: 3.0.0-alpha.4 + resolution: "p-graph@npm:3.0.0-alpha.4" + checksum: 10c0/84452847e6cb761aedcfe1d2d02faff2fd8e9155807e97e7beb90006d2e14e46c2f55c51b3578198a1d28b9c3e576bef9980a063e47b5ff681655d1433c6a03f + languageName: node + linkType: hard + "p-limit@npm:^2.0.0, p-limit@npm:^2.2.0": version: 2.3.0 resolution: "p-limit@npm:2.3.0" @@ -26017,12 +26030,13 @@ __metadata: languageName: node linkType: hard -"parse-url@npm:^8.1.0": - version: 8.1.0 - resolution: "parse-url@npm:8.1.0" +"parse-url@npm:^9.2.0": + version: 9.2.0 + resolution: "parse-url@npm:9.2.0" dependencies: + "@types/parse-path": "npm:^7.0.0" parse-path: "npm:^7.0.0" - checksum: 10c0/68b95afdf4bbf72e57c7ab66f8757c935fff888f7e2b0f1e06098b4faa19e06b6b743bddaed5bc8df4f0c2de6fc475355d787373b2fdd40092be9e4e4b996648 + checksum: 10c0/b8f56cdb01e76616255dff82544f4b5ab4378f6f4bac8604ed6fde03a75b0f71c547d92688386d8f22f38fad3c928c075abf69458677c6185da76c841bfd7a93 languageName: node linkType: hard @@ -26761,7 +26775,7 @@ __metadata: languageName: node linkType: hard -"prompts@npm:^2.1.0, prompts@npm:^2.4.0": +"prompts@npm:^2.4.0, prompts@npm:^2.4.2": version: 2.4.2 resolution: "prompts@npm:2.4.2" dependencies: @@ -27291,17 +27305,6 @@ __metadata: languageName: node linkType: hard -"read-pkg-up@npm:7.0.1": - version: 7.0.1 - resolution: "read-pkg-up@npm:7.0.1" - dependencies: - find-up: "npm:^4.1.0" - read-pkg: "npm:^5.2.0" - type-fest: "npm:^0.8.1" - checksum: 10c0/82b3ac9fd7c6ca1bdc1d7253eb1091a98ff3d195ee0a45386582ce3e69f90266163c34121e6a0a02f1630073a6c0585f7880b3865efcae9c452fa667f02ca385 - languageName: node - linkType: hard - "read-pkg-up@npm:^1.0.1": version: 1.0.1 resolution: "read-pkg-up@npm:1.0.1" @@ -27323,18 +27326,6 @@ __metadata: languageName: node linkType: hard -"read-pkg@npm:^5.2.0": - version: 5.2.0 - resolution: "read-pkg@npm:5.2.0" - dependencies: - "@types/normalize-package-data": "npm:^2.4.0" - normalize-package-data: "npm:^2.5.0" - parse-json: "npm:^5.0.0" - type-fest: "npm:^0.6.0" - checksum: 10c0/b51a17d4b51418e777029e3a7694c9bd6c578a5ab99db544764a0b0f2c7c0f58f8a6bc101f86a6fceb8ba6d237d67c89acf6170f6b98695d0420ddc86cf109fb - languageName: node - linkType: hard - "read-yaml-file@npm:2.1.0": version: 2.1.0 resolution: "read-yaml-file@npm:2.1.0" @@ -30445,13 +30436,6 @@ __metadata: languageName: node linkType: hard -"toposort@npm:^2.0.2": - version: 2.0.2 - resolution: "toposort@npm:2.0.2" - checksum: 10c0/ab9ca91fce4b972ccae9e2f539d755bf799a0c7eb60da07fd985fce0f14c159ed1e92305ff55697693b5bc13e300f5417db90e2593b127d421c9f6c440950222 - languageName: node - linkType: hard - "totalist@npm:^3.0.0": version: 3.0.1 resolution: "totalist@npm:3.0.1" @@ -30819,20 +30803,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^0.6.0": - version: 0.6.0 - resolution: "type-fest@npm:0.6.0" - checksum: 10c0/0c585c26416fce9ecb5691873a1301b5aff54673c7999b6f925691ed01f5b9232db408cdbb0bd003d19f5ae284322523f44092d1f81ca0a48f11f7cf0be8cd38 - languageName: node - linkType: hard - -"type-fest@npm:^0.8.1": - version: 0.8.1 - resolution: "type-fest@npm:0.8.1" - checksum: 10c0/dffbb99329da2aa840f506d376c863bd55f5636f4741ad6e65e82f5ce47e6914108f44f340a0b74009b0cb5d09d6752ae83203e53e98b1192cf80ecee5651636 - languageName: node - linkType: hard - "type-fest@npm:^4.41.0": version: 4.41.0 resolution: "type-fest@npm:4.41.0" @@ -31654,15 +31624,6 @@ __metadata: languageName: node linkType: hard -"uuid@npm:^9.0.0": - version: 9.0.0 - resolution: "uuid@npm:9.0.0" - bin: - uuid: dist/bin/uuid - checksum: 10c0/8867e438990d1d33ac61093e2e4e3477a2148b844e4fa9e3c2360fa4399292429c4b6ec64537eb1659c97b2d10db349c673ad58b50e2824a11e0d3630de3c056 - languageName: node - linkType: hard - "uvu@npm:^0.5.0": version: 0.5.6 resolution: "uvu@npm:0.5.6" @@ -32422,31 +32383,17 @@ __metadata: languageName: node linkType: hard -"workspace-tools@npm:0.29.1": - version: 0.29.1 - resolution: "workspace-tools@npm:0.29.1" +"workspace-tools@npm:^0.42.0": + version: 0.42.0 + resolution: "workspace-tools@npm:0.42.0" dependencies: "@yarnpkg/lockfile": "npm:^1.1.0" - git-url-parse: "npm:^13.0.0" - globby: "npm:^11.0.0" + fast-glob: "npm:^3.3.3" + git-url-parse: "npm:^16.1.0" jju: "npm:^1.4.0" - js-yaml: "npm:^4.1.0" - micromatch: "npm:^4.0.0" - checksum: 10c0/d33659484c1abc93aa262b844889ff9293b48f0c61c21ec707e530fb5061283b9e3dcd5754e85fae078da7879bcb8d88d496c5ee18fb1c38d3192101b56d038e - languageName: node - linkType: hard - -"workspace-tools@npm:^0.27.0": - version: 0.27.0 - resolution: "workspace-tools@npm:0.27.0" - dependencies: - "@yarnpkg/lockfile": "npm:^1.1.0" - git-url-parse: "npm:^13.0.0" - globby: "npm:^11.0.0" - jju: "npm:^1.4.0" - js-yaml: "npm:^4.1.0" - micromatch: "npm:^4.0.0" - checksum: 10c0/8b117f56c055bd8350e22d0a4ec72fc86e27ff7f1359a04d51d9f27a3798928031e3c099ce3a8cf8eda9a49e37222ffeb9b314dad8e428fad3c364abbbae8b73 + js-yaml: "npm:^4.2.0" + micromatch: "npm:^4.0.8" + checksum: 10c0/a39edf688de49f3e183ab57ffd0b0740350048b2c5fc656bfee93ec9c438bd90b07b98033e52709f8d92b7eef65fc5c8c70632e47f972601650706819db3d114 languageName: node linkType: hard @@ -32683,7 +32630,7 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:21.1.1, yargs-parser@npm:^21.0.0, yargs-parser@npm:^21.1.1": +"yargs-parser@npm:21.1.1, yargs-parser@npm:^21.1.1": version: 21.1.1 resolution: "yargs-parser@npm:21.1.1" checksum: 10c0/f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2 @@ -32724,7 +32671,7 @@ __metadata: languageName: node linkType: hard -"yargs-unparser@npm:2.0.0, yargs-unparser@npm:^2.0.0": +"yargs-unparser@npm:^2.0.0": version: 2.0.0 resolution: "yargs-unparser@npm:2.0.0" dependencies: From d30a0b2ce67f5a7a17bc8273ca83d6d382f6a788 Mon Sep 17 00:00:00 2001 From: Elizabeth Craig Date: Wed, 5 Aug 2026 04:13:23 -0700 Subject: [PATCH 2/4] fix registry --- scripts/beachball/src/config.test.ts | 1 + scripts/beachball/src/shared.config.ts | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/beachball/src/config.test.ts b/scripts/beachball/src/config.test.ts index 2e6e44062504da..0c1c3244b03f6c 100644 --- a/scripts/beachball/src/config.test.ts +++ b/scripts/beachball/src/config.test.ts @@ -58,6 +58,7 @@ describe(`beachball configs`, () => { '**/SPEC*.md', '**/tests/**', ], + registry: 'https://registry.npmjs.org', scope: ['!packages/fluentui/*'], tag: 'latest', changelog: { diff --git a/scripts/beachball/src/shared.config.ts b/scripts/beachball/src/shared.config.ts index f3cbb71bdca776..b7e3bf12cd9342 100644 --- a/scripts/beachball/src/shared.config.ts +++ b/scripts/beachball/src/shared.config.ts @@ -8,11 +8,14 @@ import baseConfig from './base.config'; /** * Shared Beachball release config. */ -export const config: typeof baseConfig & Required> = { +export const config: typeof baseConfig & + Required> = { ...baseConfig, // This can't be in the base config because people might use different names for remotes, // but it should be safe in release pipelines. branch: 'origin/master', + // In beachball v3 alpha, this is required if NPM_TOKEN is used. + registry: 'https://registry.npmjs.org', changelog: { customRenderers: { renderHeader, From 6bce67e414355e23b7d5cb4788924e952d2aba6c Mon Sep 17 00:00:00 2001 From: Elizabeth Craig Date: Thu, 6 Aug 2026 19:51:23 -0700 Subject: [PATCH 3/4] revert skill changes --- .agents/skills/beachball-change-file/SKILL.md | 148 ------------------ .agents/skills/change/SKILL.md | 47 ++++++ .github/instructions/copilot.instructions.md | 7 +- AGENTS.md | 24 +-- 4 files changed, 64 insertions(+), 162 deletions(-) delete mode 100644 .agents/skills/beachball-change-file/SKILL.md create mode 100644 .agents/skills/change/SKILL.md diff --git a/.agents/skills/beachball-change-file/SKILL.md b/.agents/skills/beachball-change-file/SKILL.md deleted file mode 100644 index 24cb968fdd6625..00000000000000 --- a/.agents/skills/beachball-change-file/SKILL.md +++ /dev/null @@ -1,148 +0,0 @@ ---- -description: How to create a Beachball change file. ONLY use this skill when the user asks to generate change files, before pushing a branch, or before creating a PR. -license: MIT -metadata: - github-path: skills/beachball-change-file - github-ref: refs/heads/main - github-repo: https://github.com/microsoft/beachball - github-tree-sha: 5198ce6d081a41c46a6a1bbf211418972596ef33 - source: https://github.com/microsoft/beachball/blob/main/skills/beachball-change-file/SKILL.md - version: 1.0.6 -name: beachball-change-file ---- - -[Beachball](https://microsoft.github.io/beachball/) is a tool used for managing versioning and changelogs for JS/TS codebases. Every pull request must include a Beachball change file. Change files include the list of packages with public-facing changes in the branch, with the description and semver change type for each package. After the PR is checked in and a release is run, the change files are used to determine version bumps and update changelogs. - -Beachball normally uses a CLI with an interactive prompt to create change files, but they can also be created manually using the standardized JSON format detailed below. - -## Prerequisites - -- Determine the root directory: this is almost always the git root, but the user might specify a different folder. (The root usually contains `beachball.config.*` or `.beachballrc.*` or has a `"beachball"` key in `package.json`.) -- Determine the package manager for the repo (`npm`, `yarn`, `pnpm`). The example commands below assume `yarn`, but substitute the appropriate command runner syntax for a different package manager. -- Check the root `package.json` `scripts` for scripts that run `beachball change` and `beachball check`. - - The examples below assume `scripts` called `change` and `checkchange` respectively, but substitute the appropriate script names if found. - - Using `scripts` if defined is preferred since they may add extra arguments, but it's possible to run the commands directly: `yarn beachball change` and `yarn beachball check` (substituting appropriate command runner) -- Use `beachball config get` to check the following settings (note: `beachball config get` only exists in versions `>= 2.64.0`) - - `yarn beachball config get changeDir`: where to put the change files - - `yarn beachball config get branch`: target branch name - - `yarn beachball config get groupChanges`: whether grouped change files are enabled (true/false/undefined) - -## Creating and validating a change file - -Usually, an AI agent should create a change file manually following the standardized format detailed below. - -### 1. Validate repo state - -Beachball only considers staged and committed files, so you should check for unstaged or untracked changes before proceeding: - -1. Get file paths with unstaged changes (`git ls-files -m`) and untracked changes (`git ls-files -o --exclude-standard`) -2. If there are any unstaged or untracked changes, ask the user whether they would like to stage all files or continue without staging. If they choose to stage, run `git add .` before proceeding. - -### 2. Get changed packages - -Run `yarn checkchange --verbose` to get the list of changed packages and files considered by `beachball`: - -- The list of changed packages is under "Found changes in the following packages" -- you must ONLY include these packages in the change file! (beachball has various settings to ignore packages or files) -- The list of changed files is under "changed files in current branch". IGNORE any files with `~~` strikethrough formatting. - -DO NOT manually check for existing change files. - -### 3. Create the change file(s) - -Change files are located under ``. There are two possible structures for change files, determined by the `groupChanges` setting. - -When checking diffs to generate change files, DO NOT merge with the target branch; just use the local merge-base. - -#### Case 1: Non-grouped format (`groupChanges` is `false` or unset) - -If `groupChanges` is `false` or unset, you should create a separate change file for each package. - -For each changed package **as listed by beachball**: - -1. Generate a random GUID: `node -e "console.log(crypto.randomUUID())"` -2. Create a change file under `/-.json` with the following format. See [Change entry values](#change-entry-values) below for the proper values of each field. - -```json -{ - "packageName": "", - "type": "", - "dependentChangeType": "", - "comment": "", - "email": "" -} -``` - -#### Case 2: Grouped format (`groupChanges: true`) - -If `groupChanges` is `true`, you should create a single change file. - -1. Generate a random GUID: `node -e "console.log(crypto.randomUUID())"` -2. Create a single change file under `/change-.json` with the following format. The `changes` array should have an entry for each changed package **as listed by beachball**. See [Change entry values](#change-entry-values) below for the proper values of each field. - -```json -{ - "changes": [ - { - "packageName": "", - "type": "", - "dependentChangeType": "", - "comment": "", - "email": "" - } - ] -} -``` - -### 4. Validate the change file(s) - -Run `git add `, then re-run `yarn checkchange` to verify. - -## Change entry values - -Each package's entry has the following values: - -- `packageName`: The name of the changed package, e.g. `just-task` -- `type`: The semantic versioning change type for the package. See [Determining a package's change type](#determining-a-packages-change-type) below. -- `dependentChangeType`: Change type for packages that depend on this package. If `type` is `"none"`, this should be `"none"`. Otherwise, this should be `"patch"` (beachball internally handles this for the special case of prerelease packages). -- `comment` (`--message` CLI arg): A concise description of the changes made to the package. Tips: - - This will go in the changelog, so it should focus on user-facing changes (especially any API changes) rather than implementation details. - - Markdown formatting is allowed, so any references to names from code should be wrapped with backticks. -- `email`: User's email from `git config user.email`, or `"email not defined"` if not available. Do NOT invent an email. - -### Determining a package's change type - -The `type` field is the semantic versioning change type for the package, determined based on the diff content of changed files in that package. There are different options depending on whether the package's current version contains a prerelease suffix or not, and the `disallowedChangeTypes` setting may modify which change types are allowed. - -If you're still uncertain about the change type after following the instructions below, ask the user to choose. - -For each package, start by checking: - -- The current `version` in `package.json` -- `disallowedChangeTypes` for the specific package: `yarn beachball config get disallowedChangeTypes --package ` -- Whether the package has a file `/etc/*.api.md`. If so, the diff of this file will show whether any public API signatures changed. - -#### Case 1: Version is 1.0.0 or greater and NOT prerelease - -If the package's current version is 1.0.0 or greater and does NOT have a prerelease suffix, the typical options are `` (but you MUST respect `disallowedChangeTypes`): - -- `"patch"`: Bug fixes or other changes that don't impact exported API signatures. -- `"minor"`: New exported APIs, non-breaking signature changes to exported APIs, or more significant changes to internal logic. (If the package has a `/etc/*.api.md` file, checking its diff is the easiest way to see exported API changes.) -- `"major"`: Breaking changes to exported APIs (removals or breaking signature changes), critical dependency updates, or behavior changes that might be breaking for the consumer. You MUST confirm with the user before choosing `"major"`. -- `"none"`: None of the changes will impact consumers of the package (e.g. the changes are only to non-exported test-specific files or documentation). If you're not certain, prefer `"patch"`. -- There are additional options `prerelease|premajor|preminor|prepatch`, but you should only use one of these if explicitly requested by the user. - -#### Case 2: Version is 0.x.y and NOT prerelease - -If the package's major version is 0 and does NOT have a prerelease suffix, this is similar to case 1. However, version 0 packages follow different conventions for semantic versioning (you MUST still respect `disallowedChangeTypes`): - -- Use `"minor"` for breaking changes (do NOT use `"major"` unless specifically requested) -- Use `"patch"` for any other changes that impact consumers of the package -- Use `"none"` in the same circumstances as case 1 - -#### Case 3: Version IS prerelease - -ONLY if the package's current version includes a prerelease suffix, the typical options are `` (but you MUST respect `disallowedChangeTypes`): - -- `"prerelease"`: Any changes that impact consumers of the package -- `"none"`: None of the changes will impact consumers of the package (e.g. the changes are only to non-exported test-specific files or documentation). If you're not certain, prefer `"prerelease"`. -- There are additional options `premajor|preminor|prepatch`, but you should only use one of these if explicitly requested by the user or all other change types are disallowed. diff --git a/.agents/skills/change/SKILL.md b/.agents/skills/change/SKILL.md new file mode 100644 index 00000000000000..7a0570b27d2a77 --- /dev/null +++ b/.agents/skills/change/SKILL.md @@ -0,0 +1,47 @@ +--- +name: change +description: Create a beachball change file for the current changes. Determines change type (patch/minor) and generates a description from the diff. +disable-model-invocation: true +allowed-tools: Bash Read Grep Glob +--- + +# Create a Beachball Change File + +Generate a change file for the current branch's modifications using the repo's beachball setup. + +## Steps + +1. **Determine the change type:** + + - `patch` — bug fixes, internal refactors, test-only changes + - `minor` — new features, new exports, new component variants + - `none` — changes that don't affect the published package (stories, docs, tests only) + - Never use `major` without explicit user approval + +2. **Generate a descriptive message** following the format: `fix(package-name): description` or `feat(package-name): description` + +3. **Run the repo's change script** to create the change file: + + ```bash + yarn change + ``` + + This runs `beachball change --no-commit` (configured in root `package.json`). + Beachball automatically detects which packages need change files. + + For non-interactive usage with a specific type and message: + + ```bash + yarn beachball change --no-commit --type --message "" + ``` + +4. **Verify** the change file was created: + + ```bash + yarn check:change + ``` + +## Rules + +- Always use `yarn change` or `yarn beachball change` — never manually create change files +- The message should describe the user-facing impact, not the implementation detail diff --git a/.github/instructions/copilot.instructions.md b/.github/instructions/copilot.instructions.md index ff2470c88cac2b..0cea69b329340f 100644 --- a/.github/instructions/copilot.instructions.md +++ b/.github/instructions/copilot.instructions.md @@ -69,6 +69,9 @@ yarn nx run :start # Start Storybook for component # Component generation (v9 only) yarn create-component # Interactive component generator +# Release management +yarn change # Create beachball change file (required for PRs) + # Show project targets yarn nx show projects # List all projects ``` @@ -82,7 +85,7 @@ yarn nx show projects # List all projects 3. Follow hook-based architecture pattern exactly 4. Add comprehensive tests and Storybook stories 5. Run `yarn nx run :generate-api` to update API docs -6. Create change file with `/beachball-change-file` skill before PR +6. Create change file with `yarn change` before PR **For v8 components** (maintenance only): @@ -460,7 +463,7 @@ The repository uses a triage bot that automatically assigns labels and assignees 1. Labels are automatically applied based on changed files 2. Focus on clear PR titles and descriptions 3. Reference related issues with proper syntax (`Fixes #123`) -4. Create change files for changes impacting published code (`/beachball-change-file` skill) +4. Create change files for breaking changes (`yarn change`) **For Maintainers**: diff --git a/AGENTS.md b/AGENTS.md index f92f43788dbe1f..ba571e028485b6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,7 +22,7 @@ from existing code without verifying they match these instructions. 2. **Never use `React.FC`.** Always use `ForwardRefComponent` with `React.forwardRef`. 3. **Never access `window`, `document`, or `navigator` directly.** In v9 components, use `useFluent_unstable()` to get `targetDocument` and `targetDocument.defaultView` instead of `document`/`window`. For non-component code, use `canUseDOM()` from `@fluentui/react-utilities`. 4. **Never add dependencies between component packages.** `react-button` must not depend on `react-menu`. Shared logic goes in `react-utilities` or `react-shared-contexts`. See [docs/architecture/layers.md](docs/architecture/layers.md). -5. **Never skip beachball change files** for published package changes. Use the `/beachball-change-file` skill. +5. **Never skip beachball change files** for published package changes. Run `yarn beachball change`. ## V9 Component Template (the correct pattern) @@ -91,17 +91,17 @@ state.root.className = mergeClasses( ## Skills (Slash Commands) -| Skill | Command | Purpose | -| ----------------------- | ------------------------ | -------------------------------------------------------------------- | -| `v9-component` | `/v9-component Name` | Scaffold a new v9 component with all required files | -| `beachball-change-file` | `/beachball-change-file` | Create beachball change file from current diff | -| `lint-check` | `/lint-check [pkg]` | Run lint, parse errors, and auto-fix common issues | -| `token-lookup` | `/token-lookup val` | Find the design token for a hardcoded CSS value | -| `package-info` | `/package-info pkg` | Quick lookup: path, deps, owner, tests, structure | -| `visual-test` | `/visual-test Name` | Visually verify a component via Storybook + playwright-cli | -| `review-pr` | `/review-pr #123` | Review a PR with confidence scoring and category checks | -| `triage-issues` | `/triage-issues` | Walk the Needs-Triage queue and recommend labels/assignee | -| `dependabot-rollup` | `/dependabot-rollup` | Dry-run and optionally roll up at most 11 Dependabot patch/minor PRs | +| Skill | Command | Purpose | +| ------------------- | -------------------- | -------------------------------------------------------------------- | +| `v9-component` | `/v9-component Name` | Scaffold a new v9 component with all required files | +| `change` | `/change` | Create beachball change file from current diff | +| `lint-check` | `/lint-check [pkg]` | Run lint, parse errors, and auto-fix common issues | +| `token-lookup` | `/token-lookup val` | Find the design token for a hardcoded CSS value | +| `package-info` | `/package-info pkg` | Quick lookup: path, deps, owner, tests, structure | +| `visual-test` | `/visual-test Name` | Visually verify a component via Storybook + playwright-cli | +| `review-pr` | `/review-pr #123` | Review a PR with confidence scoring and category checks | +| `triage-issues` | `/triage-issues` | Walk the Needs-Triage queue and recommend labels/assignee | +| `dependabot-rollup` | `/dependabot-rollup` | Dry-run and optionally roll up at most 11 Dependabot patch/minor PRs | ## Package Layout From 612f4811b637e3043c89652e2efb7f70aff49671 Mon Sep 17 00:00:00 2001 From: Elizabeth Craig Date: Fri, 7 Aug 2026 15:13:53 -0700 Subject: [PATCH 4/4] move base config and revert contributing doc --- beachball.config.js | 2 +- docs/workflows/contributing.md | 10 +++++++--- scripts/beachball/{src => }/base.config.js | 3 +++ scripts/beachball/src/shared.config.ts | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) rename scripts/beachball/{src => }/base.config.js (77%) diff --git a/beachball.config.js b/beachball.config.js index e1a1b88e474958..af2178ece96f52 100644 --- a/beachball.config.js +++ b/beachball.config.js @@ -1 +1 @@ -module.exports = require('./scripts/beachball/src/base.config'); +module.exports = require('./scripts/beachball/base.config'); diff --git a/docs/workflows/contributing.md b/docs/workflows/contributing.md index dc0dddee813911..34494467790d51 100644 --- a/docs/workflows/contributing.md +++ b/docs/workflows/contributing.md @@ -9,7 +9,7 @@ yarn clean # Clean build artifacts # Development yarn start # Interactive project selector -yarn nx run :build # Build specific project +yarn nx run :build # Build specific project yarn nx run :start # Start Storybook for component yarn nx run :test # Run unit tests yarn nx run :test -u # Update snapshots @@ -27,9 +27,13 @@ yarn create-component # Interactive generator ## PR Checklist -1. **Change file** — Run `yarn change` to interactively generate change files for any published package changes. (AI agents should use the `/beachball-change-file` skill instead.) +1. **Change file** — Required for any published package change: - Use `patch` for fixes, `minor` for features (or see [more info about choosing a change type](https://microsoft.github.io/beachball/concepts/change-types.html)). Never use `major` without approval. + ```bash + yarn beachball change --type patch --message "fix(react-button): description" + ``` + + Use `patch` for fixes, `minor` for features. Never `major` without approval. 2. **Tests pass** — `yarn nx run :test` diff --git a/scripts/beachball/src/base.config.js b/scripts/beachball/base.config.js similarity index 77% rename from scripts/beachball/src/base.config.js rename to scripts/beachball/base.config.js index 30e9ab201b5279..e3af0b964d46fc 100644 --- a/scripts/beachball/src/base.config.js +++ b/scripts/beachball/base.config.js @@ -1,6 +1,9 @@ /** @satisfies {import('beachball').BeachballConfig} */ const config = { access: 'public', + // Target branch WITHOUT remote, since people may have multiple remotes and choose different naming schemes. + // Specifying this helps beachball more quickly determine the target branch + remote at runtime. + branch: 'master', commit: false, disallowedChangeTypes: ['major'], tag: 'latest', diff --git a/scripts/beachball/src/shared.config.ts b/scripts/beachball/src/shared.config.ts index b7e3bf12cd9342..b0038d3755fd32 100644 --- a/scripts/beachball/src/shared.config.ts +++ b/scripts/beachball/src/shared.config.ts @@ -3,7 +3,7 @@ import { execSync } from 'child_process'; import type { BeachballConfig } from 'beachball'; import { renderEntry, renderHeader } from './customRenderers'; -import baseConfig from './base.config'; +import baseConfig from '../base.config'; /** * Shared Beachball release config.