@@ -44,7 +44,45 @@ inputs:
4444 aws-lambda-url :
4545 description : " "
4646 required : false
47- # nodejs inputs
47+ # toolchain inputs
48+ package-manager :
49+ description : |
50+ Which package manager installs dependencies and runs the changesets
51+ commands: `pnpm` (default) or `bun`.
52+
53+ With `pnpm`, Node and pnpm are installed and `pnpm install` runs. With
54+ `bun`, neither is installed: bun is set up instead and
55+ `bun install --frozen-lockfile` runs, so a bun repo needs no
56+ `engines.node` in its package.json and no pnpm lockfile.
57+ required : false
58+ default : " pnpm"
59+ bun-version :
60+ description : |
61+ The bun version to install, e.g. `1.3.14`. Only used when
62+ `package-manager` is `bun`. Takes precedence over `bun-version-file` and
63+ auto-detection. Leave it empty (the default) to read the version from
64+ the repo's own pin instead of restating it here, where it can drift.
65+ required : false
66+ default : " "
67+ bun-version-file :
68+ description : |
69+ Path to a file the bun version is read from when `bun-version` is empty.
70+ Only used when `package-manager` is `bun`.
71+
72+ setup-bun reads `.tool-versions`, `.bun-version`, and `package.json`
73+ (`packageManager`, else `engines.bun`) natively, so this action forwards
74+ those straight to setup-bun. It does not understand `mise.toml`, which is
75+ where our TypeScript repos pin an exact bun, so this action reads
76+ `mise.toml`, `.mise.toml`, and `.config/mise/config.toml` itself and
77+ passes the version to setup-bun as `bun-version`.
78+
79+ Leave it empty (the default) to auto-detect: the action checks for a mise
80+ file first, then forwards `.tool-versions` or `.bun-version` to setup-bun
81+ if present, and setup-bun finally reads `package.json` or installs
82+ `latest`.
83+ required : false
84+ default : " "
85+ # nodejs inputs (package-manager: pnpm only)
4886 node-version-file :
4987 description : " "
5088 required : false
@@ -59,13 +97,17 @@ inputs:
5997 default : " true"
6098 # changesets inputs
6199 changesets-publish-cmd :
62- description : " "
100+ description : |
101+ Defaults to `<package-manager> run ci:changeset:publish`, i.e.
102+ `pnpm run ci:changeset:publish` unless `package-manager` is `bun`.
63103 required : false
64- default : pnpm run ci:changeset:publish
104+ default : " "
65105 changesets-version-cmd :
66- description : " "
106+ description : |
107+ Defaults to `<package-manager> run ci:changeset:version`, i.e.
108+ `pnpm run ci:changeset:version` unless `package-manager` is `bun`.
67109 required : false
68- default : pnpm run ci:changeset:version
110+ default : " "
69111 changesets-create-gh-release :
70112 description : " "
71113 required : false
@@ -121,6 +163,20 @@ outputs:
121163runs :
122164 using : composite
123165 steps :
166+ - name : Validate package-manager
167+ shell : bash
168+ env :
169+ PACKAGE_MANAGER : ${{ inputs.package-manager }}
170+ run : |
171+ set -euo pipefail
172+ case "${PACKAGE_MANAGER}" in
173+ pnpm | bun) ;;
174+ *)
175+ echo "::error::package-manager must be 'pnpm' or 'bun', got '${PACKAGE_MANAGER}'"
176+ exit 1
177+ ;;
178+ esac
179+
124180 # GATI is optional. This step only runs when `aws-role-arn` is provided.
125181 # When GATI is not configured, the action falls back to `github-token`
126182 # (the automatic GITHUB_TOKEN by default). Using GATI requires the calling
@@ -167,22 +223,74 @@ runs:
167223 git config user.email "${{ inputs.git-email }}"
168224 git config user.name "${{ inputs.git-user }}"
169225
226+ # One of the two toolchain paths below runs, never both. `bun` skips Node and
227+ # pnpm entirely: a bun repo has no pnpm lockfile to install from, and its
228+ # package.json carries `engines.bun` rather than the `engines.node` that
229+ # node-version-file needs.
170230 - name : Setup nodejs
231+ if : inputs.package-manager == 'pnpm'
171232 uses : smartcontractkit/.github/actions/setup-nodejs@setup-nodejs/v1
172233 with :
173234 node-version-file : ${{ inputs.node-version-file }}
174235 pnpm-version : ${{ inputs.pnpm-version }}
175236 use-cache : ${{ inputs.pnpm-use-cache }}
176237 run-install : " true"
177238
239+ # setup-bun reads .tool-versions, .bun-version, and package.json natively
240+ # via its bun-version-file input, so those are forwarded to it unchanged.
241+ # It does not read mise.toml, which is where our TypeScript repos pin an
242+ # exact bun, so the script resolves that case to a plain version instead.
243+ # `bun-version` still wins when set, the same way setup-nodejs lets
244+ # pnpm-version override .tool-versions.
245+ - name : Resolve bun version
246+ id : bun-version
247+ if : inputs.package-manager == 'bun'
248+ shell : bash
249+ env :
250+ BUN_VERSION : ${{ inputs.bun-version }}
251+ BUN_VERSION_FILE : ${{ inputs.bun-version-file }}
252+ run : " ${GITHUB_ACTION_PATH}/scripts/resolve-bun-version.sh"
253+
254+ - name : Setup bun
255+ if : inputs.package-manager == 'bun'
256+ uses : oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
257+ with :
258+ bun-version : ${{ steps.bun-version.outputs.version }}
259+ bun-version-file : ${{ steps.bun-version.outputs.file }}
260+
261+ # bun.lock records the root package's name and its dependencies, not the
262+ # root's own version, so a `changeset version` bump does not invalidate it
263+ # and --frozen-lockfile keeps holding across releases.
264+ - name : Run package manager install (bun)
265+ if : inputs.package-manager == 'bun'
266+ shell : bash
267+ run : bun install --frozen-lockfile
268+
269+ # Both commands default to the selected package manager, so a bun caller
270+ # that overrides neither does not fall back to a pnpm that was never
271+ # installed. For a pnpm caller the resolved values are unchanged.
272+ - name : Resolve changesets commands
273+ id : cmds
274+ shell : bash
275+ env :
276+ PACKAGE_MANAGER : ${{ inputs.package-manager }}
277+ PUBLISH_CMD : ${{ inputs.changesets-publish-cmd }}
278+ VERSION_CMD : ${{ inputs.changesets-version-cmd }}
279+ run : |
280+ set -euo pipefail
281+ {
282+ echo "publish=${PUBLISH_CMD:-${PACKAGE_MANAGER} run ci:changeset:publish}"
283+ echo "version=${VERSION_CMD:-${PACKAGE_MANAGER} run ci:changeset:version}"
284+ } | tee -a "${GITHUB_OUTPUT}"
285+
178286 - name : Run changesets
179287 id : changesets
180288 uses : smartcontractkit/.github/actions/signed-commits@changesets-signed-commits/v1
181289 env :
182290 GITHUB_TOKEN : ${{ steps.resolve-gh-token.outputs.token }}
183291 with :
184- publish : ${{ inputs.changesets- publish-cmd }}
185- version : ${{ inputs.changesets- version-cmd }}
292+ publish : ${{ steps.cmds.outputs. publish }}
293+ version : ${{ steps.cmds.outputs. version }}
186294 createGithubReleases : ${{ inputs.changesets-create-gh-release }}
187295 rootVersionPackagePath :
188296 ${{ inputs.changesets-root-version-package-path }}
0 commit comments