From 31fc6a00041e559f9ae1014dbd4ff2610d80eb44 Mon Sep 17 00:00:00 2001 From: Sem Van Broekhoven <144097969+dotsem@users.noreply.github.com> Date: Thu, 12 Nov 2026 14:41:24 +0100 Subject: [PATCH 1/4] chore: remove unused items from gitignore --- .gitignore | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.gitignore b/.gitignore index 5d1d311..5e7a148 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,3 @@ -node_modules/ -.pnpm-store/ *.log .DS_Store Thumbs.db -.dart_tool/ -**/build/ -**/ephemeral/ -build-args.json From ba3a2c8cbc1016bb4f965d5af87cafb964f50a6c Mon Sep 17 00:00:00 2001 From: Sem Van Broekhoven <144097969+dotsem@users.noreply.github.com> Date: Thu, 12 Nov 2026 14:41:36 +0100 Subject: [PATCH 2/4] chore: remove prettierignore --- .prettierignore | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .prettierignore diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index be0c97c..0000000 --- a/.prettierignore +++ /dev/null @@ -1,4 +0,0 @@ -node_modules/ -dist/ -**/dist/** -pnpm-lock.yaml From fb94d8cfc906acb3be7b44ec4b35d17cf72fe1b6 Mon Sep 17 00:00:00 2001 From: Sem Van Broekhoven <144097969+dotsem@users.noreply.github.com> Date: Thu, 12 Nov 2026 14:50:40 +0100 Subject: [PATCH 3/4] refactor: update workflows to adhere to new split standards --- .github/workflows/actionlint.yml | 20 +++++++++++--------- .github/workflows/check-refs.yml | 9 ++++++++- .github/workflows/lint.yml | 25 ++++++++++++++----------- .github/workflows/release.yml | 25 +++++++++++++++++++------ .github/workflows/test-scripts.yml | 9 ++++++++- 5 files changed, 60 insertions(+), 28 deletions(-) diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index 5d0e625..036a54d 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -5,13 +5,17 @@ on: paths: - ".github/workflows/**" - "action.yml" + - "action.yaml" - "**/action.yml" + - "**/action.yaml" push: branches: [main] paths: - ".github/workflows/**" - "action.yml" + - "action.yaml" - "**/action.yml" + - "**/action.yaml" workflow_dispatch: workflow_call: @@ -26,16 +30,14 @@ jobs: actionlint: name: actionlint runs-on: ubuntu-latest - permissions: - contents: read - checks: write # github-check reporter - pull-requests: write # github-pr-review reporter + timeout-minutes: 10 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Run actionlint - uses: reviewdog/action-actionlint@a7d35aaf8c309203a4ae861d32b7bd490baa7bf3 # v1.83.0 - with: - reporter: ${{ github.event_name == 'pull_request' && 'github-pr-review' || 'github-check' }} - filter_mode: ${{ github.event_name == 'pull_request' && 'file' || 'nofilter' }} - fail_level: error + shell: bash + env: + ACTIONLINT_IMAGE: rhysd/actionlint:1.7.12@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667 + run: | + docker run --rm -v "$PWD:/repo" -w /repo "$ACTIONLINT_IMAGE" \ + -format '{{range $err := .}}::error file={{$err.Filepath}},line={{$err.Line}},col={{$err.Column}}::{{$err.Message}}\n{{end}}' diff --git a/.github/workflows/check-refs.yml b/.github/workflows/check-refs.yml index 8142389..39f1b0f 100644 --- a/.github/workflows/check-refs.yml +++ b/.github/workflows/check-refs.yml @@ -4,14 +4,20 @@ on: pull_request: paths: - ".github/workflows/*.yml" + - ".github/workflows/*.yaml" - "action.yml" + - "action.yaml" - "**/action.yml" + - "**/action.yaml" push: branches: [main] paths: - ".github/workflows/*.yml" + - ".github/workflows/*.yaml" - "action.yml" + - "action.yaml" - "**/action.yml" + - "**/action.yaml" workflow_dispatch: workflow_call: @@ -26,6 +32,7 @@ jobs: check-refs: name: dotactions references runs-on: ubuntu-latest + timeout-minutes: 5 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -36,7 +43,7 @@ jobs: path='(/[A-Za-z0-9_./-]+)?' self="${GITHUB_REPOSITORY//./\\.}${path}" org="${GITHUB_REPOSITORY_OWNER//./\\.}/[A-Za-z0-9_.-]+${path}" - files=('.github/workflows/*.yml' 'action.yml' '*/action.yml') + files=('.github/workflows/*.yml' '.github/workflows/*.yaml' 'action.yml' 'action.yaml' '*/action.yml' '*/action.yaml') failed=0 # Self-references stay @main on main; the release workflow rewrites them to the release tag. diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index f79f887..cd33ed9 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -28,6 +28,7 @@ jobs: shellcheck: name: ShellCheck runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -35,27 +36,29 @@ jobs: - name: Run ShellCheck shell: bash + env: + ACTIONLINT_IMAGE: rhysd/actionlint:1.7.12@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667 run: | - git ls-files '*.sh' '*.bash' ':!:tests/fixtures/*' | xargs -r shellcheck -x + git ls-files -z '*.sh' '*.bash' ':!:tests/fixtures/*' \ + | xargs -0 -r docker run --rm -v "$PWD:/repo" -w /repo --entrypoint shellcheck "$ACTIONLINT_IMAGE" -x psscriptanalyzer: name: PSScriptAnalyzer runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Run PSScriptAnalyzer shell: pwsh run: | - if (-not (Get-Module -ListAvailable -Name PSScriptAnalyzer)) { - Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser - } - $scripts = git ls-files "*.ps1" ":!:tests/*" - if ($scripts) { - $issues = $scripts | Invoke-ScriptAnalyzer -Severity Error, Warning - if ($issues) { - $issues | Format-Table -AutoSize - exit 1 - } + if (-not $scripts) { exit 0 } + + Install-Module -Name PSScriptAnalyzer -RequiredVersion 1.25.0 -Force -Scope CurrentUser + Import-Module PSScriptAnalyzer -RequiredVersion 1.25.0 + $issues = $scripts | Invoke-ScriptAnalyzer -Severity Error, Warning + if ($issues) { + $issues | Format-Table -AutoSize + exit 1 } diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 016d4a6..1fa607c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,6 +4,7 @@ name: Release # 1. rewrites every self-reference (/[/path]@main) to @v in a release commit # 2. tags that commit v and publishes a GitHub release with generated notes # 3. moves the floating tags (v, and v0. during 0.x) to it, unless it's a pre-release +# or an older version than the one the floating tag already has (so a hotfix never moves v1 backwards) # main itself is never modified, so it keeps @main. # # Authenticates as a GitHub App (short-lived installation token, scoped to the caller's repo) because @@ -39,6 +40,7 @@ permissions: jobs: release: runs-on: ubuntu-latest + timeout-minutes: 10 steps: - name: Validate inputs shell: bash @@ -85,7 +87,8 @@ jobs: VERSION: ${{ inputs.version }} run: | self="${GITHUB_REPOSITORY//./\\.}(/[A-Za-z0-9_./-]+)?" - mapfile -t files < <(git ls-files '.github/workflows/*.yml' 'action.yml' '*/action.yml') + mapfile -t files < <(git ls-files '.github/workflows/*.yml' '.github/workflows/*.yaml' \ + 'action.yml' 'action.yaml' '*/action.yml' '*/action.yaml') sed -i -E "s#(${self})@main\b#\1@v${VERSION}#g" "${files[@]}" if git grep -nE "${self}@main\b" -- "${files[@]}"; then @@ -133,11 +136,21 @@ jobs: REST="${VERSION#*.}" MINOR="${REST%%.*}" - git tag -fa "v${MAJOR}" -m "Update v${MAJOR} to v${VERSION}" - git push origin "v${MAJOR}" --force - + # highest stable release tag matching the pattern; the new tag is already created locally. + highest() { + git tag -l "$1" | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n 1 + } + float() { + if [ "$(highest "$1.*")" != "v${VERSION}" ]; then + echo "::notice::Not moving $1: a newer release than v${VERSION} exists ($(highest "$1.*"))" + return + fi + git tag -fa "$1" -m "Update $1 to v${VERSION}" + git push origin "$1" --force + } + + float "v${MAJOR}" # float minor tag during 0.x, where minors may contain breaking changes if [ "$MAJOR" = "0" ]; then - git tag -fa "v0.${MINOR}" -m "Update v0.${MINOR} to v${VERSION}" - git push origin "v0.${MINOR}" --force + float "v0.${MINOR}" fi diff --git a/.github/workflows/test-scripts.yml b/.github/workflows/test-scripts.yml index a632803..41c9243 100644 --- a/.github/workflows/test-scripts.yml +++ b/.github/workflows/test-scripts.yml @@ -15,6 +15,7 @@ jobs: test-scripts: name: Shell tests (${{ matrix.os }}) runs-on: ${{ matrix.os }} + timeout-minutes: 20 strategy: fail-fast: false matrix: @@ -33,8 +34,14 @@ jobs: - name: Run tests/*.test.sh shell: bash run: | + shopt -s nullglob + tests=(tests/*.test.sh) + if [ "${#tests[@]}" -eq 0 ]; then + echo "::error::No tests/*.test.sh found; don't call test-scripts.yml from a repo without script tests" + exit 1 + fi failed=0 - for t in tests/*.test.sh; do + for t in "${tests[@]}"; do echo "::group::$t" bash "$t" || failed=1 echo "::endgroup::" From e490f0f7300ee6dc9089610ce2ad5328ffc2de8a Mon Sep 17 00:00:00 2001 From: Sem Van Broekhoven <144097969+dotsem@users.noreply.github.com> Date: Thu, 12 Nov 2026 14:51:09 +0100 Subject: [PATCH 4/4] docs(readme): update readme according to new standards --- README.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 52165ae..85d006a 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,11 @@ Shared CI for the `dotactions/*` repos: reusable workflows plus the shell test h | Workflow | Does | Caller job needs | | :--- | :--- | :--- | -| `release.yml` | Rewrites the caller's `@main` self-references to `@v` in a release commit, tags it, creates the GitHub release, moves `v` (and `v0.` during `0.x`) | `secrets: inherit` | +| `release.yml` | Rewrites the caller's `@main` self-references to `@v` in a release commit, tags it, creates the GitHub release, moves `v` (and `v0.` during `0.x`) forward only | `secrets: inherit` | | `check-refs.yml` | Self-references must be `@main`; other repos in the org must be `@<40-char release-tag sha> # vX.Y.Z` | — | -| `actionlint.yml` | actionlint via reviewdog | `checks: write`, `pull-requests: write` | -| `lint.yml` | ShellCheck and PSScriptAnalyzer on tracked scripts | — | -| `test-scripts.yml` | `tests/*.test.sh` on ubuntu, macOS and Windows, with submodules | — | +| `actionlint.yml` | actionlint (pinned image), errors as annotations | — | +| `lint.yml` | ShellCheck (pinned image) and PSScriptAnalyzer (pinned version) on tracked scripts | — | +| `test-scripts.yml` | `tests/*.test.sh` on ubuntu, macOS and Windows, with submodules; fails if there are none | — | Inside a called workflow, `github.*` and `vars` belong to the **caller**, so every workflow acts on the calling repo. @@ -50,13 +50,9 @@ permissions: jobs: actionlint: uses: dotactions/tooling/.github/workflows/actionlint.yml@ # v1.0.0 - permissions: - contents: read - checks: write - pull-requests: write ``` -`check-refs.yml`, `lint.yml` and `test-scripts.yml` are called the same way, with no `with:` or extra permissions. +`check-refs.yml`, `lint.yml` and `test-scripts.yml` are called the same way. None needs `with:` or permissions beyond `contents: read`. ## Test harness