Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/actionlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
# Runner labels actionlint has no way to know about.
#
# actionlint checks every `runs-on` against the list of GitHub-hosted labels it
# ships with, so the Blacksmith machines pr.yml and release.yml ask for read as
# typos and any change to a workflow comes back with an error against each one.
#
# Nothing in this repository runs actionlint as part of a check. This file is
# here for the editors and review tooling that do run it, and because a label
# that has to be spelled exactly is worth writing down in one place.
#
# Keep in step with the `runs-on` lines in .github/workflows/.
self-hosted-runner:
labels:
- blacksmith-4vcpu-ubuntu-2404
- blacksmith-8vcpu-ubuntu-2404
162 changes: 130 additions & 32 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,138 @@ concurrency:
group: release
cancel-in-progress: false

# Nothing is granted by default; the job below asks for the two scopes it
# needs and no more.
# Nothing is granted by default; each job below asks for the scopes it needs
# and no more.
permissions: {}

# The checks pr.yml already ran, run again against main, and then publish.
#
# Re-running them is not belt and braces. The main ruleset does not require a
# pull request to be up to date with main before it merges, so two branches
# that were each green on their own can still break main together, and a
# release is the first thing after that which anyone would notice.
#
# They are separate jobs from the publish for two reasons. One is the runner:
# the checks want the Blacksmith machines pr.yml uses, and the publish wants a
# GitHub-hosted one (see the note on the release job). The other is that four
# jobs cost the slowest of them rather than the sum, and as one job the release
# was spending most of its wall clock running checks end to end.
#
# The check names are deliberately not the bare "Lint"/"Test"/"Build"/"Pack"
# pr.yml uses. Those four are the required status checks in the main ruleset,
# and a ruleset matches a check by name whatever workflow posted it, so a
# release dispatched from a branch with an open pull request would otherwise
# report into that pull request's gate.
#
# Spelled out rather than calling `pnpm check`, because that starts with
# `pnpm fmt`, which rewrites files instead of reporting on them. Keep these
# jobs and the ones in pr.yml in step with each other.
jobs:
lint:
name: Release lint
runs-on: blacksmith-4vcpu-ubuntu-2404

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate actionlint configuration and inspect runner-label declarations.
fd -H -t f -i 'actionlint\.ya?ml' . || true
rg -n -C 3 'self-hosted-runner|blacksmith-(4|8)vcpu-ubuntu-2404' . || true

Repository: KensioSoftware/yulin

Length of output: 158


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- workflow ---'
sed -n '1,220p' .github/workflows/release.yml

printf '%s\n' '--- relevant repository files ---'
git ls-files | rg '(^|/)(actionlint|\.github|Makefile|package\.json|\.pre-commit-config|Taskfile|justfile)' | head -200

printf '%s\n' '--- actionlint references and runner configuration ---'
rg -n -i -C 4 'actionlint|runner-label|runs-on|blacksmith|self-hosted' .github . 2>/dev/null | head -300

Repository: KensioSoftware/yulin

Length of output: 16245


🌐 Web query:

actionlint 1.7.12 unknown runner label self-hosted-runner configuration Blacksmith blacksmith-4vcpu-ubuntu-2404

💡 Result:

To resolve the actionlint error regarding the unknown runner label "blacksmith-4vcpu-ubuntu-2404", you must explicitly whitelist this custom label in your project's actionlint configuration file [1][2]. Actionlint flags this as an error because it is not part of its built-in list of recognized GitHub-hosted runner labels [2]. To fix this, create or update the file.github/actionlint.yaml in your repository with the following configuration [1][3][4]: #.github/actionlint.yaml self-hosted-runner: labels: - blacksmith-4vcpu-ubuntu-2404 If you use multiple Blacksmith runner labels, you can list them all under the labels section [5][6][7]: #.github/actionlint.yaml self-hosted-runner: labels: - blacksmith-4vcpu-ubuntu-2404 - blacksmith-8vcpu-ubuntu-2404 # Add other labels as needed By adding these definitions, actionlint will recognize these as valid self-hosted runner labels and stop reporting the [runner-label] error [1][8][9][10].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

