Compare commits

..
15 Commits
Author SHA1 Message Date
Mateusz Burzyński b4392ca0f8 add explicit files 2026-05-24 14:12:27 +02:00
Mateusz Burzyński f50762a5f9 no template 2026-05-24 13:54:59 +02:00
Mateusz Burzyński 962764bc54 try no compact 2026-05-24 13:51:53 +02:00
Mateusz Burzyński 79a0643eb4 tweak 2026-05-24 13:51:21 +02:00
Mateusz Burzyński 4f914b551a tweak CODEOWNERS and remove release-pr workflow 2026-05-24 12:47:55 +02:00
Mateusz Burzyński cf4be527b8 add pkg.pr.new 2026-05-24 12:45:51 +02:00
Bjorn Lu f1222b6286 Refactor to fs-fixture (#622) 2026-05-18 10:03:43 +00:00
Mateusz Burzyński 87481d361e Add shellEmulator to pnpm-workspace.yaml (#624) 2026-05-16 15:41:11 +00:00
Bjorn Lu e33c0e699d Update vscode settings (#623)
* Update vscode settings

* Update launch.json
2026-05-15 19:04:24 +00:00
Bjorn LuandMateusz Burzyński c13a48983a Use rolldown for bundling (#621)
* Use rolldown for bundling

* update vite

---------

Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
2026-05-15 19:01:37 +00:00
Bjorn Lu 6c80731937 Migrate to oxfmt (#618)
* Migrate to oxfmt

* Enable import sorting

* trailingComma always
2026-05-15 11:48:55 +00:00
Mateusz Burzyński 03ba888eb8 Add zizmor workflow (#617)
* Add `zizmor` workflow

* fix issues

* fix one thing

* add permission comments

* add job names

* move zizmor to CI
2026-05-15 10:16:37 +00:00
Bjorn Lu aec1f01000 Update vitest to v4 (#619) 2026-05-15 08:53:32 +00:00
Marco PasqualettiandMateusz Burzyński 04ba326779 migrate to pnpm (#609)
* migrate to `pnpm`

* rename `simple-project` fixture packages to remove socket security errors

* add pnpm `dedupe` options

* update release-pr workflow

* update

* update snashots

* tweaks

* tweak

* tweak

* fix missing ci-setup

* tweak

* tweak deps

* update pnpm

* ok, Socket, let's rename them

* update snapshots

* rename again

* fmt

---------

Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
2026-05-14 09:04:38 +00:00
Mateusz Burzyński ccba80bb5a Fix the ability to create GitHub releases in our own workflow (#614) 2026-05-07 10:05:44 +00:00
38 changed files with 3073 additions and 3633 deletions
+4 -5
View File
@@ -1,5 +1,4 @@
/.github/workflows/** @Andarist @emmatown /.github/workflows/** @Andarist @bluwy @emmatown
/action.yml @Andarist @emmatown /action.yml @Andarist @bluwy @emmatown
/scripts/bump.ts @Andarist @emmatown /scripts/bump.ts @Andarist @bluwy @emmatown
/scripts/release.ts @Andarist @emmatown /scripts/release.ts @Andarist @bluwy @emmatown
/scripts/release-pr.ts @Andarist @emmatown
+14 -4
View File
@@ -1,14 +1,24 @@
name: Setup CI name: Setup CI
description: Setup CI
inputs:
skip-cache:
description: "Whether to skip the cache"
required: false
default: "false"
runs: runs:
using: composite using: composite
steps: steps:
- name: Setup Node.js - name: Set up pnpm
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 uses: pnpm/action-setup@8912a9102ac27614460f54aedde9e1e7f9aec20d # v6.0.5
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with: with:
node-version-file: ".node-version" node-version-file: ".node-version"
cache: yarn package-manager-cache: ${{ inputs.skip-cache != 'true' }}
cache: ${{ inputs.skip-cache != 'true' && 'pnpm' || '' }}
- name: Install dependencies - name: Install dependencies
shell: bash shell: bash
run: yarn install --frozen-lockfile run: pnpm install --frozen-lockfile
+2
View File
@@ -9,3 +9,5 @@ updates:
directory: "/" # Location of package manifests directory: "/" # Location of package manifests
schedule: schedule:
interval: "weekly" interval: "weekly"
cooldown:
default-days: 7
+41 -9
View File
@@ -2,26 +2,54 @@ name: CI
on: on:
pull_request: pull_request:
push: # merge queue is required so all commits on target branches trigger this workflow
branches: [main] # despite lack of the push event trigger here
merge_group: merge_group:
branches: [main] branches:
- main
permissions: permissions:
contents: read contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.sha }}
cancel-in-progress: true
jobs: jobs:
lint-workflows:
name: Lint workflows
runs-on: ubuntu-latest
permissions:
actions: read # only required in private repos
security-events: write # allow writing security events
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Run zizmor
uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3
with:
persona: pedantic
annotations: true
advanced-security: false
test: test:
name: Test name: Test
timeout-minutes: 20 timeout-minutes: 20
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check out repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: ./.github/actions/ci-setup - uses: ./.github/actions/ci-setup
- name: Test - name: Test
run: yarn test run: pnpm test
typecheck: typecheck:
name: Typecheck name: Typecheck
@@ -29,18 +57,22 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check out repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: ./.github/actions/ci-setup - uses: ./.github/actions/ci-setup
- name: Typecheck - name: Typecheck
run: yarn typecheck run: pnpm typecheck
ci-ok: ci-ok:
name: CI OK name: CI OK
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: always() if: always()
needs: [test, typecheck] needs: [lint-workflows, test, typecheck]
steps: steps:
- name: Exit with error if some jobs are not successful - name: Exit with error if some jobs are not successful
run: exit 1 run: exit 1
if: ${{ always() && (contains(needs.*.result, 'failure') || contains(needs.*.result, 'skipped') || contains(needs.*.result, 'cancelled')) }} if: ${{ always() && (contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) }}
+31
View File
@@ -0,0 +1,31 @@
name: pkg-pr-new
on: pull_request
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
publish:
name: Publish
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: ./.github/actions/ci-setup
with:
skip-cache: true # avoid cache poisoning attacks
- name: Build
run: pnpm build
- run:
| # zizmor: ignore[use-trusted-publishing] we're not publishing to npm here
pnpm exec pkg-pr-new publish --pnpm --packageManager=pnpm --commentWithDev --commentWithSha --no-compact --no-template
+23 -7
View File
@@ -5,7 +5,10 @@ on:
branches: branches:
- main - main
concurrency: ${{ github.workflow }}-${{ github.ref }} concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
queue: max
permissions: {} # each job should define its own permission explicitly permissions: {} # each job should define its own permission explicitly
@@ -21,17 +24,23 @@ jobs:
issues: write # to post issue comments (changesets/action) issues: write # to post issue comments (changesets/action)
pull-requests: write # to create pull request (changesets/action) pull-requests: write # to create pull request (changesets/action)
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check out repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: ./.github/actions/ci-setup - uses: ./.github/actions/ci-setup
with:
skip-cache: true # avoid cache poisoning attacks
- name: Build - name: Build
run: yarn build run: pnpm build
- name: Create or update release pull request - name: Create or update release pull request
id: changesets id: changesets
uses: ./ uses: ./
with: with:
version: yarn bump version: pnpm bump
publish: publish:
name: Publish name: Publish
@@ -40,6 +49,8 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
environment: marketplace environment: marketplace
timeout-minutes: 20 timeout-minutes: 20
permissions:
contents: write # to create release and have it authored by github-actions (changesets/action)
steps: steps:
- uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1 - uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
id: app-token id: app-token
@@ -47,16 +58,21 @@ jobs:
client-id: ${{ vars.APP_CLIENT_ID }} client-id: ${{ vars.APP_CLIENT_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }} private-key: ${{ secrets.APP_PRIVATE_KEY }}
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check out repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: true
# we need this token to bypass the branch and tag protection rules
token: ${{ steps.app-token.outputs.token }} token: ${{ steps.app-token.outputs.token }}
- uses: ./.github/actions/ci-setup - uses: ./.github/actions/ci-setup
with:
skip-cache: true # avoid cache poisoning attacks
- name: Build - name: Build
run: yarn build run: pnpm build
- name: Publish to marketplace - name: Publish to marketplace
uses: ./ uses: ./
with: with:
publish: yarn release publish: pnpm release
-183
View File
@@ -1,183 +0,0 @@
name: Release PR
on:
issue_comment:
types: [created]
permissions: {}
jobs:
release_check:
if: github.repository == 'changesets/action' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/release-pr')
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
pull-requests: read
steps:
- id: report_in_progress
run: |
echo "in_progress_reaction_id=$(gh api /repos/${{github.repository}}/issues/comments/${{github.event.comment.id}}/reactions -f content='eyes' --jq '.id')" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- id: parse_command
run: |
if [[ "$COMMENT_BODY" =~ ^/release-pr[[:space:]]+([0-9a-fA-F]{7,40})[[:space:]]*$ ]]
then
echo "requested_sha=${BASH_REMATCH[1]}" >> "$GITHUB_OUTPUT"
else
echo "Expected '/release-pr <sha>' where <sha> is a 7-40 character commit SHA."
exit 1
fi
env:
COMMENT_BODY: ${{ github.event.comment.body }}
- id: check_authorization
run: |
if [[ $AUTHOR_ASSOCIATION == 'MEMBER' || $AUTHOR_ASSOCIATION == 'OWNER' || $AUTHOR_ASSOCIATION == 'COLLABORATOR' ]]
then
echo "User is authorized to release"
else
echo "User is not authorized to release"
exit 1
fi
env:
AUTHOR_ASSOCIATION: ${{ github.event.comment.author_association }}
- id: resolve_requested_sha
run: |
requested_sha=$(echo "$REQUESTED_SHA" | tr '[:upper:]' '[:lower:]')
mapfile -t matches < <(
gh api /repos/${{ github.repository }}/pulls/${{ github.event.issue.number }}/commits --paginate --jq '.[].sha' |
awk -v sha="$requested_sha" 'index(tolower($0), sha) == 1 { print $0 }'
)
if [[ ${#matches[@]} -eq 0 ]]
then
echo "Requested SHA $REQUESTED_SHA is not part of this pull request."
exit 1
fi
if [[ ${#matches[@]} -gt 1 ]]
then
echo "Requested SHA $REQUESTED_SHA is ambiguous for this pull request."
exit 1
fi
resolved_sha="${matches[0]}"
pr_head_sha=$(gh pr view ${{ github.event.issue.number }} --json headRefOid --jq '.headRefOid')
if [[ "$resolved_sha" != "$pr_head_sha" ]]
then
echo "Requested SHA $resolved_sha is not the current PR head $pr_head_sha."
exit 1
fi
echo "resolved_sha=$resolved_sha" >> "$GITHUB_OUTPUT"
echo "pr_head_sha=$pr_head_sha" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REQUESTED_SHA: ${{ steps.parse_command.outputs.requested_sha }}
- id: get_pr_head_repository
run: |
echo "head_repository=$(gh pr view ${{ github.event.issue.number }} --json headRepositoryOwner,headRepository --jq '.headRepositoryOwner.login + "/" + .headRepository.name')" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
outputs:
in_progress_reaction_id: ${{ steps.report_in_progress.outputs.in_progress_reaction_id }}
requested_sha: ${{ steps.parse_command.outputs.requested_sha }}
resolved_sha: ${{ steps.resolve_requested_sha.outputs.resolved_sha }}
pr_head_sha: ${{ steps.resolve_requested_sha.outputs.pr_head_sha }}
head_repository: ${{ steps.get_pr_head_repository.outputs.head_repository }}
release:
if: github.repository == 'changesets/action'
timeout-minutes: 20
runs-on: ubuntu-latest
needs: release_check
permissions:
contents: write
issues: write
pull-requests: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/actions/ci-setup
- name: Fetch validated commit from pull request head repository
run: |
git remote add pr-head https://github.com/$HEAD_REPOSITORY.git
git fetch --no-tags pr-head $RESOLVED_SHA
env:
HEAD_REPOSITORY: ${{ needs.release_check.outputs.head_repository }}
RESOLVED_SHA: ${{ needs.release_check.outputs.resolved_sha }}
- name: Checkout validated commit
run: git checkout --detach $RESOLVED_SHA
env:
RESOLVED_SHA: ${{ needs.release_check.outputs.resolved_sha }}
- name: Check if Version Packages PR
id: check_version_packages
run: |
echo "version_packages=$(gh pr view ${{ github.event.issue.number }} --json headRefName --jq '.headRefName|startswith("changeset-release/")')" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Reset Version Packages PR
if: steps.check_version_packages.outputs.version_packages == 'true'
run: git reset --hard HEAD~1
- run: yarn changeset version --snapshot pr${{ github.event.issue.number }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build
run: yarn build
- name: Setup Git user
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
- name: Release snapshot version
run: yarn run release:pr
- run: gh api /repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions -f content='rocket'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: gh api -X DELETE /repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions/${{ needs.release_check.outputs.in_progress_reaction_id }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
gh pr comment ${{ github.event.issue.number }} --body "The release for \`${{ needs.release_check.outputs.resolved_sha }}\` triggered by [this comment](${{ github.event.comment.url }}) has [succeeded](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}). Published commit: [${{ github.repository }}@$(git rev-parse HEAD)](https://github.com/${{ github.repository }}/commit/$(git rev-parse HEAD))."
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
report-failure-if-needed:
needs: [release_check, release]
timeout-minutes: 2
runs-on: ubuntu-latest
if: failure() && github.repository == 'changesets/action' && (needs.release_check.result == 'failure' || needs.release.result == 'failure')
permissions:
issues: write
pull-requests: write
steps:
- run: gh api /repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions -f content='-1'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: gh api -X DELETE /repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions/${{ needs.release_check.outputs.in_progress_reaction_id }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
gh pr comment ${{ github.event.issue.number }} --body "The release for \`${{ needs.release_check.outputs.requested_sha }}\` triggered by [this comment](${{ github.event.comment.url }}) has [failed](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})."
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
+7
View File
@@ -0,0 +1,7 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"printWidth": 80,
"sortImports": {
"newlinesBetween": false
}
}
+1 -1
View File
@@ -1,5 +1,4 @@
{ {
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
@@ -7,6 +6,7 @@
"request": "launch", "request": "launch",
"name": "Debug Current Test File", "name": "Debug Current Test File",
"autoAttachChildProcesses": true, "autoAttachChildProcesses": true,
"skipFiles": [],
"program": "${workspaceRoot}/node_modules/vitest/vitest.mjs", "program": "${workspaceRoot}/node_modules/vitest/vitest.mjs",
"args": ["run", "${relativeFile}"], "args": ["run", "${relativeFile}"],
"smartStep": true, "smartStep": true,
+2 -1
View File
@@ -1,3 +1,4 @@
{ {
"typescript.tsdk": "node_modules/typescript/lib" "js/ts.tsdk.path": "node_modules/typescript/lib",
"editor.defaultFormatter": "oxc.oxc-vscode"
} }
+38 -26
View File
@@ -21,7 +21,7 @@ This action for [Changesets](https://github.com/changesets/changesets) creates a
- published - A boolean value to indicate whether a publishing has happened or not - published - A boolean value to indicate whether a publishing has happened or not
- publishedPackages - A JSON array to present the published packages. The format is `[{"name": "@xx/xx", "version": "1.2.0"}, {"name": "@xx/xy", "version": "0.8.9"}]` - publishedPackages - A JSON array to present the published packages. The format is `[{"name": "@xx/xx", "version": "1.2.0"}, {"name": "@xx/xy", "version": "0.8.9"}]`
### Example workflow: ### Example workflow
#### Without Publishing #### Without Publishing
@@ -43,15 +43,18 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repo - name: Checkout Repo
uses: actions/checkout@v3 uses: actions/checkout@v6
- name: Setup Node.js 20 - name: Setup pnpm
uses: actions/setup-node@v3 uses: pnpm/action-setup@v6
- name: Setup Node.js 26
uses: actions/setup-node@v6
with: with:
node-version: 20 node-version: 26
- name: Install Dependencies - name: Install Dependencies
run: yarn run: pnpm install --frozen-lockfile
- name: Create Release Pull Request - name: Create Release Pull Request
uses: changesets/action@v1 uses: changesets/action@v1
@@ -77,22 +80,25 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repo - name: Checkout Repo
uses: actions/checkout@v3 uses: actions/checkout@v6
- name: Setup Node.js 20.x - name: Setup pnpm
uses: actions/setup-node@v3 uses: pnpm/action-setup@v6
- name: Setup Node.js 26
uses: actions/setup-node@v6
with: with:
node-version: 20.x node-version: 26
- name: Install Dependencies - name: Install Dependencies
run: yarn run: pnpm install --frozen-lockfile
- name: Create Release Pull Request or Publish to npm - name: Create Release Pull Request or Publish to npm
id: changesets id: changesets
uses: changesets/action@v1 uses: changesets/action@v1
with: with:
# This expects you to have a script called release which does a build for your packages and calls changeset publish # This expects you to have a script called release which does a build for your packages and calls changeset publish
publish: yarn release publish: pnpm release
env: env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -104,7 +110,7 @@ jobs:
By default the GitHub Action creates a `.npmrc` file with the following content: By default the GitHub Action creates a `.npmrc` file with the following content:
``` ```txt
//registry.npmjs.org/:_authToken=${process.env.NPM_TOKEN} //registry.npmjs.org/:_authToken=${process.env.NPM_TOKEN}
``` ```
@@ -141,15 +147,18 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repo - name: Checkout Repo
uses: actions/checkout@v3 uses: actions/checkout@v6
- name: Setup Node.js 20.x - name: Setup pnpm
uses: actions/setup-node@v3 uses: pnpm/action-setup@v6
- name: Setup Node.js 26
uses: actions/setup-node@v6
with: with:
node-version: 20.x node-version: 26
- name: Install Dependencies - name: Install Dependencies
run: yarn run: pnpm install --frozen-lockfile
- name: Create Release Pull Request or Publish to npm - name: Create Release Pull Request or Publish to npm
id: changesets id: changesets
@@ -158,7 +167,7 @@ jobs:
- name: Publish - name: Publish
if: steps.changesets.outputs.hasChangesets == 'false' if: steps.changesets.outputs.hasChangesets == 'false'
# You can do something when a publish should happen. # You can do something when a publish should happen.
run: yarn publish run: pnpm publish
``` ```
#### With version script #### With version script
@@ -183,21 +192,24 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repo - name: Checkout Repo
uses: actions/checkout@v3 uses: actions/checkout@v6
- name: Setup Node.js 20.x - name: Setup pnpm
uses: actions/setup-node@v3 uses: pnpm/action-setup@v6
- name: Setup Node.js 26
uses: actions/setup-node@v6
with: with:
node-version: 20.x node-version: 26
- name: Install Dependencies - name: Install Dependencies
run: yarn run: pnpm install --frozen-lockfile
- name: Create Release Pull Request - name: Create Release Pull Request
uses: changesets/action@v1 uses: changesets/action@v1
with: with:
# this expects you to have a npm script called version that runs some logic and then calls `changeset version`. # this expects you to have a npm script called version that runs some logic and then calls `changeset version`.
version: yarn version version: pnpm version
``` ```
#### With Yarn 2 / Plug'n'Play #### With Yarn 2 / Plug'n'Play
@@ -208,5 +220,5 @@ If you are using [Yarn Plug'n'Play](https://yarnpkg.com/features/pnp), you shoul
- uses: changesets/action@v1 - uses: changesets/action@v1
with: with:
version: yarn changeset version version: yarn changeset version
... # ...
``` ```
@@ -1,4 +0,0 @@
{
"$schema": "https://unpkg.com/@changesets/config@1.3.0/schema.json",
"ignore": ["ignored-package-pkg-a"]
}
@@ -1,8 +0,0 @@
{
"private": true,
"name": "ignored-package",
"version": "1.0.0",
"workspaces": [
"packages/*"
]
}
@@ -1,7 +0,0 @@
{
"name": "ignored-package-pkg-a",
"version": "1.0.0",
"dependencies": {
"ignored-package-pkg-b": "1.0.0"
}
}
@@ -1,4 +0,0 @@
{
"name": "ignored-package-pkg-b",
"version": "1.0.0"
}
@@ -1,3 +0,0 @@
{
"$schema": "https://unpkg.com/@changesets/config@1.3.0/schema.json"
}
-8
View File
@@ -1,8 +0,0 @@
{
"private": true,
"name": "simple-project",
"version": "1.0.0",
"workspaces": [
"packages/*"
]
}
@@ -1,7 +0,0 @@
{
"name": "simple-project-pkg-a",
"version": "1.0.0",
"dependencies": {
"simple-project-pkg-b": "1.0.0"
}
}
@@ -1,4 +0,0 @@
{
"name": "simple-project-pkg-b",
"version": "1.0.0"
}
-61
View File
File diff suppressed because one or more lines are too long
+32 -40
View File
@@ -1,51 +1,34 @@
{ {
"name": "@changesets/action", "name": "@changesets/action",
"version": "1.8.0", "version": "1.8.0",
"main": "dist/index.js",
"type": "module",
"license": "MIT", "license": "MIT",
"devDependencies": { "type": "module",
"@changesets/changelog-github": "^0.5.1", "exports": "./dist/index.js",
"@changesets/cli": "^2.29.3", "files": [
"@changesets/write": "^0.4.0", "dist",
"@rollup/plugin-commonjs": "^28.0.3", "action.yml"
"@rollup/plugin-json": "^6.1.0", ],
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-terser": "^0.4.4",
"@types/node": "^22.15.17",
"@types/semver": "^7.5.0",
"builtin-modules": "^5.0.0",
"esbuild": "^0.25.4",
"fixturez": "^1.1.0",
"husky": "^3.0.3",
"prettier": "^2.0.5",
"rollup": "^4.40.2",
"typescript": "^5.8.3",
"vitest": "^3.1.3"
},
"scripts": { "scripts": {
"build": "rollup -c", "build": "rolldown -c",
"test": "vitest", "test": "vitest",
"test:watch": "yarn test --watch", "test:watch": "pnpm test --watch",
"typecheck": "tsc", "typecheck": "tsc",
"format": "oxfmt --check",
"format:fix": "oxfmt",
"changeset": "changeset", "changeset": "changeset",
"bump": "node --experimental-strip-types ./scripts/bump.ts", "bump": "node --experimental-strip-types ./scripts/bump.ts",
"release": "node --experimental-strip-types ./scripts/release.ts", "release": "node --experimental-strip-types ./scripts/release.ts"
"release:pr": "node --experimental-strip-types ./scripts/release-pr.ts"
},
"engines": {
"node": ">= 24"
}, },
"dependencies": { "dependencies": {
"@actions/core": "^1.11.1", "@actions/core": "^3.0.1",
"@actions/exec": "^1.1.1", "@actions/exec": "^3.0.0",
"@actions/github": "^6.0.1", "@actions/github": "^9.1.1",
"@changesets/ghcommit": "^2.0.1", "@changesets/ghcommit": "^2.0.1",
"@changesets/pre": "^2.0.2", "@changesets/pre": "^2.0.2",
"@changesets/read": "^0.6.5", "@changesets/read": "^0.6.5",
"@manypkg/get-packages": "^1.1.3", "@manypkg/get-packages": "^1.1.3",
"@octokit/core": "^5.2.1", "@octokit/core": "^7.0.6",
"@octokit/plugin-throttling": "^8.0.0", "@octokit/plugin-throttling": "^11.0.3",
"@types/mdast": "^3.0.0", "@types/mdast": "^3.0.0",
"mdast-util-to-string": "^1.0.6", "mdast-util-to-string": "^1.0.6",
"remark-parse": "^7.0.1", "remark-parse": "^7.0.1",
@@ -53,13 +36,22 @@
"semver": "^7.5.3", "semver": "^7.5.3",
"unified": "^8.3.2" "unified": "^8.3.2"
}, },
"husky": { "devDependencies": {
"hooks": {} "@changesets/changelog-github": "^0.5.1",
"@changesets/cli": "^2.29.3",
"@changesets/types": "^6.1.0",
"@changesets/write": "^0.4.0",
"@types/node": "^24.12.2",
"@types/semver": "^7.5.0",
"fs-fixture": "^2.13.0",
"oxfmt": "^0.48.0",
"pkg-pr-new": "^0.0.71",
"rolldown": "^1.0.1",
"typescript": "^5.8.3",
"vitest": "^4.1.6"
}, },
"prettier": {}, "engines": {
"resolutions": { "node": ">=24"
"trim": "^0.0.3",
"y18n": "^4.0.1"
}, },
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" "packageManager": "pnpm@11.1.1+sha512.d1fdf5f73c617b64fa1a56a81c3c8dfe0e966e33a6010aa256b517ae77be21d93e05affc0de1a83b0e4f29d569f68b446ae8f068cd7247c0bb3df0fb4d7bdf9a"
} }
+2697
View File
File diff suppressed because it is too large Load Diff
+17
View File
@@ -0,0 +1,17 @@
blockExoticSubdeps: true
dedupePeers: true
dedupePeerDependents: true
minimumReleaseAge: 10080
minimumReleaseAgeExclude:
- '@oxc-project/*'
- '@rolldown/*'
- rolldown@1.0.1
- vite@8.0.13
- vitest@4.1.6
overrides:
lightningcss: '-' # we do not bundle any css
postcss: '-' # we do not bundle any css
shellEmulator: true
trustPolicy: no-downgrade
+13
View File
@@ -0,0 +1,13 @@
import { defineConfig } from 'rolldown'
export default defineConfig({
input: 'src/index.ts',
output: {
dir: 'dist',
format: 'esm',
cleanDir: true,
minify: true,
comments: false,
},
platform: 'node',
})
-38
View File
@@ -1,38 +0,0 @@
import { defineConfig } from "rollup";
import commonjs from "@rollup/plugin-commonjs";
import nodeResolve from "@rollup/plugin-node-resolve";
import terser from "@rollup/plugin-terser";
import json from "@rollup/plugin-json";
import { transform } from "esbuild";
import builtinModulesList from "builtin-modules";
const builtinModules = new Set(builtinModulesList);
export default defineConfig({
input: "src/index.ts",
output: {
dir: "dist",
format: "esm",
},
external: (id) => builtinModules.has(id),
plugins: [
nodeResolve({
preferBuiltins: false,
}),
json(),
commonjs(),
{
name: "esbuild",
async transform(code, id) {
if (!/\.(mts|cts|ts|tsx)$/.test(id)) {
return null;
}
const result = await transform(code, {
loader: "ts",
});
return result.code;
},
},
terser(),
],
});
+2 -2
View File
@@ -1,6 +1,6 @@
import { exec } from "@actions/exec";
import fs from "node:fs"; import fs from "node:fs";
import path from "node:path"; import path from "node:path";
import { exec } from "@actions/exec";
import pkgJson from "../package.json" with { type: "json" }; import pkgJson from "../package.json" with { type: "json" };
process.chdir(path.join(import.meta.dirname, "..")); process.chdir(path.join(import.meta.dirname, ".."));
@@ -13,6 +13,6 @@ const readmePath = path.join(import.meta.dirname, "..", "README.md");
const content = fs.readFileSync(readmePath, "utf8"); const content = fs.readFileSync(readmePath, "utf8");
const updatedContent = content.replace( const updatedContent = content.replace(
/changesets\/action@[^\s]+/g, /changesets\/action@[^\s]+/g,
`changesets/action@${releaseLine}` `changesets/action@${releaseLine}`,
); );
fs.writeFileSync(readmePath, updatedContent); fs.writeFileSync(readmePath, updatedContent);
-20
View File
@@ -1,20 +0,0 @@
import { exec } from "@actions/exec";
import path from "node:path";
import pkgJson from "../package.json" with { type: "json" };
const tag = `v${pkgJson.version}`;
const releaseLine = "pr-release";
process.chdir(path.join(import.meta.dirname, ".."));
await exec("git", ["checkout", "--detach"]);
await exec("git", ["add", "--force", "dist"]);
await exec("git", ["commit", "-m", tag]);
await exec("git", [
"push",
"--force",
"origin",
`HEAD:refs/heads/${releaseLine}`,
]);
+3 -4
View File
@@ -1,6 +1,5 @@
import { exec, getExecOutput } from "@actions/exec";
import path from "node:path"; import path from "node:path";
import { exec, getExecOutput } from "@actions/exec";
import pkgJson from "../package.json" with { type: "json" }; import pkgJson from "../package.json" with { type: "json" };
const tag = `v${pkgJson.version}`; const tag = `v${pkgJson.version}`;
@@ -14,11 +13,11 @@ process.chdir(path.join(import.meta.dirname, ".."));
["ls-remote", "--exit-code", "origin", "--tags", `refs/tags/${tag}`], ["ls-remote", "--exit-code", "origin", "--tags", `refs/tags/${tag}`],
{ {
ignoreReturnCode: true, ignoreReturnCode: true,
} },
); );
if (exitCode === 0) { if (exitCode === 0) {
console.log( console.log(
`Action is not being published because version ${tag} is already published` `Action is not being published because version ${tag} is already published`,
); );
return; return;
} }
+9 -9
View File
@@ -8,7 +8,7 @@ exports[`version > creates a draft PR when prDraft is "create" 1`] = `
# Releases # Releases
## simple-project-pkg-a@1.1.0 ## changesets-dev-simple-project-pkg-a@1.1.0
### Minor Changes ### Minor Changes
@@ -31,7 +31,7 @@ exports[`version > creates simple PR 1`] = `
# Releases # Releases
## simple-project-pkg-a@1.1.0 ## changesets-dev-simple-project-pkg-a@1.1.0
### Minor Changes ### Minor Changes
@@ -40,9 +40,9 @@ exports[`version > creates simple PR 1`] = `
### Patch Changes ### Patch Changes
- Updated dependencies - Updated dependencies
- simple-project-pkg-b@1.1.0 - changesets-dev-simple-project-pkg-b@1.1.0
## simple-project-pkg-b@1.1.0 ## changesets-dev-simple-project-pkg-b@1.1.0
### Minor Changes ### Minor Changes
@@ -87,7 +87,7 @@ exports[`version > does not include changelog entries if full message exceeds si
> The changelog information of each package has been omitted from this message, as the content exceeds the size limit. > The changelog information of each package has been omitted from this message, as the content exceeds the size limit.
## simple-project-pkg-a@1.1.0 ## changesets-dev-simple-project-pkg-a@1.1.0
", ",
"draft": false, "draft": false,
@@ -107,7 +107,7 @@ exports[`version > doesn't include ignored package that got a dependency update
# Releases # Releases
## ignored-package-pkg-b@1.1.0 ## changesets-dev-ignored-package-pkg-b@1.1.0
### Minor Changes ### Minor Changes
@@ -130,7 +130,7 @@ exports[`version > only includes bumped packages in the PR body 1`] = `
# Releases # Releases
## simple-project-pkg-a@1.1.0 ## changesets-dev-simple-project-pkg-a@1.1.0
### Minor Changes ### Minor Changes
@@ -183,7 +183,7 @@ exports[`version > updates an existing PR via GraphQL and converts it to draft w
# Releases # Releases
## simple-project-pkg-a@1.1.0 ## changesets-dev-simple-project-pkg-a@1.1.0
### Minor Changes ### Minor Changes
@@ -224,7 +224,7 @@ exports[`version > updates an existing PR via GraphQL without converting it to d
# Releases # Releases
## simple-project-pkg-a@1.1.0 ## changesets-dev-simple-project-pkg-a@1.1.0
### Minor Changes ### Minor Changes
+3 -3
View File
@@ -14,7 +14,7 @@ const push = async (branch: string, options: GitOptions) => {
const switchToMaybeExistingBranch = async ( const switchToMaybeExistingBranch = async (
branch: string, branch: string,
options: GitOptions options: GitOptions,
) => { ) => {
let { stderr } = await getExecOutput("git", ["checkout", branch], { let { stderr } = await getExecOutput("git", ["checkout", branch], {
ignoreReturnCode: true, ignoreReturnCode: true,
@@ -41,7 +41,7 @@ const checkIfClean = async (options: GitOptions): Promise<boolean> => {
const { stdout } = await getExecOutput( const { stdout } = await getExecOutput(
"git", "git",
["status", "--porcelain"], ["status", "--porcelain"],
options options,
); );
return !stdout.length; return !stdout.length;
}; };
@@ -71,7 +71,7 @@ export class Git {
], ],
{ {
cwd: this.cwd, cwd: this.cwd,
} },
); );
} }
+13 -13
View File
@@ -1,6 +1,6 @@
import * as core from "@actions/core";
import fs from "node:fs/promises"; import fs from "node:fs/promises";
import path from "node:path"; import path from "node:path";
import * as core from "@actions/core";
import { Git } from "./git.ts"; import { Git } from "./git.ts";
import { setupOctokit } from "./octokit.ts"; import { setupOctokit } from "./octokit.ts";
import readChangesetState from "./readChangesetState.ts"; import readChangesetState from "./readChangesetState.ts";
@@ -48,7 +48,7 @@ const getOptionalInput = (name: string) => core.getInput(name) || undefined;
core.info("setting GitHub credentials"); core.info("setting GitHub credentials");
await fs.writeFile( await fs.writeFile(
`${process.env.HOME}/.netrc`, `${process.env.HOME}/.netrc`,
`machine github.com\nlogin github-actions[bot]\npassword ${githubToken}` `machine github.com\nlogin github-actions[bot]\npassword ${githubToken}`,
); );
let { changesets } = await readChangesetState(cwd); let { changesets } = await readChangesetState(cwd);
@@ -56,7 +56,7 @@ const getOptionalInput = (name: string) => core.getInput(name) || undefined;
let publishScript = core.getInput("publish"); let publishScript = core.getInput("publish");
let hasChangesets = changesets.length !== 0; let hasChangesets = changesets.length !== 0;
const hasNonEmptyChangesets = changesets.some( const hasNonEmptyChangesets = changesets.some(
(changeset) => changeset.releases.length > 0 (changeset) => changeset.releases.length > 0,
); );
let hasPublishScript = !!publishScript; let hasPublishScript = !!publishScript;
@@ -67,12 +67,12 @@ const getOptionalInput = (name: string) => core.getInput(name) || undefined;
switch (true) { switch (true) {
case !hasChangesets && !hasPublishScript: case !hasChangesets && !hasPublishScript:
core.info( core.info(
"No changesets present or were removed by merging release PR. Not publishing because no publish script found." "No changesets present or were removed by merging release PR. Not publishing because no publish script found.",
); );
return; return;
case !hasChangesets && hasPublishScript: { case !hasChangesets && hasPublishScript: {
core.info( core.info(
"No changesets found. Attempting to publish any unpublished packages to npm" "No changesets found. Attempting to publish any unpublished packages to npm",
); );
if (process.env.NPM_TOKEN) { if (process.env.NPM_TOKEN) {
@@ -87,24 +87,24 @@ const getOptionalInput = (name: string) => core.getInput(name) || undefined;
}); });
if (authLine) { if (authLine) {
core.info( core.info(
"Found existing auth token for the npm registry in the user .npmrc file" "Found existing auth token for the npm registry in the user .npmrc file",
); );
} else { } else {
core.info( core.info(
"Didn't find existing auth token for the npm registry in the user .npmrc file, creating one" "Didn't find existing auth token for the npm registry in the user .npmrc file, creating one",
); );
await fs.appendFile( await fs.appendFile(
userNpmrcPath, userNpmrcPath,
`\n//registry.npmjs.org/:_authToken=${process.env.NPM_TOKEN}\n` `\n//registry.npmjs.org/:_authToken=${process.env.NPM_TOKEN}\n`,
); );
} }
} else { } else {
core.info( core.info(
"No user .npmrc file found, creating one with NPM_TOKEN used as auth token" "No user .npmrc file found, creating one with NPM_TOKEN used as auth token",
); );
await fs.writeFile( await fs.writeFile(
userNpmrcPath, userNpmrcPath,
`//registry.npmjs.org/:_authToken=${process.env.NPM_TOKEN}\n` `//registry.npmjs.org/:_authToken=${process.env.NPM_TOKEN}\n`,
); );
} }
} else if ( } else if (
@@ -112,11 +112,11 @@ const getOptionalInput = (name: string) => core.getInput(name) || undefined;
process.env.ACTIONS_ID_TOKEN_REQUEST_URL process.env.ACTIONS_ID_TOKEN_REQUEST_URL
) { ) {
core.info( core.info(
"No NPM_TOKEN found, but OIDC is available - using npm trusted publishing" "No NPM_TOKEN found, but OIDC is available - using npm trusted publishing",
); );
} else { } else {
core.info( core.info(
"No NPM_TOKEN or OIDC available - assuming npm is already authenticated" "No NPM_TOKEN or OIDC available - assuming npm is already authenticated",
); );
} }
@@ -133,7 +133,7 @@ const getOptionalInput = (name: string) => core.getInput(name) || undefined;
core.setOutput("published", "true"); core.setOutput("published", "true");
core.setOutput( core.setOutput(
"publishedPackages", "publishedPackages",
JSON.stringify(result.publishedPackages) JSON.stringify(result.publishedPackages),
); );
} }
return; return;
+4 -4
View File
@@ -9,7 +9,7 @@ export const setupOctokit = (githubToken: string) => {
throttle: { throttle: {
onRateLimit: (retryAfter, options: any, octokit, retryCount) => { onRateLimit: (retryAfter, options: any, octokit, retryCount) => {
core.warning( core.warning(
`Request quota exhausted for request ${options.method} ${options.url}` `Request quota exhausted for request ${options.method} ${options.url}`,
); );
if (retryCount <= 2) { if (retryCount <= 2) {
@@ -21,10 +21,10 @@ export const setupOctokit = (githubToken: string) => {
retryAfter, retryAfter,
options: any, options: any,
octokit, octokit,
retryCount retryCount,
) => { ) => {
core.warning( core.warning(
`SecondaryRateLimit detected for request ${options.method} ${options.url}` `SecondaryRateLimit detected for request ${options.method} ${options.url}`,
); );
if (retryCount <= 2) { if (retryCount <= 2) {
@@ -34,7 +34,7 @@ export const setupOctokit = (githubToken: string) => {
}, },
}, },
}, },
throttling throttling,
); );
}; };
+2 -2
View File
@@ -1,6 +1,6 @@
import type { PreState, NewChangeset } from "@changesets/types";
import { readPreState } from "@changesets/pre"; import { readPreState } from "@changesets/pre";
import readChangesets from "@changesets/read"; import readChangesets from "@changesets/read";
import type { PreState, NewChangeset } from "@changesets/types";
export type ChangesetState = { export type ChangesetState = {
preState: PreState | undefined; preState: PreState | undefined;
@@ -8,7 +8,7 @@ export type ChangesetState = {
}; };
export default async function readChangesetState( export default async function readChangesetState(
cwd: string = process.cwd() cwd: string = process.cwd(),
): Promise<ChangesetState> { ): Promise<ChangesetState> {
let preState = await readPreState(cwd); let preState = await readPreState(cwd);
let changesets = await readChangesets(cwd); let changesets = await readChangesets(cwd);
+88 -45
View File
@@ -1,8 +1,7 @@
import path from "node:path";
import type { Changeset } from "@changesets/types"; import type { Changeset } from "@changesets/types";
import writeChangeset from "@changesets/write"; import writeChangeset from "@changesets/write";
import fixturez from "fixturez"; import { createFixture } from "fs-fixture";
import fs from "node:fs/promises";
import path from "node:path";
import { beforeEach, describe, expect, it, vi } from "vitest"; import { beforeEach, describe, expect, it, vi } from "vitest";
import { Git } from "./git.ts"; import { Git } from "./git.ts";
import { setupOctokit } from "./octokit.ts"; import { setupOctokit } from "./octokit.ts";
@@ -36,14 +35,58 @@ let mockedGithubMethods = {
}; };
let mockedGraphql = vi.fn(); let mockedGraphql = vi.fn();
let f = fixturez(import.meta.dirname); const nodeModulesDir = path.join(import.meta.dirname, "..", "node_modules");
function createSimpleProjectFixture() {
return createFixture({
node_modules: (api) => api.symlink(nodeModulesDir),
".changeset/config.json": JSON.stringify({}),
"packages/pkg-a/package.json": JSON.stringify({
name: "changesets-dev-simple-project-pkg-a",
version: "1.0.0",
dependencies: {
"changesets-dev-simple-project-pkg-b": "1.0.0",
},
}),
"packages/pkg-b/package.json": JSON.stringify({
name: "changesets-dev-simple-project-pkg-b",
version: "1.0.0",
}),
"package.json": JSON.stringify({
name: "simple-project",
version: "1.0.0",
private: true,
workspaces: ["packages/*"],
}),
});
}
function createIgnoredPackageFixture() {
return createFixture({
node_modules: (api) => api.symlink(nodeModulesDir),
".changeset/config.json": JSON.stringify({
ignore: ["changesets-dev-ignored-package-pkg-a"],
}),
"packages/pkg-a/package.json": JSON.stringify({
name: "changesets-dev-ignored-package-pkg-a",
version: "1.0.0",
dependencies: {
"changesets-dev-ignored-package-pkg-b": "1.0.0",
},
}),
"packages/pkg-b/package.json": JSON.stringify({
name: "changesets-dev-ignored-package-pkg-b",
version: "1.0.0",
}),
"package.json": JSON.stringify({
name: "ignored-package",
version: "1.0.0",
private: true,
workspaces: ["packages/*"],
}),
});
}
const linkNodeModules = async (cwd: string) => {
await fs.symlink(
path.join(import.meta.dirname, "..", "node_modules"),
path.join(cwd, "node_modules")
);
};
const writeChangesets = (changesets: Changeset[], cwd: string) => { const writeChangesets = (changesets: Changeset[], cwd: string) => {
return Promise.all(changesets.map((commit) => writeChangeset(commit, cwd))); return Promise.all(changesets.map((commit) => writeChangeset(commit, cwd)));
}; };
@@ -54,8 +97,8 @@ beforeEach(() => {
describe("version", () => { describe("version", () => {
it("creates simple PR", async () => { it("creates simple PR", async () => {
let cwd = f.copy("simple-project"); await using fixture = await createSimpleProjectFixture();
await linkNodeModules(cwd); const cwd = fixture.path;
mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({ data: [] })); mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({ data: [] }));
@@ -68,18 +111,18 @@ describe("version", () => {
{ {
releases: [ releases: [
{ {
name: "simple-project-pkg-a", name: "changesets-dev-simple-project-pkg-a",
type: "minor", type: "minor",
}, },
{ {
name: "simple-project-pkg-b", name: "changesets-dev-simple-project-pkg-b",
type: "minor", type: "minor",
}, },
], ],
summary: "Awesome feature", summary: "Awesome feature",
}, },
], ],
cwd cwd,
); );
await runVersion({ await runVersion({
@@ -93,8 +136,8 @@ describe("version", () => {
}); });
it('creates a draft PR when prDraft is "create"', async () => { it('creates a draft PR when prDraft is "create"', async () => {
let cwd = f.copy("simple-project"); await using fixture = await createSimpleProjectFixture();
await linkNodeModules(cwd); const cwd = fixture.path;
mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({ data: [] })); mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({ data: [] }));
@@ -107,14 +150,14 @@ describe("version", () => {
{ {
releases: [ releases: [
{ {
name: "simple-project-pkg-a", name: "changesets-dev-simple-project-pkg-a",
type: "minor", type: "minor",
}, },
], ],
summary: "Awesome feature", summary: "Awesome feature",
}, },
], ],
cwd cwd,
); );
await runVersion({ await runVersion({
@@ -129,8 +172,8 @@ describe("version", () => {
}); });
it("only includes bumped packages in the PR body", async () => { it("only includes bumped packages in the PR body", async () => {
let cwd = f.copy("simple-project"); await using fixture = await createSimpleProjectFixture();
await linkNodeModules(cwd); const cwd = fixture.path;
mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({ data: [] })); mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({ data: [] }));
@@ -143,14 +186,14 @@ describe("version", () => {
{ {
releases: [ releases: [
{ {
name: "simple-project-pkg-a", name: "changesets-dev-simple-project-pkg-a",
type: "minor", type: "minor",
}, },
], ],
summary: "Awesome feature", summary: "Awesome feature",
}, },
], ],
cwd cwd,
); );
await runVersion({ await runVersion({
@@ -164,8 +207,8 @@ describe("version", () => {
}); });
it("doesn't include ignored package that got a dependency update in the PR body", async () => { it("doesn't include ignored package that got a dependency update in the PR body", async () => {
let cwd = f.copy("ignored-package"); await using fixture = await createIgnoredPackageFixture();
await linkNodeModules(cwd); const cwd = fixture.path;
mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({ data: [] })); mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({ data: [] }));
@@ -178,14 +221,14 @@ describe("version", () => {
{ {
releases: [ releases: [
{ {
name: "ignored-package-pkg-b", name: "changesets-dev-ignored-package-pkg-b",
type: "minor", type: "minor",
}, },
], ],
summary: "Awesome feature", summary: "Awesome feature",
}, },
], ],
cwd cwd,
); );
await runVersion({ await runVersion({
@@ -199,8 +242,8 @@ describe("version", () => {
}); });
it("does not include changelog entries if full message exceeds size limit", async () => { it("does not include changelog entries if full message exceeds size limit", async () => {
let cwd = f.copy("simple-project"); await using fixture = await createSimpleProjectFixture();
await linkNodeModules(cwd); const cwd = fixture.path;
mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({ data: [] })); mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({ data: [] }));
@@ -213,7 +256,7 @@ describe("version", () => {
{ {
releases: [ releases: [
{ {
name: "simple-project-pkg-a", name: "changesets-dev-simple-project-pkg-a",
type: "minor", type: "minor",
}, },
], ],
@@ -240,7 +283,7 @@ fluminis divesque vulnere aquis parce lapsis rabie si visa fulmineis.
`, `,
}, },
], ],
cwd cwd,
); );
await runVersion({ await runVersion({
@@ -253,13 +296,13 @@ fluminis divesque vulnere aquis parce lapsis rabie si visa fulmineis.
expect(mockedGithubMethods.pulls.create.mock.calls[0]).toMatchSnapshot(); expect(mockedGithubMethods.pulls.create.mock.calls[0]).toMatchSnapshot();
expect(mockedGithubMethods.pulls.create.mock.calls[0][0].body).toMatch( expect(mockedGithubMethods.pulls.create.mock.calls[0][0].body).toMatch(
/The changelog information of each package has been omitted from this message/ /The changelog information of each package has been omitted from this message/,
); );
}); });
it("does not include any release information if a message with simplified release info exceeds size limit", async () => { it("does not include any release information if a message with simplified release info exceeds size limit", async () => {
let cwd = f.copy("simple-project"); await using fixture = await createSimpleProjectFixture();
await linkNodeModules(cwd); const cwd = fixture.path;
mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({ data: [] })); mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({ data: [] }));
@@ -272,7 +315,7 @@ fluminis divesque vulnere aquis parce lapsis rabie si visa fulmineis.
{ {
releases: [ releases: [
{ {
name: "simple-project-pkg-a", name: "changesets-dev-simple-project-pkg-a",
type: "minor", type: "minor",
}, },
], ],
@@ -299,7 +342,7 @@ fluminis divesque vulnere aquis parce lapsis rabie si visa fulmineis.
`, `,
}, },
], ],
cwd cwd,
); );
await runVersion({ await runVersion({
@@ -312,13 +355,13 @@ fluminis divesque vulnere aquis parce lapsis rabie si visa fulmineis.
expect(mockedGithubMethods.pulls.create.mock.calls[0]).toMatchSnapshot(); expect(mockedGithubMethods.pulls.create.mock.calls[0]).toMatchSnapshot();
expect(mockedGithubMethods.pulls.create.mock.calls[0][0].body).toMatch( expect(mockedGithubMethods.pulls.create.mock.calls[0][0].body).toMatch(
/All release information have been omitted from this message, as the content exceeds the size limit/ /All release information have been omitted from this message, as the content exceeds the size limit/,
); );
}); });
it('updates an existing PR via GraphQL without converting it to draft when prDraft is "create"', async () => { it('updates an existing PR via GraphQL without converting it to draft when prDraft is "create"', async () => {
let cwd = f.copy("simple-project"); await using fixture = await createSimpleProjectFixture();
await linkNodeModules(cwd); const cwd = fixture.path;
mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({ mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({
data: [{ number: 123, node_id: "PR_kwDOA" }], data: [{ number: 123, node_id: "PR_kwDOA" }],
@@ -329,14 +372,14 @@ fluminis divesque vulnere aquis parce lapsis rabie si visa fulmineis.
{ {
releases: [ releases: [
{ {
name: "simple-project-pkg-a", name: "changesets-dev-simple-project-pkg-a",
type: "minor", type: "minor",
}, },
], ],
summary: "Awesome feature", summary: "Awesome feature",
}, },
], ],
cwd cwd,
); );
await runVersion({ await runVersion({
@@ -351,8 +394,8 @@ fluminis divesque vulnere aquis parce lapsis rabie si visa fulmineis.
}); });
it('updates an existing PR via GraphQL and converts it to draft when prDraft is "always"', async () => { it('updates an existing PR via GraphQL and converts it to draft when prDraft is "always"', async () => {
let cwd = f.copy("simple-project"); await using fixture = await createSimpleProjectFixture();
await linkNodeModules(cwd); const cwd = fixture.path;
mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({ mockedGithubMethods.pulls.list.mockImplementationOnce(() => ({
data: [{ number: 123, node_id: "PR_kwDOA" }], data: [{ number: 123, node_id: "PR_kwDOA" }],
@@ -363,14 +406,14 @@ fluminis divesque vulnere aquis parce lapsis rabie si visa fulmineis.
{ {
releases: [ releases: [
{ {
name: "simple-project-pkg-a", name: "changesets-dev-simple-project-pkg-a",
type: "minor", type: "minor",
}, },
], ],
summary: "Awesome feature", summary: "Awesome feature",
}, },
], ],
cwd cwd,
); );
await runVersion({ await runVersion({
+20 -18
View File
@@ -1,11 +1,11 @@
import fs from "node:fs/promises";
import { createRequire } from "node:module";
import path from "node:path";
import * as core from "@actions/core"; import * as core from "@actions/core";
import { exec, getExecOutput } from "@actions/exec"; import { exec, getExecOutput } from "@actions/exec";
import * as github from "@actions/github"; import * as github from "@actions/github";
import type { PreState } from "@changesets/types"; import type { PreState } from "@changesets/types";
import { type Package, getPackages } from "@manypkg/get-packages"; import { type Package, getPackages } from "@manypkg/get-packages";
import fs from "node:fs/promises";
import { createRequire } from "node:module";
import path from "node:path";
import semverLt from "semver/functions/lt.js"; import semverLt from "semver/functions/lt.js";
import { Git } from "./git.ts"; import { Git } from "./git.ts";
import type { Octokit } from "./octokit.ts"; import type { Octokit } from "./octokit.ts";
@@ -28,7 +28,7 @@ const MAX_CHARACTERS_PER_MESSAGE = 60000;
const createRelease = async ( const createRelease = async (
octokit: Octokit, octokit: Octokit,
{ pkg, tagName }: { pkg: Package; tagName: string } { pkg, tagName }: { pkg: Package; tagName: string },
) => { ) => {
let changelog; let changelog;
try { try {
@@ -45,7 +45,7 @@ const createRelease = async (
// we can find a changelog but not the entry for this version // we can find a changelog but not the entry for this version
// if this is true, something has probably gone wrong // if this is true, something has probably gone wrong
throw new Error( throw new Error(
`Could not find changelog entry for ${pkg.packageJson.name}@${pkg.packageJson.version}` `Could not find changelog entry for ${pkg.packageJson.name}@${pkg.packageJson.version}`,
); );
} }
@@ -91,7 +91,7 @@ export async function runPublish({
let changesetPublishOutput = await getExecOutput( let changesetPublishOutput = await getExecOutput(
publishCommand, publishCommand,
publishArgs, publishArgs,
{ cwd, env: { ...process.env, GITHUB_TOKEN: githubToken } } { cwd, env: { ...process.env, GITHUB_TOKEN: githubToken } },
); );
let { packages, tool } = await getPackages(cwd); let { packages, tool } = await getPackages(cwd);
@@ -111,7 +111,7 @@ export async function runPublish({
if (pkg === undefined) { if (pkg === undefined) {
throw new Error( throw new Error(
`Package "${pkgName}" not found.` + `Package "${pkgName}" not found.` +
"This is probably a bug in the action, please open an issue" "This is probably a bug in the action, please open an issue",
); );
} }
releasedPackages.push(pkg); releasedPackages.push(pkg);
@@ -123,14 +123,14 @@ export async function runPublish({
const tagName = `${pkg.packageJson.name}@${pkg.packageJson.version}`; const tagName = `${pkg.packageJson.name}@${pkg.packageJson.version}`;
await git.pushTag(tagName); await git.pushTag(tagName);
await createRelease(octokit, { pkg, tagName }); await createRelease(octokit, { pkg, tagName });
}) }),
); );
} }
} else { } else {
if (packages.length === 0) { if (packages.length === 0) {
throw new Error( throw new Error(
`No package found.` + `No package found.` +
"This is probably a bug in the action, please open an issue" "This is probably a bug in the action, please open an issue",
); );
} }
let pkg = packages[0]; let pkg = packages[0];
@@ -166,14 +166,16 @@ export async function runPublish({
const requireChangesetsCliPkgJson = (cwd: string) => { const requireChangesetsCliPkgJson = (cwd: string) => {
try { try {
return require(require.resolve("@changesets/cli/package.json", { return require(
paths: [cwd], require.resolve("@changesets/cli/package.json", {
})); paths: [cwd],
}),
);
} catch (err) { } catch (err) {
if (isErrorWithCode(err, "MODULE_NOT_FOUND")) { if (isErrorWithCode(err, "MODULE_NOT_FOUND")) {
throw new Error( throw new Error(
`Have you forgotten to install \`@changesets/cli\` in "${cwd}"?`, `Have you forgotten to install \`@changesets/cli\` in "${cwd}"?`,
{ cause: err } { cause: err },
); );
} }
throw err; throw err;
@@ -309,7 +311,7 @@ export async function runVersion({
{ {
cwd, cwd,
env, env,
} },
); );
} }
@@ -318,7 +320,7 @@ export async function runVersion({
changedPackages.map(async (pkg) => { changedPackages.map(async (pkg) => {
let changelogContents = await fs.readFile( let changelogContents = await fs.readFile(
path.join(pkg.dir, "CHANGELOG.md"), path.join(pkg.dir, "CHANGELOG.md"),
"utf8" "utf8",
); );
let entry = getChangelogEntry(changelogContents, pkg.packageJson.version); let entry = getChangelogEntry(changelogContents, pkg.packageJson.version);
@@ -328,7 +330,7 @@ export async function runVersion({
content: entry.content, content: entry.content,
header: `## ${pkg.packageJson.name}@${pkg.packageJson.version}`, header: `## ${pkg.packageJson.name}@${pkg.packageJson.version}`,
}; };
}) }),
); );
const finalPrTitle = `${prTitle}${!!preState ? ` (${preState.tag})` : ""}`; const finalPrTitle = `${prTitle}${!!preState ? ` (${preState.tag})` : ""}`;
@@ -353,8 +355,8 @@ export async function runVersion({
`Existing pull requests: ${JSON.stringify( `Existing pull requests: ${JSON.stringify(
existingPullRequests.data, existingPullRequests.data,
null, null,
2 2,
)}` )}`,
); );
await git.pushChanges({ branch: versionBranch, message: finalCommitMessage }); await git.pushChanges({ branch: versionBranch, message: finalCommitMessage });
+7 -7
View File
@@ -1,11 +1,11 @@
import unified from "unified";
import remarkParse from "remark-parse";
import remarkStringify from "remark-stringify";
import fs from "node:fs/promises"; import fs from "node:fs/promises";
import { getPackages, type Package } from "@manypkg/get-packages";
import type { Root } from "mdast"; import type { Root } from "mdast";
// @ts-ignore // @ts-ignore
import mdastToString from "mdast-util-to-string"; import mdastToString from "mdast-util-to-string";
import { getPackages, type Package } from "@manypkg/get-packages"; import remarkParse from "remark-parse";
import remarkStringify from "remark-stringify";
import unified from "unified";
export const BumpLevels = { export const BumpLevels = {
dep: 0, dep: 0,
@@ -21,7 +21,7 @@ export async function getVersionsByDirectory(cwd: string) {
export async function getChangedPackages( export async function getChangedPackages(
cwd: string, cwd: string,
previousVersions: Map<string, string> previousVersions: Map<string, string>,
) { ) {
let { packages } = await getPackages(cwd); let { packages } = await getPackages(cwd);
let changedPackages = new Set<Package>(); let changedPackages = new Set<Package>();
@@ -87,7 +87,7 @@ export function getChangelogEntry(changelog: string, version: string) {
export function sortTheThings( export function sortTheThings(
a: { private: boolean; highestLevel: number }, a: { private: boolean; highestLevel: number },
b: { private: boolean; highestLevel: number } b: { private: boolean; highestLevel: number },
) { ) {
if (a.private === b.private) { if (a.private === b.private) {
return b.highestLevel - a.highestLevel; return b.highestLevel - a.highestLevel;
@@ -110,6 +110,6 @@ export function isErrorWithCode(err: unknown, code: string) {
export function fileExists(filePath: string) { export function fileExists(filePath: string) {
return fs.access(filePath, fs.constants.F_OK).then( return fs.access(filePath, fs.constants.F_OK).then(
() => true, () => true,
() => false () => false,
); );
} }
-17
View File
@@ -1,17 +0,0 @@
type Opts = {
glob?: string | Array<string>;
root?: string;
cleanup?: boolean;
};
declare module "fixturez" {
export default function (
cwd: string,
opts?: Opts
): {
find: (a: string) => string;
temp: () => string;
copy: (a: string) => string;
cleanup: () => any;
};
}
-3069
View File
File diff suppressed because it is too large Load Diff