🧅 Write your GitHub Actions using Bun!
// main.ts
import * as core from "@actions/core";
console.log(`Hello ${core.getInput("name")}!`);
core.setOutput("time", new Date().toLocaleTimeString()); | |
# action.yml
runs:
using: bun1
main: main.ts |
# .github/workflows/publish-action.yml
- uses: jcbhmr/configure-bun-action@v1
- uses: actions4git/add-commit-push@v1 |
🧅 Uses Bun, not Node.js to run your JavaScript (or TypeScript)
📦 Embeds the bun
binary in your GitHub Action
🌯 Uses the native Node.js runtime to spawn bun /path/to/main.ts
🧙♂️ Bun supports auto-installing dependencies
🚀 Looking to get started with a template? Check out the "Hello world!" GitHub Action using Bun template to hit the ground running!
To get started using Bun as your GitHub Actions runtime of choice, just add this
to your action.yml
. Yes, it's non-standard and won't work as-is but don't
worry, we'll preprocess it with uses: jcbhmr/configure-bun-action@v1
.
# action.yml
runs:
using: bun1
main: main.ts
Nice! Now you have the proper manifest. To actually publish your new GitHub
Action so that it can be used we need to preprocess it to use the native Node.js
runtime with a wrapper to run bun main.ts
. That's exactly what this GitHub
Action does. To use it you'll need to add a post-release GitHub Actions workflow
like this to your project:
# .github/workflows/publish-action.yml
name: publish-action
on:
release:
types: released
jobs:
publish-action:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: jcbhmr/configure-bun-action@v1
- uses: actions4git/setup-git@v1
- run: git add -Af && git commit -m 'Automatic changes'
- run: git tag -f "$TAG" && git push -f origin "$TAG"
env:
TAG: ${{ github.event.release.tag_name }}
- uses: actions/publish-action@v0.2.2
with:
source-tag: ${{ github.event.release.tag_name }}
Look at that! Now whenever we release a new v1.0.0
version this workflow will
run to downlevel our using: bun1
action to using: node20
. Then we update the
tag to use the compiled version. After that magic has completed,
actions/publish-action will update the major v1
version tag to point to the
new release.
💡 You can use this post-release tag mutation trick for your Node.js-based GitHub Actions too!
Now you might be wondering how to test your action locally, right? To do that,
just make sure you run uses: jcbhmr/configure-bun-action@v1
before you do
uses: ./
like this:
# .github/workflows/test-action.yml
name: Test action
on:
push:
branches: "main"
pull_request:
jobs:
test-action:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: jcbhmr/configure-bun-action@v1
- uses: ./
-
There's a startup delay from the Node.js wrapper. This is required since we are using Node.js as our native runtime layer. There's an additional startup delay from un-gzipping the binary files.
-
This GitHub Action pseudo-runtime relies on large binary files in your Git repository. As you create more releases you repository size may grow quite large. We aren't using a from-network installation because the startup time would skyrocket to ~5 seconds.
-
Any GitHub Action created using Bun won't support Windows since Bun doesn't yet provide stable builds for Windows. oven-sh/bun#43
-
Your GitHub Action is no longer directly usable; there's a compile step. That means
uses: octocat/my-action@main
doesn't work. This problem is shared with many Node.js-based Actions which also require a compile step.
When using the recommended on: release
post-release build workflow, there's
also these caveats:
- There's a ~30 second window where the latest release has uncompiled code.
The major tags are never affected. This is nothing to worry about
because there's no way this could break anything. The only way to see the
uncompiled code would be to explicitly
uses: octocat/my-action@v1.2.3
(@v1
is unaffected) immediately after v1.2.3 was released. It's not humanly possible to respond that fast to a new release. Even so, this is still a thing that is worth knowing.
When this configurator action runs, it essentially does the following... TODO
This action relies on you to commit the result in order to make it usable
by GitHub Actions consumers. That means doing git add .bun
, git commit
, and
git push
or something similar. See the Usage section for details.
Why Node.js instead of Docker as the native runtime?
Because Docker is slower. That's it. 🤷♂️
How do I test my changes?
The easiest way is to open a Draft Pull Request either against the upstream repository or against your own fork's main branch and watch the GitHub Actions do their thing.