if command -v actionlint >/dev/null 2>&1; then
  actionlint --version
  actionlint .github/workflows/release.yml || true
else
  echo "actionlint is not installed"
fi

printf '%s\n' '--- hidden config files ---'
find . -maxdepth 3 -type f \( -iname '*actionlint*' -o -name '.yamllint*' \) -print

Repository: KensioSoftware/yulin

Length of output: 4001


🌐 Web query:

site:github.com/rhysd/actionlint docs/config.md self-hosted-runner labels actionlint.yaml location

💡 Result:

The configuration file for actionlint, named actionlint.yaml or actionlint.yml, is typically placed in the.github directory of your repository [1][2]. Regarding the specific configuration for self-hosted runners, the labels are defined under the self-hosted-runner section in your actionlint configuration file [3][2]. This allows actionlint to recognize your custom runner labels when validating workflows [4]. The configuration supports glob patterns for flexible label matching [3][4]. Example configuration structure: self-hosted-runner: labels: - linux-runner-1 - custom-gpu-* For most setups, placing the file at.github/actionlint.yaml is sufficient [1][2]. If you are using specialized tools like Super-Linter, you may need to check that specific tool's documentation for its required configuration file location, as it may differ from the default expected by actionlint [1][5]. You can generate a default configuration file using the actionlint -init-config command [1].

Citations:


Configure actionlint for the Blacksmith runner labels.

Add blacksmith-4vcpu-ubuntu-2404 and blacksmith-8vcpu-ubuntu-2404 under self-hosted-runner.labels in .github/actionlint.yaml. actionlint 1.7.12 rejects all four runs-on entries without this configuration.

🧰 Tools
🪛 actionlint (1.7.12)

[error] 85-85: label "blacksmith-4vcpu-ubuntu-2404" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2025-vs2026", "windows-2022", "windows-11-arm", "ubuntu-slim", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "macos-latest", "macos-latest-xlarge", "macos-latest-large", "macos-26-intel", "macos-26-xlarge", "macos-26-large", "macos-26", "macos-15-intel", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xlarge", "macos-14-large", "macos-14", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)

📍 Affects 1 file
  • .github/workflows/release.yml#L85-L85 (this comment)
  • .github/workflows/release.yml#L114-L114
  • .github/workflows/release.yml#L133-L133
  • .github/workflows/release.yml#L156-L156
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml at line 85, Add blacksmith-4vcpu-ubuntu-2404
and blacksmith-8vcpu-ubuntu-2404 to self-hosted-runner.labels in
.github/actionlint.yaml so actionlint accepts the runner labels used by all four
entries in .github/workflows/release.yml at lines 85, 114, 133, and 156; no
direct changes are required in release.yml.

Source: Linters/SAST tools

permissions:
contents: read
steps:
# Actions are pinned to commit SHAs rather than tags throughout this
# workflow. A tag can be moved to point at new code, which is how the
# tj-actions/changed-files compromise reached the repositories using it;
# a SHA cannot. The trailing comment is the tag each SHA was resolved
# from, so a bump is still readable in review.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
with:
version: 11.17.0
cache: true
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm fta

test:
name: Release test
# The same runner pr.yml gives the suite, kept in step with it rather than
# sized on its own. Since vitest.config.ts stopped isolating every test
# file the suite is no longer the long pole here, so if these two ever want
# tuning, measure before paying for the larger machine in either file.
runs-on: blacksmith-8vcpu-ubuntu-2404
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
with:
version: 11.17.0
cache: true
- run: pnpm install --frozen-lockfile
- run: pnpm test:coverage

build:
name: Release build
runs-on: blacksmith-4vcpu-ubuntu-2404
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
with:
version: 11.17.0
cache: true
- run: pnpm install --frozen-lockfile
- run: pnpm build:check
# Extracts the examples out of docs/, type checks and lints them. Not one
# of pr.yml's jobs; a release is where a documented example that no
# longer compiles would otherwise first be noticed.
- run: pnpm examples:check

pack:
name: Release pack
runs-on: blacksmith-4vcpu-ubuntu-2404
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
with:
version: 11.17.0
cache: true
- run: pnpm install --frozen-lockfile
# The same check pr.yml runs as Pack: builds the tarball, installs it
# into a throwaway project and imports every export subpath. The last
# gate before a broken dist/ reaches the registry.
- run: pnpm verify:pack

release:
name: Release
# A GitHub-hosted runner rather than the Blacksmith ones pr.yml uses. The
# release path is the one place worth keeping third parties out of, and
# this job runs a few times a month, so the speed is not worth the reach.
# Nothing runs here until every check above is green. They check out the
# same commit this one publishes, so a green check is a statement about the
# tarball semantic-release is about to build.
needs: [lint, test, build, pack]

# A GitHub-hosted runner rather than the Blacksmith ones the checks use.
# This is the job that mints the npm publish credential, and the publish
# path is the one place worth keeping third parties out of. The checks hold
# no credential and produce nothing this job consumes, so they can run
# wherever is fastest without that reach following them here.
runs-on: ubuntu-latest

# What the npm trusted publisher is scoped to, and where any approval
Expand All @@ -78,11 +200,6 @@ jobs:
id-token: write

steps:
# Actions are pinned to commit SHAs rather than tags throughout this
# workflow. A tag can be moved to point at new code, which is how the
# tj-actions/changed-files compromise reached the repositories using it;
# a SHA cannot. The trailing comment is the tag each SHA was resolved
# from, so a bump is still readable in review.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
# semantic-release works out the next version by reading the
Expand All @@ -104,30 +221,11 @@ jobs:

- run: pnpm install --frozen-lockfile

# The checks pr.yml already ran, run again against main.
#
# This is not belt and braces. The main ruleset does not require a pull
# request to be up to date with main before it merges, so two branches
# that were each green on their own can still break main together, and
# a release is the first thing after that which anyone would notice.
#
# Spelled out rather than calling `pnpm check`, because that starts with
# `pnpm fmt`, which rewrites files instead of reporting on them. Keep
# this list and the jobs in pr.yml in step with each other.
- run: pnpm lint
- run: pnpm fta
- run: pnpm build:check
- run: pnpm examples:check
- run: pnpm test:coverage

# The same check pr.yml runs as Pack: builds the tarball, installs it
# into a throwaway project and imports every export subpath. The last
# gate before a broken dist/ reaches the registry.
- run: pnpm verify:pack

# Decides the version, publishes to npm, tags and writes the GitHub
# Release. Does nothing at all if the commits since the last tag are
# only chore/test/docs. See .releaserc.yaml.
# only chore/test/docs. See .releaserc.yaml. The tarball is built here by
# prepack, from this checkout, rather than carried over from the pack
# check — that check proves the build works, it does not hand anything on.
- run: pnpm exec semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
17 changes: 17 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,23 @@ export default defineConfig({
},
test: {
environment: "node",
// Test files share a worker rather than getting a fresh one each. The suite
// is dominated by importing modules, not by running tests: with a worker
// per file the same @aws-sdk clients are parsed hundreds of times over, and
// that import cost was roughly five times the time the tests themselves
// took. Sharing the worker imports them once and the cost all but vanishes.
//
// What makes it safe is what the simulator is for. State lives on a SimAws
// instance a test makes and drops, not in module scope, so a file leaves
// nothing behind for the next one to find. Nothing in the suite calls
// vi.mock either, which is the usual reason a shared module registry goes
// wrong. The whole suite passes in a single process, in file order and
// shuffled, which is the strongest form of that claim available.
//
// Turn this back on if a test ever has to reach for module-level state —
// and prefer changing the test, because a simulator that cannot survive a
// shared registry is one its users cannot either.
isolate: false,
typecheck: {
tsconfig: "./tsconfig.json",
},
Expand Down
Loading