Compare commits

..

45 Commits

Author SHA1 Message Date
34372bcd36 feat(pr-lint): consolidate dependency review into pr-lint action (#497)
* feat(pr-lint): consolidate dependency review into pr-lint action

Move dependency review from standalone workflow into the pr-lint
composite action. Adds repository visibility check via GitHub API
and runs dependency-review-action only on public repos during
pull_request events, before MegaLinter.

* fix(pr-lint): harden dependency review visibility check

Address PR review feedback from Copilot and CodeRabbit:
- Skip visibility check on non-PR events (if: pull_request)
- Add continue-on-error so API failures don't block MegaLinter
- Use curl --fail --show-error to surface HTTP errors in logs
- Use github.token directly instead of inputs.token fallback
- Add Accept header for GitHub API versioning
- Validate jq output type to fail closed on bad API responses

* fix(pr-lint): use event payload for visibility, unblock MegaLinter on dep review

Replace curl API call with local jq read from $GITHUB_EVENT_PATH for
the repository visibility check — simpler, faster, no auth needed.

Add continue-on-error to dependency review so MegaLinter always runs,
with a re-fail step after artifacts upload to preserve the failure signal.
2026-03-08 21:44:45 +02:00
f995f89a21 chore(claude): add hooks, skills, and agents for Claude Code (#496)
* chore(claude): add hooks, skills, and agents for Claude Code

Add auto-formatting hooks (ruff, shfmt, prettier, actionlint),
rules.yml edit blocker, 5 skills (/release, /test-action,
/new-action, /validate, /check-pins), and 2 subagents
(action-validator, test-coverage-reviewer). Update CLAUDE.md
with hook documentation.

* fix(claude): add tool availability guards and fix skill docs

Add jq availability checks to hook scripts (block-rules-yml.sh,
post-edit-write.sh) and wrap actionlint call in command -v guard,
consistent with project rules #2 and #10. Fix validate skill to
reflect actual make all pipeline order and note that make test
runs separately.

* fix(claude): correct skill docs per PR review feedback

Fix validate skill description to say "precommit" instead of "test",
and fix check-pins SHA guidance to use origin/main instead of HEAD.

* feat(tools): add SHA-pinning enforcement to check-version-refs

The check-version-refs script previously only displayed existing
SHA-pinned refs but silently skipped non-SHA references. Add a
validation pass that detects and reports any ivuorinen/actions/*
references not using a 40-char hex SHA, exiting 1 on violations.

* fix(tools): fix temp file leak in check-version-refs.sh

Write find output directly to $violations_file instead of
$violations_file.all so the EXIT trap covers cleanup on all
exit paths, not just the happy path.
2026-03-08 04:22:02 +02:00
renovate[bot]
242ecca8f0 chore(deps): update pre-commit hook astral-sh/ruff-pre-commit (v0.15.4 → v0.15.5) (#495)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-07 17:07:03 +02:00
renovate[bot]
97105fc2a9 chore(deps): lock file maintenance (#494)
* chore(deps): update actions/setup-node action (v6.2.0 → v6.3.0)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): lock file maintenance

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

---------

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 11:17:12 +02:00
renovate[bot]
e9deac2a01 chore(deps)!: update docker/metadata-action (v5.10.0 → v6.0.0) (#493)
* chore(deps): update actions/setup-node action (v6.2.0 → v6.3.0)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps)!: update docker/metadata-action (v5.10.0 → v6.0.0)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

---------

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 11:16:38 +02:00
renovate[bot]
480c06b83b chore(deps): update actions/setup-node action (v6.2.0 → v6.3.0) (#491)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 11:16:07 +02:00
renovate[bot]
07ce8df887 chore(deps)!: update docker/build-push-action (v6.19.2 → v7.0.0) (#492)
* chore(deps): update actions/setup-node action (v6.2.0 → v6.3.0)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps)!: update docker/build-push-action (v6.19.2 → v7.0.0)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

---------

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 11:15:36 +02:00
renovate[bot]
0f29424163 chore(deps): update actions/setup-dotnet action (v5.1.0 → v5.2.0) (#490)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 11:15:00 +02:00
renovate[bot]
ce81e51641 chore(deps): update raven-actions/actionlint action (v2.1.1 → v2.1.2) (#488)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 11:14:39 +02:00
renovate[bot]
261323db29 chore(deps): update actions/dependency-review-action action (v4.8.3 → v4.9.0) (#489)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 11:14:15 +02:00
renovate[bot]
c679f0c863 chore(deps): update pre-commit hook astral-sh/uv-pre-commit (0.10.7 → 0.10.8) (#486)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 02:51:06 +02:00
renovate[bot]
128b2f1713 chore(deps): update oven-sh/setup-bun action (v2.1.2 → v2.1.3) (#485)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 02:50:33 +02:00
renovate[bot]
08393e8063 chore(deps): update github/codeql-action action (v4.32.4 → v4.32.6) (#484)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 02:49:32 +02:00
renovate[bot]
ed9f205433 chore(deps): update aquasecurity/trivy-action action (0.34.1 → 0.34.2) (#483)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 02:49:00 +02:00
Copilot
ae4ad9ec80 fix: harden workflow permissions with deny-all top-level and least-privilege job scopes (#482) 2026-03-06 02:44:56 +02:00
renovate[bot]
455267f892 chore(deps): update pre-commit hook bridgecrewio/checkov (3.2.506 → 3.2.507) (#487)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 02:41:33 +02:00
renovate[bot]
d1af04260d chore(deps)!: update docker/login-action (v3.7.0 → v4.0.0) (#477) 2026-03-05 22:41:05 +02:00
renovate[bot]
0921e373ce chore(deps)!: update docker/setup-buildx-action (v3.12.0 → v4.0.0) (#478) 2026-03-05 22:26:51 +02:00
renovate[bot]
6bbe5089d2 chore(deps)!: update docker/setup-qemu-action (v3.7.0 → v4.0.0) (#479) 2026-03-05 22:15:39 +02:00
renovate[bot]
7cf51e5364 chore(deps): lock file maintenance (#481) 2026-03-05 22:14:11 +02:00
renovate[bot]
72c6155089 chore(deps)!: update github/issue-metrics (v3.25.5 → v4.1.0) (#480) 2026-03-05 22:07:00 +02:00
renovate[bot]
6e8f2aae9d chore(deps): update pre-commit hook astral-sh/uv-pre-commit (0.10.5 → 0.10.7) (#475)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-02 17:22:01 +02:00
renovate[bot]
f15daec6dc chore(deps): update pre-commit hook astral-sh/ruff-pre-commit (v0.15.2 → v0.15.4) (#474)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-02 17:21:37 +02:00
renovate[bot]
66870c6d0c chore(deps): update oxsecurity/megalinter action (v9.3.0 → v9.4.0) (#476)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-02 17:20:54 +02:00
renovate[bot]
03eeb4c39f chore(deps): update astral-sh/setup-uv action (v7.3.0 → v7.3.1) (#473)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-02 03:04:57 +02:00
renovate[bot]
992b64a580 chore(deps)!: update hashicorp/setup-terraform (v3.1.2 → v4.0.0) (#471)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-02 02:35:56 +02:00
renovate[bot]
f114b11df1 chore(deps): lock file maintenance (#472)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-02 02:35:20 +02:00
bd59245cd7 fix(deps): replace step-security/retry and update action pins (#468)
* fix(deps): replace step-security/retry with nick-fields/retry

* chore(deps): update github action sha pins via pinact

* refactor: remove common-retry references from tests and validators

* chore: simplify description fallback and update action count

* docs: remove hardcoded test counts from memory and docs

Replace exact "769 tests" references with qualitative language
so these files don't go stale as test count grows.
2026-03-02 02:31:26 +02:00
dependabot[bot]
d919327c7e chore(deps): bump minimatch (#466) 2026-02-28 16:20:54 +02:00
renovate[bot]
8faacf8a1c chore(deps): update actions/dependency-review-action action (v4.8.2 → v4.8.3) (#461)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-24 20:09:57 +02:00
renovate[bot]
bbca76975e chore(deps): update pre-commit hook astral-sh/ruff-pre-commit (v0.15.1 → v0.15.2) (#462)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-24 20:06:53 +02:00
renovate[bot]
b75d237069 chore(deps): update pre-commit hook bridgecrewio/checkov (3.2.502 → 3.2.506) (#464)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-24 20:06:32 +02:00
renovate[bot]
7973e4945b chore(deps): update markdownlint-cli2 (0.20.0 → 0.21.0) (#465)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-24 20:06:10 +02:00
renovate[bot]
2ce9325ff9 chore(deps): update pre-commit hook astral-sh/uv-pre-commit (0.10.3 → 0.10.5) (#463)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-24 20:05:35 +02:00
renovate[bot]
37e80e5224 chore(deps): lock file maintenance (#457) 2026-02-23 21:43:14 +02:00
renovate[bot]
2555420036 chore(deps): update aquasecurity/trivy-action action (0.34.0 → 0.34.1) (#458)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-23 21:30:15 +02:00
renovate[bot]
2e4525cb96 chore(deps): update github/codeql-action action (v4.32.3 → v4.32.4) (#459)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-23 21:29:42 +02:00
renovate[bot]
a75db3a84a chore(deps): update actions/stale action (v10.1.1 → v10.2.0) (#460)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-23 21:29:07 +02:00
renovate[bot]
309f4460ec chore(deps): update pre-commit hook davidanson/markdownlint-cli2 (v0.20.0 → v0.21.0) (#456)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-17 23:20:07 +02:00
renovate[bot]
55897dfdeb chore(deps): update pre-commit hook rhysd/actionlint (v1.7.10 → v1.7.11) (#455)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-17 19:15:21 +02:00
renovate[bot]
88a0b89d8d chore(deps): update pre-commit hook astral-sh/ruff-pre-commit (v0.15.0 → v0.15.1) (#452)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-17 19:13:47 +02:00
renovate[bot]
0131cbfcf6 chore(deps): update docker/build-push-action action (v6.18.0 → v6.19.2) (#451)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-17 19:13:25 +02:00
renovate[bot]
f36f50e375 chore(deps): update aquasecurity/trivy-action action (0.33.1 → 0.34.0) (#450)
* chore(deps): update pre-commit hook rhysd/actionlint (v1.7.10 → v1.7.11)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update aquasecurity/trivy-action action (0.33.1 → 0.34.0)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

---------

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-17 19:11:17 +02:00
renovate[bot]
f0c398f47d chore(deps): update pre-commit hook bridgecrewio/checkov (3.2.500 → 3.2.502) (#454)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-17 19:00:40 +02:00
renovate[bot]
1eb60955d1 chore(deps): update pre-commit hook astral-sh/uv-pre-commit (0.10.0 → 0.10.3) (#453)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-17 18:59:38 +02:00
60 changed files with 695 additions and 377 deletions

View File

@@ -0,0 +1,30 @@
You review action.yml files against the repository's critical prevention rules.
Check each action.yml file for these violations:
1. All external action refs are SHA-pinned (not @main/@v1)
2. All internal action refs use `ivuorinen/actions/name@SHA` format
3. Shell scripts use `set -eu` (POSIX, not bash)
4. Steps with referenced outputs have `id:` fields
5. Tool availability checked before use (`command -v`)
6. Variables properly quoted (`"$var"`)
7. `$GITHUB_OUTPUT` uses `printf`, not `echo`
8. No nested `${{ }}` in quoted YAML strings
9. Token inputs use `${{ github.token }}` default
10. Fallbacks provided for tools not on all runners
Run `actionlint` on each file. Report violations with file path, line, and fix suggestion.
To find all action.yml files:
```bash
find . -name "action.yml" -not -path "./.git/*"
```
For each file, read it and check against all 10 rules. Then run:
```bash
actionlint <file>
```
Output a summary table of violations found, grouped by action.

View File

@@ -0,0 +1,33 @@
You review test coverage for GitHub Actions in this monorepo.
For each action:
1. Read the action.yml to understand inputs, outputs, and steps
2. Read the corresponding test files in `_tests/unit/<action-name>/`
3. Check if all inputs have validation tests
4. Check if error paths are tested (missing required inputs, invalid values)
5. Check if shell scripts have edge case tests (spaces in paths, empty strings, special chars)
6. Report coverage gaps with specific test suggestions
To find all actions and their tests:
```bash
ls -d */action.yml | sed 's|/action.yml||'
ls -d _tests/unit/*/
```
Compare the two lists to find actions without any tests.
For each action with tests, check coverage of:
- All required inputs validated
- All optional inputs with defaults tested
- Error conditions (missing inputs, invalid formats)
- Edge cases in shell logic (empty strings, special characters, spaces in paths)
- Output values verified
Output a coverage report with:
- Actions with no tests (critical)
- Actions with partial coverage (list missing test cases)
- Actions with good coverage (brief confirmation)

View File

@@ -0,0 +1,21 @@
#!/bin/sh
set -eu
# Read JSON input from stdin to get the file path
if ! command -v jq >/dev/null 2>&1; then
echo "Error: jq is required but not found" >&2
exit 1
fi
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.filePath // empty')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
case "$FILE_PATH" in
*/rules.yml)
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"rules.yml files are auto-generated. Run make update-validators instead."}}'
;;
esac

View File

@@ -0,0 +1,46 @@
#!/bin/sh
set -eu
# Read JSON input from stdin to get the file path
if ! command -v jq >/dev/null 2>&1; then
echo "Error: jq is required but not found" >&2
exit 1
fi
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.filePath // empty')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
case "$FILE_PATH" in
*/rules.yml)
# rules.yml should not be reached here (blocked by PreToolUse),
# but skip formatting just in case
exit 0
;;
*.py)
ruff format --quiet "$FILE_PATH" 2>/dev/null || true
ruff check --fix --quiet "$FILE_PATH" 2>/dev/null || true
;;
*.sh)
shfmt -w "$FILE_PATH" 2>/dev/null || true
shellcheck "$FILE_PATH" 2>&1 || true
;;
*.yml | *.yaml | *.json)
npx prettier --write "$FILE_PATH" 2>/dev/null || true
;;
*.md)
npx prettier --write "$FILE_PATH" 2>/dev/null || true
;;
esac
# Run actionlint on action.yml files
case "$FILE_PATH" in
*/action.yml)
if command -v actionlint >/dev/null 2>&1; then
actionlint "$FILE_PATH" 2>&1 || true
fi
;;
esac

26
.claude/settings.json Normal file
View File

@@ -0,0 +1,26 @@
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-rules-yml.sh"
}
]
}
],
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/post-edit-write.sh"
}
]
}
]
}
}

View File

@@ -0,0 +1,40 @@
---
name: check-pins
description: Verify all action references are properly SHA-pinned
disable-model-invocation: true
---
# Check SHA-Pinned Action References
## 1. Check version references
```bash
make check-version-refs
```
This verifies that all `ivuorinen/actions/*` references in `action.yml` files use SHA-pinned commits.
## 2. Check local references
```bash
make check-local-refs
```
This verifies that test workflows use `./action-name` format (local references are allowed in tests).
## 3. Interpret results
**Violations to fix:**
- `@main` or `@v*` references in `action.yml` files must be replaced with full SHA commits
- `./action-name` in `action.yml` (non-test) files must use `ivuorinen/actions/action-name@<SHA>`
- External actions must be pinned to SHA commits, not version tags
**How to get the SHA for pinning:**
```bash
# After pushing, get the SHA of the latest commit on the remote
git rev-parse origin/main
```
Use a SHA that exists on the remote. Local-only commits won't resolve when the action is used externally.

View File

@@ -0,0 +1,60 @@
---
name: new-action
description: Scaffold a new GitHub Action with all required files
disable-model-invocation: true
---
# Scaffold a New GitHub Action
## 1. Gather information
Ask the user for:
- **Action name** (kebab-case, e.g. `my-new-action`)
- **Description** (one line)
- **Category** (setup, linting, testing, build, publishing, repository, utility)
- **Inputs** (name, description, required, default for each)
- **What it does** (shell commands, composite steps, etc.)
## 2. Create directory and action.yml
Create `<action-name>/action.yml` following the existing action patterns:
- Use `composite` runs type
- Include `set -eu` in shell scripts (POSIX sh, not bash)
- Use `${{ github.token }}` for token defaults
- Pin all external action references to SHA commits
- Pin internal action references using `ivuorinen/actions/action-name@<SHA>`
- Add `id:` to steps whose outputs are referenced
## 3. Generate validation rules
```bash
make update-validators
```
This generates `<action-name>/rules.yml` from the action's inputs.
## 4. Generate test scaffolding
```bash
make generate-tests
```
## 5. Generate README
```bash
make docs
```
## 6. Run validation
```bash
make all
```
Fix any issues before considering the action complete.
## 7. Update repository overview
Remind the user to update the Serena memory `repository_overview` if they use Serena.

View File

@@ -0,0 +1,57 @@
---
name: release
description: Create a new CalVer release with validation checks
disable-model-invocation: true
---
# Release Workflow
Follow these steps to create a new CalVer release:
## 1. Pre-flight checks
Run the full validation pipeline:
```bash
make all
```
If any step fails, fix the issues before proceeding.
## 2. Check version references
Verify all action references are properly pinned:
```bash
make check-version-refs
make check-local-refs
```
## 3. Prepare the release
Run release preparation (updates version references):
```bash
make release-prep
```
Review the changes with `git diff`.
## 4. Confirm with user
Ask the user to confirm:
- The version number (defaults to `vYYYY.MM.DD` based on today's date)
- That all changes look correct
## 5. Create the release
```bash
make release VERSION=vYYYY.MM.DD
```
Replace `vYYYY.MM.DD` with the confirmed version.
## 6. Verify
Show the user the created tag and any output from the release process.

View File

@@ -0,0 +1,34 @@
---
name: test-action
description: Run tests for a specific GitHub Action by name
disable-model-invocation: true
---
# Test a Specific Action
## 1. Identify the action
Ask the user which action to test if not already specified.
List available actions if needed:
```bash
ls -d */action.yml | sed 's|/action.yml||'
```
## 2. Run tests
```bash
make test-action ACTION=<action-name>
```
## 3. Display results
Show the test output. If tests fail, read the relevant test files in `_tests/unit/<action-name>/` and the action's `action.yml` to help diagnose the issue.
## 4. Coverage (optional)
If the user wants coverage information:
```bash
make test-coverage
```

View File

@@ -0,0 +1,51 @@
---
name: validate
description: Run full validation pipeline (docs, format, lint, precommit)
disable-model-invocation: true
---
# Full Validation Pipeline
Run the complete validation pipeline:
```bash
make all
```
This runs in order: `install-tools` -> `update-validators` -> `docs` -> `update-catalog` -> `format` -> `lint` -> `precommit`
**Note:** `make test` must be run separately.
## If validation fails
### Formatting issues
```bash
make format
```
Then re-run `make all`.
### Linting issues
- **actionlint**: Check action.yml syntax, step IDs, expression usage
- **shellcheck**: POSIX compliance, quoting, variable usage
- **ruff**: Python style and errors
- **markdownlint**: Markdown formatting
- **prettier**: YAML/JSON/MD formatting
### Test failures
```bash
make test
```
Read the failing test output and fix the underlying action or test.
### Documentation drift
```bash
make docs
```
Regenerates READMEs from action.yml files.

View File

@@ -17,7 +17,7 @@ runs:
using: composite using: composite
steps: steps:
- name: Install uv - name: Install uv
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0 uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
with: with:
enable-cache: true enable-cache: true
@@ -31,7 +31,7 @@ runs:
run: uv sync --frozen run: uv sync --frozen
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with: with:
node-version: '24' node-version: '24'
cache: npm cache: npm

View File

@@ -17,10 +17,7 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
permissions: permissions: {}
contents: read
actions: read
pull-requests: read
jobs: jobs:
analyze: analyze:
@@ -29,6 +26,9 @@ jobs:
timeout-minutes: 30 timeout-minutes: 30
permissions: permissions:
contents: read
actions: read
pull-requests: read
security-events: write security-events: write
statuses: write statuses: write
issues: write issues: write

View File

@@ -23,25 +23,26 @@ on:
default: 'latest' default: 'latest'
type: string type: string
permissions: permissions: {}
contents: read
packages: write
jobs: jobs:
build-and-push: build-and-push:
name: Build and Push Testing Image name: Build and Push Testing Image
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 20 timeout-minutes: 20
permissions:
contents: read
packages: write
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@71cf2267d89c5cb81562390fa70a37fa40b1305e # v6-beta uses: actions/checkout@71cf2267d89c5cb81562390fa70a37fa40b1305e # v6-beta
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Log in to GitHub Container Registry - name: Log in to GitHub Container Registry
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
@@ -49,7 +50,7 @@ jobs:
- name: Extract metadata - name: Extract metadata
id: meta id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
with: with:
images: ghcr.io/${{ github.repository_owner }}/actions images: ghcr.io/${{ github.repository_owner }}/actions
tags: | tags: |
@@ -59,7 +60,7 @@ jobs:
type=raw,value=${{ github.event.inputs.tag }},enable=${{ github.event.inputs.tag != '' }} type=raw,value=${{ github.event.inputs.tag }},enable=${{ github.event.inputs.tag != '' }}
- name: Build and push Docker image - name: Build and push Docker image
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
with: with:
context: _tools/docker-testing-tools context: _tools/docker-testing-tools
file: _tools/docker-testing-tools/Dockerfile file: _tools/docker-testing-tools/Dockerfile

View File

@@ -13,17 +13,16 @@ on:
- cron: '30 1 * * 0' # Run at 1:30 AM UTC every Sunday - cron: '30 1 * * 0' # Run at 1:30 AM UTC every Sunday
merge_group: merge_group:
permissions: permissions: {}
actions: read
contents: read
jobs: jobs:
analyze: analyze:
name: Analyze (${{ matrix.language }}) name: Analyze (${{ matrix.language }})
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
security-events: write actions: read
contents: read contents: read
security-events: write
strategy: strategy:
fail-fast: false fail-fast: false

View File

@@ -1,17 +0,0 @@
---
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
name: 'Dependency Review'
on:
- pull_request
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@71cf2267d89c5cb81562390fa70a37fa40b1305e # v6-beta
- name: 'Dependency Review'
uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2

View File

@@ -5,8 +5,7 @@ on:
schedule: schedule:
- cron: '3 2 1 * *' - cron: '3 2 1 * *'
permissions: permissions: {}
contents: read
jobs: jobs:
build: build:
@@ -30,7 +29,7 @@ jobs:
echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV" echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV"
- name: Run issue-metrics tool - name: Run issue-metrics tool
uses: github/issue-metrics@67526e7bd8100b870f10b1c120780a8375777b43 # v3.25.5 uses: github/issue-metrics@41a7961f701cc64490f32e143af8ef479b93e87d # v4.1.0
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SEARCH_QUERY: 'repo:ivuorinen/actions is:issue created:${{ env.last_month }} -reason:"not planned"' SEARCH_QUERY: 'repo:ivuorinen/actions is:issue created:${{ env.last_month }} -reason:"not planned"'

View File

@@ -6,7 +6,7 @@ on:
schedule: schedule:
- cron: '0 21 * * *' # 00:00 at Europe/Helsinki - cron: '0 21 * * *' # 00:00 at Europe/Helsinki
permissions: read-all permissions: {}
jobs: jobs:
new-daily-release: new-daily-release:

View File

@@ -37,9 +37,7 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
permissions: permissions: {}
contents: read
packages: read # Required for private dependencies
jobs: jobs:
megalinter: megalinter:
@@ -74,7 +72,7 @@ jobs:
- name: Upload SARIF Report - name: Upload SARIF Report
if: always() && hashFiles('megalinter-reports/sarif/*.sarif') if: always() && hashFiles('megalinter-reports/sarif/*.sarif')
uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with: with:
sarif_file: megalinter-reports/sarif sarif_file: megalinter-reports/sarif
category: megalinter category: megalinter

View File

@@ -7,8 +7,7 @@ on:
tags: tags:
- 'v*' - 'v*'
permissions: permissions: {}
contents: read
jobs: jobs:
release: release:

View File

@@ -18,11 +18,7 @@ on:
- '**/*.yaml' - '**/*.yaml'
- '.github/workflows/**' - '.github/workflows/**'
permissions: permissions: {}
contents: read
pull-requests: write
issues: write
actions: read
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }} group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
@@ -32,6 +28,11 @@ jobs:
security-analysis: security-analysis:
name: Security Analysis name: Security Analysis
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
actions: read
steps: steps:
- name: Checkout PR - name: Checkout PR

View File

@@ -8,10 +8,7 @@ on:
workflow_call: workflow_call:
workflow_dispatch: workflow_dispatch:
permissions: permissions: {}
contents: read
packages: read
statuses: read
jobs: jobs:
stale: stale:
@@ -25,7 +22,7 @@ jobs:
steps: steps:
- name: 🚀 Run stale - name: 🚀 Run stale
uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1 uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 30 days-before-stale: 30

View File

@@ -22,7 +22,7 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
permissions: read-all permissions: {}
jobs: jobs:
labels: labels:
@@ -31,6 +31,7 @@ jobs:
timeout-minutes: 10 timeout-minutes: 10
permissions: permissions:
contents: read
issues: write issues: write
steps: steps:

View File

@@ -73,14 +73,14 @@ jobs:
if: always() if: always()
- name: Upload SARIF file - name: Upload SARIF file
uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
if: always() && hashFiles('_tests/reports/test-results.sarif') != '' if: always() && hashFiles('_tests/reports/test-results.sarif') != ''
with: with:
sarif_file: _tests/reports/test-results.sarif sarif_file: _tests/reports/test-results.sarif
category: github-actions-tests category: github-actions-tests
- name: Upload unit test results - name: Upload unit test results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
if: always() if: always()
with: with:
name: unit-test-results name: unit-test-results
@@ -133,7 +133,7 @@ jobs:
fi fi
- name: Upload integration test results - name: Upload integration test results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
if: always() && steps.check-integration-reports.outputs.reports-found == 'true' if: always() && steps.check-integration-reports.outputs.reports-found == 'true'
with: with:
name: integration-test-results name: integration-test-results
@@ -167,7 +167,7 @@ jobs:
run: make test-coverage run: make test-coverage
- name: Upload coverage report - name: Upload coverage report
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: coverage-report name: coverage-report
path: _tests/coverage/ path: _tests/coverage/
@@ -263,7 +263,7 @@ jobs:
steps: steps:
- name: Download test results - name: Download test results
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with: with:
pattern: '*-test-results' pattern: '*-test-results'
merge-multiple: true merge-multiple: true

View File

@@ -12,15 +12,16 @@ on:
required: false required: false
type: string type: string
permissions: permissions: {}
contents: write
pull-requests: write
issues: write
jobs: jobs:
check-and-update: check-and-update:
name: Check Version References name: Check Version References
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
steps: steps:
- name: Checkout Repository - name: Checkout Repository

View File

@@ -14,7 +14,7 @@ repos:
types: [markdown, python, yaml] types: [markdown, python, yaml]
files: ^(docs/.*|README\.md|CONTRIBUTING\.md|CHANGELOG\.md|.*\.py|.*\.ya?ml)$ files: ^(docs/.*|README\.md|CONTRIBUTING\.md|CHANGELOG\.md|.*\.py|.*\.ya?ml)$
- repo: https://github.com/astral-sh/uv-pre-commit - repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.10.0 rev: 0.10.8
hooks: hooks:
- id: uv-lock - id: uv-lock
- id: uv-sync - id: uv-sync
@@ -44,7 +44,7 @@ repos:
args: [--autofix, --no-sort-keys] args: [--autofix, --no-sort-keys]
- repo: https://github.com/DavidAnson/markdownlint-cli2 - repo: https://github.com/DavidAnson/markdownlint-cli2
rev: v0.20.0 rev: v0.21.0
hooks: hooks:
- id: markdownlint-cli2 - id: markdownlint-cli2
args: [--fix] args: [--fix]
@@ -55,7 +55,7 @@ repos:
- id: yamllint - id: yamllint
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.0 rev: v0.15.5
hooks: hooks:
# Run the linter with auto-fix # Run the linter with auto-fix
- id: ruff-check - id: ruff-check
@@ -78,13 +78,13 @@ repos:
exclude: '^_tests/.*\.sh$' exclude: '^_tests/.*\.sh$'
- repo: https://github.com/rhysd/actionlint - repo: https://github.com/rhysd/actionlint
rev: v1.7.10 rev: v1.7.11
hooks: hooks:
- id: actionlint - id: actionlint
args: ['-shellcheck='] args: ['-shellcheck=']
- repo: https://github.com/bridgecrewio/checkov.git - repo: https://github.com/bridgecrewio/checkov.git
rev: '3.2.500' rev: '3.2.507'
hooks: hooks:
- id: checkov - id: checkov
args: args:

View File

@@ -5,28 +5,28 @@
- **Path**: /Users/ivuorinen/Code/ivuorinen/actions - **Path**: /Users/ivuorinen/Code/ivuorinen/actions
- **Branch**: main - **Branch**: main
- **External Usage**: `ivuorinen/actions/<action-name>@main` - **External Usage**: `ivuorinen/actions/<action-name>@main`
- **Total Actions**: 44 self-contained actions - **Total Actions**: 43 self-contained actions
- **Dogfooding**: Workflows use local actions (pr-lint, codeql-analysis, security-scan) - **Dogfooding**: Workflows use local actions (pr-lint, codeql-analysis, security-scan)
## Structure ## Structure
```text ```text
/ /
├── <action-dirs>/ # 44 self-contained actions ├── <action-dirs>/ # 43 self-contained actions
│ ├── action.yml # Action definition │ ├── action.yml # Action definition
│ ├── README.md # Auto-generated │ ├── README.md # Auto-generated
│ └── CustomValidator.py # Optional validator │ └── CustomValidator.py # Optional validator
├── validate-inputs/ # Centralized validation ├── validate-inputs/ # Centralized validation
│ ├── validators/ # 9 specialized modules │ ├── validators/ # 9 specialized modules
│ ├── scripts/ # Rule/test generators │ ├── scripts/ # Rule/test generators
│ └── tests/ # 769 pytest tests │ └── tests/ # pytest tests
├── _tests/ # ShellSpec framework ├── _tests/ # ShellSpec framework
├── _tools/ # Development utilities ├── _tools/ # Development utilities
├── .github/workflows/ # CI/CD workflows ├── .github/workflows/ # CI/CD workflows
└── Makefile # Build automation └── Makefile # Build automation
``` ```
## Action Categories (44 total) ## Action Categories (43 total)
**Setup (7)**: node-setup, set-git-config, php-version-detect, python-version-detect, python-version-detect-v2, go-version-detect, dotnet-version-detect **Setup (7)**: node-setup, set-git-config, php-version-detect, python-version-detect, python-version-detect-v2, go-version-detect, dotnet-version-detect
@@ -40,7 +40,7 @@
**Testing (3)**: php-tests, php-laravel-phpunit, php-composer **Testing (3)**: php-tests, php-laravel-phpunit, php-composer
**Repository (9)**: github-release, release-monthly, sync-labels, stale, compress-images, common-cache, common-file-check, common-retry, codeql-analysis **Repository (8)**: github-release, release-monthly, sync-labels, stale, compress-images, common-cache, common-file-check, codeql-analysis
**Utilities (3)**: version-file-parser, version-validator, validate-inputs **Utilities (3)**: version-file-parser, version-validator, validate-inputs
@@ -77,12 +77,12 @@ make test # All tests (pytest + ShellSpec)
## Testing Framework ## Testing Framework
- **ShellSpec**: GitHub Actions and shell scripts - **ShellSpec**: GitHub Actions and shell scripts
- **pytest**: Python validators (769 tests, 100% pass rate) - **pytest**: Python validators (100% pass rate)
- **Test Generator**: Automatic scaffolding for new actions - **Test Generator**: Automatic scaffolding for new actions
## Current Status ## Current Status
- ✅ All tests passing (769/769) - ✅ All tests passing
- ✅ Zero linting issues - ✅ Zero linting issues
- ✅ Modular validator architecture - ✅ Modular validator architecture
- ✅ Convention-based validation - ✅ Convention-based validation

View File

@@ -2,7 +2,7 @@
## Status: PRODUCTION READY ✅ ## Status: PRODUCTION READY ✅
- 769 tests passing (100%) - All tests passing (100%)
- Zero linting issues - Zero linting issues
- Modular architecture complete - Modular architecture complete
@@ -60,7 +60,7 @@ validate-inputs/
├── scripts/ ├── scripts/
│ ├── update-validators.py # Rule generator │ ├── update-validators.py # Rule generator
│ └── generate-tests.py # Test generator │ └── generate-tests.py # Test generator
└── tests/ # 769 pytest tests └── tests/ # pytest tests
<action>/CustomValidator.py # Action-specific validators <action>/CustomValidator.py # Action-specific validators
``` ```

View File

@@ -25,12 +25,22 @@
### Folders ### Folders
- `.serena/` Internal config (do not edit) - `.serena/` Internal config (do not edit)
- `.claude/hooks/` Claude Code hook scripts (auto-format, lint, block rules.yml edits)
- `.claude/skills/` Claude Code skills (`/release`, `/test-action`, `/new-action`, `/validate`, `/check-pins`)
- `.claude/agents/` Claude Code subagents (action-validator, test-coverage-reviewer)
- `.github/` Workflows/templates - `.github/` Workflows/templates
- `_tests/` ShellSpec tests - `_tests/` ShellSpec tests
- `_tools/` Helper tools - `_tools/` Helper tools
- `validate-inputs/` Python validation system + tests - `validate-inputs/` Python validation system + tests
- `*/rules.yml` Auto-generated validation rules - `*/rules.yml` Auto-generated validation rules
### Claude Code Hooks
**Auto-formatting**: PostToolUse hooks auto-format files on Edit/Write (ruff for .py, shfmt for .sh, prettier for .yml/.yaml/.json/.md, actionlint for action.yml)
**Blocked edits**: PreToolUse hook blocks direct edits to `rules.yml` (auto-generated, use `make update-validators`)
**Hook schema**: `matcher` is a regex string matching tool names (e.g. `"Edit|Write"`), not an object. File filtering done in hook scripts via stdin JSON (`jq -r '.tool_input.file_path'`)
**Reference**: `$CLAUDE_PROJECT_DIR` for project-relative paths in hook commands
### Memory System ### Memory System
**Location**: `.serena/memories/` (9 consolidated memories for context) **Location**: `.serena/memories/` (9 consolidated memories for context)

View File

@@ -210,7 +210,7 @@ bump-major-version: ## Replace one major version with another (usage: make bump-
@sh _tools/bump-major-version.sh "$(OLD)" "$(NEW)" @sh _tools/bump-major-version.sh "$(OLD)" "$(NEW)"
@echo "$(GREEN)✅ Major version bumped$(RESET)" @echo "$(GREEN)✅ Major version bumped$(RESET)"
check-version-refs: ## List all current SHA-pinned action references check-version-refs: ## Verify all action references are SHA-pinned
@echo "$(BLUE)🔍 Checking action references...$(RESET)" @echo "$(BLUE)🔍 Checking action references...$(RESET)"
@sh _tools/check-version-refs.sh @sh _tools/check-version-refs.sh

View File

@@ -183,9 +183,6 @@ validate_input_python "docker-build" "tag" "v1.0.0" # success
validate_input_python "pre-commit" "config-file" "config.yml" # success validate_input_python "pre-commit" "config-file" "config.yml" # success
validate_input_python "pre-commit" "config-file" "../etc/pass" # failure validate_input_python "pre-commit" "config-file" "../etc/pass" # failure
# Injection detection
validate_input_python "common-retry" "command" "echo test" # success
validate_input_python "common-retry" "command" "rm -rf /; " # failure
``` ```
### Helper Functions from spec_helper.sh ### Helper Functions from spec_helper.sh
@@ -482,11 +479,6 @@ End
✅ **Always include**: ✅ **Always include**:
```bash ```bash
It "rejects command injection"
When call validate_input_python "common-retry" "command" "rm -rf /; "
The status should be failure
End
It "rejects path traversal" It "rejects path traversal"
When call validate_input_python "pre-commit" "config-file" "../etc/passwd" When call validate_input_python "pre-commit" "config-file" "../etc/passwd"
The status should be failure The status should be failure

View File

@@ -264,7 +264,7 @@ def get_input_property(action_file: str, input_name: str, property_check: str) -
if property_check == "description": if property_check == "description":
description = input_data.get("description", "") description = input_data.get("description", "")
return description if description else "no-description" return description or "no-description"
if property_check == "all_optional": if property_check == "all_optional":
# Check if all inputs are optional (none are required) # Check if all inputs are optional (none are required)

View File

@@ -337,7 +337,7 @@ class ValidationCore:
""" """
if not value: # Empty values are generally allowed, except for specific cases if not value: # Empty values are generally allowed, except for specific cases
# Some inputs should not be empty even if they're optional # Some inputs should not be empty even if they're optional
if action_name == "php-composer" and input_name in ["composer-version"]: if action_name == "php-composer" and input_name == "composer-version":
return False, f"Empty {input_name} is not allowed" return False, f"Empty {input_name} is not allowed"
return None, "" return None, ""
@@ -552,7 +552,7 @@ class ActionFileParser:
def _get_description_property(input_data: dict) -> str: def _get_description_property(input_data: dict) -> str:
"""Get the description property.""" """Get the description property."""
description = input_data.get("description", "") description = input_data.get("description", "")
return description if description else "no-description" return description or "no-description"
@staticmethod @staticmethod
def _get_all_optional_property(inputs: dict) -> str: def _get_all_optional_property(inputs: dict) -> str:

View File

@@ -92,9 +92,6 @@ setup_default_inputs() {
"go-build" | "go-lint") "go-build" | "go-lint")
[[ "$input_name" != "go-version" ]] && export INPUT_GO_VERSION="1.21" [[ "$input_name" != "go-version" ]] && export INPUT_GO_VERSION="1.21"
;; ;;
"common-retry")
[[ "$input_name" != "command" ]] && export INPUT_COMMAND="echo test"
;;
"dotnet-version-detect") "dotnet-version-detect")
[[ "$input_name" != "default-version" ]] && export INPUT_DEFAULT_VERSION="8.0" [[ "$input_name" != "default-version" ]] && export INPUT_DEFAULT_VERSION="8.0"
;; ;;
@@ -154,9 +151,6 @@ cleanup_default_inputs() {
"go-build" | "go-lint") "go-build" | "go-lint")
[[ "$input_name" != "go-version" ]] && unset INPUT_GO_VERSION [[ "$input_name" != "go-version" ]] && unset INPUT_GO_VERSION
;; ;;
"common-retry")
[[ "$input_name" != "command" ]] && unset INPUT_COMMAND
;;
"dotnet-version-detect") "dotnet-version-detect")
[[ "$input_name" != "default-version" ]] && unset INPUT_DEFAULT_VERSION [[ "$input_name" != "default-version" ]] && unset INPUT_DEFAULT_VERSION
;; ;;
@@ -239,12 +233,6 @@ shellspec_mock_action_run() {
"common-file-check") "common-file-check")
echo "found=true" >>"$GITHUB_OUTPUT" echo "found=true" >>"$GITHUB_OUTPUT"
;; ;;
"common-retry")
echo "success=true" >>"$GITHUB_OUTPUT"
echo "attempts=1" >>"$GITHUB_OUTPUT"
echo "exit-code=0" >>"$GITHUB_OUTPUT"
echo "duration=5" >>"$GITHUB_OUTPUT"
;;
"compress-images") "compress-images")
echo "images_compressed=true" >>"$GITHUB_OUTPUT" echo "images_compressed=true" >>"$GITHUB_OUTPUT"
printf "compression_report=## Compression Results\n- 3 images compressed\n- 25%% size reduction\n" >>"$GITHUB_OUTPUT" printf "compression_report=## Compression Results\n- 3 images compressed\n- 25%% size reduction\n" >>"$GITHUB_OUTPUT"

View File

@@ -23,19 +23,43 @@ for tool in find grep sed printf sort cut tr wc; do
fi fi
done done
# --- Validation pass: detect non-SHA-pinned references ---
violations_file=$(safe_mktemp)
trap 'rm -f "$violations_file"' EXIT
find . -maxdepth 2 -name "action.yml" -path "*/action.yml" \
! -path "./_*" ! -path "./.github/*" \
-exec grep -nE '^\s+uses:\s+ivuorinen/actions/' {} /dev/null \; \
>"$violations_file"
violations_found=false
while IFS= read -r match; do
if ! printf '%s\n' "$match" | grep -qE '@[0-9a-f]{40}'; then
if [ "$violations_found" = false ]; then
msg_error "Non-SHA-pinned action references found:"
violations_found=true
fi
printf ' %s\n' "$match" >&2
fi
done <"$violations_file"
if [ "$violations_found" = true ]; then
rm -f "$violations_file"
exit 1
fi
rm -f "$violations_file"
printf '%b' "${BLUE}Current SHA-pinned action references:${NC}\n" printf '%b' "${BLUE}Current SHA-pinned action references:${NC}\n"
printf '\n' printf '\n'
# Create temp files for processing # Create temp files for processing
temp_file=$(safe_mktemp) temp_file=$(safe_mktemp)
trap 'rm -f "$temp_file"' EXIT
temp_input=$(safe_mktemp) temp_input=$(safe_mktemp)
trap 'rm -f "$temp_file" "$temp_input"' EXIT trap 'rm -f "$temp_file" "$temp_input"' EXIT
# Find all action references and collect SHA|action pairs # Find all action references and collect SHA|action pairs
# Use input redirection to avoid subshell issues with pipeline # Use input redirection to avoid subshell issues with pipeline
find . -maxdepth 2 -name "action.yml" -path "*/action.yml" ! -path "./_*" ! -path "./.github/*" -exec grep -h "uses: ivuorinen/actions/" {} \; > "$temp_input" find . -maxdepth 2 -name "action.yml" -path "*/action.yml" ! -path "./_*" ! -path "./.github/*" -exec grep -h "uses: ivuorinen/actions/" {} \; >"$temp_input"
while IFS= read -r line; do while IFS= read -r line; do
# Extract action name and SHA using sed # Extract action name and SHA using sed
@@ -43,9 +67,9 @@ while IFS= read -r line; do
sha=$(echo "$line" | sed -n 's|.*@\([a-f0-9]\{40\}\).*|\1|p') sha=$(echo "$line" | sed -n 's|.*@\([a-f0-9]\{40\}\).*|\1|p')
if [ -n "$action" ] && [ -n "$sha" ]; then if [ -n "$action" ] && [ -n "$sha" ]; then
printf '%s\n' "$sha|$action" >> "$temp_file" printf '%s\n' "$sha|$action" >>"$temp_file"
fi fi
done < "$temp_input" done <"$temp_input"
# Check if we found any references # Check if we found any references
if [ ! -s "$temp_file" ]; then if [ ! -s "$temp_file" ]; then
@@ -54,7 +78,7 @@ if [ ! -s "$temp_file" ]; then
fi fi
# Sort by SHA and group # Sort by SHA and group
sort "$temp_file" | uniq > "${temp_file}.sorted" sort "$temp_file" | uniq >"${temp_file}.sorted"
mv "${temp_file}.sorted" "$temp_file" mv "${temp_file}.sorted" "$temp_file"
# Count unique SHAs # Count unique SHAs
@@ -95,7 +119,7 @@ while IFS='|' read -r sha action; do
# Add to current SHA group # Add to current SHA group
actions_list="$actions_list, $action" actions_list="$actions_list, $action"
fi fi
done < "$temp_file" done <"$temp_file"
# Print last SHA group # Print last SHA group
if [ -n "$current_sha" ]; then if [ -n "$current_sha" ]; then

View File

@@ -83,7 +83,7 @@ runs:
- name: Install ansible-lint - name: Install ansible-lint
id: install-ansible-lint id: install-ansible-lint
if: steps.check-files.outputs.files_found == 'true' if: steps.check-files.outputs.files_found == 'true'
uses: step-security/retry@e1d59ce1f574b32f0915e3a8df055cfe9f99be5d # v3.0.4 uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2
with: with:
timeout_minutes: 5 timeout_minutes: 5
max_attempts: ${{ inputs.max-retries }} max_attempts: ${{ inputs.max-retries }}
@@ -130,6 +130,6 @@ runs:
- name: Upload SARIF Report - name: Upload SARIF Report
if: steps.check-files.outputs.files_found == 'true' if: steps.check-files.outputs.files_found == 'true'
uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with: with:
sarif_file: ansible-lint.sarif sarif_file: ansible-lint.sarif

View File

@@ -181,7 +181,7 @@ runs:
echo "Detected package manager: $package_manager" echo "Detected package manager: $package_manager"
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with: with:
node-version: '24' node-version: '24'
@@ -212,7 +212,7 @@ runs:
- name: Setup Bun - name: Setup Bun
if: steps.detect-pm.outputs.package-manager == 'bun' if: steps.detect-pm.outputs.package-manager == 'bun'
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2 uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2.1.3
with: with:
bun-version: latest bun-version: latest
@@ -331,7 +331,7 @@ runs:
- name: Upload SARIF Report - name: Upload SARIF Report
if: inputs.mode == 'check' && always() if: inputs.mode == 'check' && always()
uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with: with:
sarif_file: biome-report.sarif sarif_file: biome-report.sarif

View File

@@ -186,7 +186,7 @@ runs:
echo "Using build mode: $build_mode" echo "Using build mode: $build_mode"
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with: with:
languages: ${{ inputs.language }} languages: ${{ inputs.language }}
queries: ${{ inputs.queries }} queries: ${{ inputs.queries }}
@@ -199,12 +199,12 @@ runs:
threads: ${{ inputs.threads }} threads: ${{ inputs.threads }}
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 uses: github/codeql-action/autobuild@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
if: ${{ steps.set-build-mode.outputs.build-mode == 'autobuild' }} if: ${{ steps.set-build-mode.outputs.build-mode == 'autobuild' }}
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
id: analysis id: analysis
uses: github/codeql-action/analyze@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with: with:
category: ${{ steps.set-category.outputs.category }} category: ${{ steps.set-category.outputs.category }}
upload: ${{ inputs.upload-results }} upload: ${{ inputs.upload-results }}

View File

@@ -148,14 +148,14 @@ runs:
echo "Final detected .NET version: $detected_version" >&2 echo "Final detected .NET version: $detected_version" >&2
- name: Setup .NET SDK - name: Setup .NET SDK
uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
with: with:
dotnet-version: ${{ steps.detect-dotnet-version.outputs.detected-version }} dotnet-version: ${{ steps.detect-dotnet-version.outputs.detected-version }}
cache: true cache: true
cache-dependency-path: '**/packages.lock.json' cache-dependency-path: '**/packages.lock.json'
- name: Restore Dependencies - name: Restore Dependencies
uses: step-security/retry@e1d59ce1f574b32f0915e3a8df055cfe9f99be5d # v3.0.4 uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2
with: with:
timeout_minutes: 10 timeout_minutes: 10
max_attempts: ${{ inputs.max-retries }} max_attempts: ${{ inputs.max-retries }}
@@ -203,7 +203,7 @@ runs:
- name: Upload Test Results - name: Upload Test Results
if: always() if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: csharp-test-results name: csharp-test-results
path: | path: |

View File

@@ -164,7 +164,7 @@ runs:
echo "Final detected .NET version: $detected_version" >&2 echo "Final detected .NET version: $detected_version" >&2
- name: Setup .NET SDK - name: Setup .NET SDK
uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
with: with:
dotnet-version: ${{ steps.detect-dotnet-version.outputs.detected-version }} dotnet-version: ${{ steps.detect-dotnet-version.outputs.detected-version }}
cache: true cache: true
@@ -206,6 +206,6 @@ runs:
fi fi
- name: Upload SARIF Report - name: Upload SARIF Report
uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with: with:
sarif_file: dotnet-format.sarif sarif_file: dotnet-format.sarif

View File

@@ -162,14 +162,14 @@ runs:
echo "Final detected .NET version: $detected_version" >&2 echo "Final detected .NET version: $detected_version" >&2
- name: Setup .NET SDK - name: Setup .NET SDK
uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
with: with:
dotnet-version: ${{ inputs.dotnet-version || steps.detect-dotnet-version.outputs.detected-version }} dotnet-version: ${{ inputs.dotnet-version || steps.detect-dotnet-version.outputs.detected-version }}
cache: true cache: true
cache-dependency-path: '**/packages.lock.json' cache-dependency-path: '**/packages.lock.json'
- name: Restore Dependencies - name: Restore Dependencies
uses: step-security/retry@e1d59ce1f574b32f0915e3a8df055cfe9f99be5d # v3.0.4 uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2
with: with:
timeout_minutes: 10 timeout_minutes: 10
max_attempts: ${{ inputs.max-retries }} max_attempts: ${{ inputs.max-retries }}

View File

@@ -169,13 +169,13 @@ runs:
fi fi
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
with: with:
platforms: ${{ inputs.architectures }} platforms: ${{ inputs.architectures }}
- name: Set up Docker Buildx - name: Set up Docker Buildx
id: buildx id: buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
with: with:
version: ${{ inputs.buildx-version }} version: ${{ inputs.buildx-version }}
platforms: ${{ inputs.architectures }} platforms: ${{ inputs.architectures }}
@@ -321,7 +321,7 @@ runs:
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
if: ${{ inputs.push == 'true' }} if: ${{ inputs.push == 'true' }}
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
@@ -536,7 +536,7 @@ runs:
- name: Scan Image for Vulnerabilities - name: Scan Image for Vulnerabilities
id: scan id: scan
if: inputs.scan-image == 'true' && inputs.dry-run != 'true' if: inputs.scan-image == 'true' && inputs.dry-run != 'true'
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1 uses: aquasecurity/trivy-action@97e0b3872f55f89b95b2f65b3dbab56962816478 # 0.34.2
with: with:
scan-type: 'image' scan-type: 'image'
image-ref: ${{ steps.image-name.outputs.name }}:${{ inputs.tag }} image-ref: ${{ steps.image-name.outputs.name }}:${{ inputs.tag }}

View File

@@ -202,7 +202,7 @@ runs:
printf '%s\n' "Input validation completed successfully" printf '%s\n' "Input validation completed successfully"
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Determine Image Names and Tags - name: Determine Image Names and Tags
id: meta id: meta
@@ -265,14 +265,14 @@ runs:
- name: Login to Docker Hub - name: Login to Docker Hub
if: inputs.registry == 'dockerhub' || inputs.registry == 'both' if: inputs.registry == 'dockerhub' || inputs.registry == 'both'
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with: with:
username: ${{ inputs.dockerhub-username }} username: ${{ inputs.dockerhub-username }}
password: ${{ inputs.dockerhub-token }} password: ${{ inputs.dockerhub-token }}
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
if: inputs.registry == 'github' || inputs.registry == 'both' if: inputs.registry == 'github' || inputs.registry == 'both'
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
@@ -280,7 +280,7 @@ runs:
- name: Build and Push Docker Image - name: Build and Push Docker Image
id: build id: build
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
with: with:
context: ${{ inputs.context }} context: ${{ inputs.context }}
file: ${{ inputs.dockerfile }} file: ${{ inputs.dockerfile }}

View File

@@ -288,7 +288,7 @@ runs:
echo "Detected package manager: $package_manager" echo "Detected package manager: $package_manager"
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with: with:
node-version: '24' node-version: '24'
@@ -319,7 +319,7 @@ runs:
- name: Setup Bun - name: Setup Bun
if: steps.detect-pm.outputs.package-manager == 'bun' if: steps.detect-pm.outputs.package-manager == 'bun'
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2 uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2.1.3
with: with:
bun-version: latest bun-version: latest
@@ -457,7 +457,7 @@ runs:
- name: Upload SARIF Report - name: Upload SARIF Report
if: inputs.mode == 'check' && inputs.report-format == 'sarif' && always() if: inputs.mode == 'check' && inputs.report-format == 'sarif' && always()
uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with: with:
sarif_file: ${{ inputs.working-directory }}/eslint-results.sarif sarif_file: ${{ inputs.working-directory }}/eslint-results.sarif

View File

@@ -159,13 +159,13 @@ runs:
echo "Final detected Go version: $detected_version" >&2 echo "Final detected Go version: $detected_version" >&2
- name: Setup Go - name: Setup Go
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with: with:
go-version: ${{ steps.detect-go-version.outputs.detected-version }} go-version: ${{ steps.detect-go-version.outputs.detected-version }}
cache: true cache: true
- name: Download Dependencies - name: Download Dependencies
uses: step-security/retry@e1d59ce1f574b32f0915e3a8df055cfe9f99be5d # v3.0.4 uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2
with: with:
timeout_minutes: 10 timeout_minutes: 10
max_attempts: ${{ inputs.max-retries }} max_attempts: ${{ inputs.max-retries }}
@@ -253,7 +253,7 @@ runs:
- name: Upload Build Artifacts - name: Upload Build Artifacts
if: always() if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: go-build-artifacts name: go-build-artifacts
path: | path: |

View File

@@ -205,7 +205,7 @@ runs:
validate_linter_list "$DISABLE_LINTERS" "disable-linters" validate_linter_list "$DISABLE_LINTERS" "disable-linters"
- name: Setup Go - name: Setup Go
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with: with:
go-version: ${{ inputs.go-version }} go-version: ${{ inputs.go-version }}
cache: true cache: true
@@ -414,7 +414,7 @@ runs:
- name: Upload Lint Results - name: Upload Lint Results
if: always() && inputs.report-format == 'sarif' if: always() && inputs.report-format == 'sarif'
uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with: with:
sarif_file: ${{ inputs.working-directory }}/reports/golangci-lint.sarif sarif_file: ${{ inputs.working-directory }}/reports/golangci-lint.sarif
category: golangci-lint category: golangci-lint

View File

@@ -121,7 +121,7 @@ runs:
echo "Detected package manager: $package_manager" echo "Detected package manager: $package_manager"
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with: with:
node-version: '24' node-version: '24'
@@ -152,7 +152,7 @@ runs:
- name: Setup Bun - name: Setup Bun
if: steps.detect-pm.outputs.package-manager == 'bun' if: steps.detect-pm.outputs.package-manager == 'bun'
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2 uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2.1.3
with: with:
bun-version: latest bun-version: latest

173
package-lock.json generated
View File

@@ -13,7 +13,7 @@
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"markdown-table": "^3.0.3", "markdown-table": "^3.0.3",
"markdown-table-formatter": "^1.6.0", "markdown-table-formatter": "^1.6.0",
"markdownlint-cli2": "^0.20.0", "markdownlint-cli2": "^0.21.0",
"prettier": "^3.3.3", "prettier": "^3.3.3",
"yaml-lint": "^1.7.0" "yaml-lint": "^1.7.0"
}, },
@@ -21,16 +21,6 @@
"node": ">=18.0.0" "node": ">=18.0.0"
} }
}, },
"node_modules/@isaacs/cliui": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz",
"integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==",
"dev": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"
}
},
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -185,29 +175,26 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/balanced-match": { "node_modules/balanced-match": {
"version": "4.0.2", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
"integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==", "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": {
"jackspeak": "^4.2.3"
},
"engines": { "engines": {
"node": "20 || >=22" "node": "18 || 20 || >=22"
} }
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "5.0.2", "version": "5.0.4",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz",
"integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^4.0.2" "balanced-match": "^4.0.2"
}, },
"engines": { "engines": {
"node": "20 || >=22" "node": "18 || 20 || >=22"
} }
}, },
"node_modules/braces": { "node_modules/braces": {
@@ -435,16 +422,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/dir-glob/node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
"version": "8.0.0", "version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -546,9 +523,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/fs-extra": { "node_modules/fs-extra": {
"version": "11.3.3", "version": "11.3.4",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz",
"integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -578,9 +555,9 @@
} }
}, },
"node_modules/get-east-asian-width": { "node_modules/get-east-asian-width": {
"version": "1.4.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz",
"integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -591,18 +568,18 @@
} }
}, },
"node_modules/glob": { "node_modules/glob": {
"version": "13.0.3", "version": "13.0.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-13.0.3.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz",
"integrity": "sha512-/g3B0mC+4x724v1TgtBlBtt2hPi/EWptsIAmXUx9Z2rvBYleQcsrmaOzd5LyL50jf/Soi83ZDJmw2+XqvH/EeA==", "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==",
"dev": true, "dev": true,
"license": "BlueOak-1.0.0", "license": "BlueOak-1.0.0",
"dependencies": { "dependencies": {
"minimatch": "^10.2.0", "minimatch": "^10.2.2",
"minipass": "^7.1.2", "minipass": "^7.1.3",
"path-scurry": "^2.0.0" "path-scurry": "^2.0.2"
}, },
"engines": { "engines": {
"node": "20 || >=22" "node": "18 || 20 || >=22"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
@@ -622,18 +599,18 @@
} }
}, },
"node_modules/globby": { "node_modules/globby": {
"version": "15.0.0", "version": "16.1.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-15.0.0.tgz", "resolved": "https://registry.npmjs.org/globby/-/globby-16.1.0.tgz",
"integrity": "sha512-oB4vkQGqlMl682wL1IlWd02tXCbquGWM4voPEI85QmNKCaw8zGTm1f1rubFgkg3Eli2PtKlFgrnmUqasbQWlkw==", "integrity": "sha512-+A4Hq7m7Ze592k9gZRy4gJ27DrXRNnC1vPjxTt1qQxEY8RxagBkBxivkCwg7FxSTG0iLLEMaUx13oOr0R2/qcQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@sindresorhus/merge-streams": "^4.0.0", "@sindresorhus/merge-streams": "^4.0.0",
"fast-glob": "^3.3.3", "fast-glob": "^3.3.3",
"ignore": "^7.0.5", "ignore": "^7.0.5",
"path-type": "^6.0.0", "is-path-inside": "^4.0.0",
"slash": "^5.1.0", "slash": "^5.1.0",
"unicorn-magic": "^0.3.0" "unicorn-magic": "^0.4.0"
}, },
"engines": { "engines": {
"node": ">=20" "node": ">=20"
@@ -789,20 +766,17 @@
"node": ">=0.12.0" "node": ">=0.12.0"
} }
}, },
"node_modules/jackspeak": { "node_modules/is-path-inside": {
"version": "4.2.3", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz",
"integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==", "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==",
"dev": true, "dev": true,
"license": "BlueOak-1.0.0", "license": "MIT",
"dependencies": {
"@isaacs/cliui": "^9.0.0"
},
"engines": { "engines": {
"node": "20 || >=22" "node": ">=12"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/js-yaml": { "node_modules/js-yaml": {
@@ -839,9 +813,9 @@
} }
}, },
"node_modules/katex": { "node_modules/katex": {
"version": "0.16.28", "version": "0.16.35",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.28.tgz", "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.35.tgz",
"integrity": "sha512-YHzO7721WbmAL6Ov1uzN/l5mY5WWWhJBSW+jq4tkfZfsxmo1hu6frS0EOswvjBUnWE6NtjEs48SFn5CQESRLZg==", "integrity": "sha512-S0+riEvy1CK4VKse1ivMff8gmabe/prY7sKB3njjhyoLLsNFDQYtKNgXrbWUggGDCJBz7Fctl5i8fLCESHXzSg==",
"dev": true, "dev": true,
"funding": [ "funding": [
"https://opencollective.com/katex", "https://opencollective.com/katex",
@@ -900,9 +874,9 @@
} }
}, },
"node_modules/markdown-it": { "node_modules/markdown-it": {
"version": "14.1.0", "version": "14.1.1",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz",
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -987,16 +961,16 @@
} }
}, },
"node_modules/markdownlint-cli2": { "node_modules/markdownlint-cli2": {
"version": "0.20.0", "version": "0.21.0",
"resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.20.0.tgz", "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.21.0.tgz",
"integrity": "sha512-esPk+8Qvx/f0bzI7YelUeZp+jCtFOk3KjZ7s9iBQZ6HlymSXoTtWGiIRZP05/9Oy2ehIoIjenVwndxGtxOIJYQ==", "integrity": "sha512-DzzmbqfMW3EzHsunP66x556oZDzjcdjjlL2bHG4PubwnL58ZPAfz07px4GqteZkoCGnBYi779Y2mg7+vgNCwbw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"globby": "15.0.0", "globby": "16.1.0",
"js-yaml": "4.1.1", "js-yaml": "4.1.1",
"jsonc-parser": "3.3.1", "jsonc-parser": "3.3.1",
"markdown-it": "14.1.0", "markdown-it": "14.1.1",
"markdownlint": "0.40.0", "markdownlint": "0.40.0",
"markdownlint-cli2-formatter-default": "0.0.6", "markdownlint-cli2-formatter-default": "0.0.6",
"micromatch": "4.0.8" "micromatch": "4.0.8"
@@ -1592,27 +1566,27 @@
} }
}, },
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "10.2.0", "version": "10.2.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.0.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
"integrity": "sha512-ugkC31VaVg9cF0DFVoADH12k6061zNZkZON+aX8AWsR9GhPcErkcMBceb6znR8wLERM2AkkOxy2nWRLpT9Jq5w==", "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
"dev": true, "dev": true,
"license": "BlueOak-1.0.0", "license": "BlueOak-1.0.0",
"dependencies": { "dependencies": {
"brace-expansion": "^5.0.2" "brace-expansion": "^5.0.2"
}, },
"engines": { "engines": {
"node": "20 || >=22" "node": "18 || 20 || >=22"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/minipass": { "node_modules/minipass": {
"version": "7.1.2", "version": "7.1.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
"dev": true, "dev": true,
"license": "ISC", "license": "BlueOak-1.0.0",
"engines": { "engines": {
"node": ">=16 || 14 >=14.17" "node": ">=16 || 14 >=14.17"
} }
@@ -1768,9 +1742,9 @@
} }
}, },
"node_modules/path-scurry": { "node_modules/path-scurry": {
"version": "2.0.1", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz",
"integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==",
"dev": true, "dev": true,
"license": "BlueOak-1.0.0", "license": "BlueOak-1.0.0",
"dependencies": { "dependencies": {
@@ -1778,23 +1752,20 @@
"minipass": "^7.1.2" "minipass": "^7.1.2"
}, },
"engines": { "engines": {
"node": "20 || >=22" "node": "18 || 20 || >=22"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/path-type": { "node_modules/path-type": {
"version": "6.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18" "node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/picomatch": { "node_modules/picomatch": {
@@ -1941,9 +1912,9 @@
} }
}, },
"node_modules/replace-in-file/node_modules/minimatch": { "node_modules/replace-in-file/node_modules/minimatch": {
"version": "5.1.6", "version": "5.1.9",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
"dev": true, "dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
@@ -2063,13 +2034,13 @@
} }
}, },
"node_modules/strip-ansi": { "node_modules/strip-ansi": {
"version": "7.1.2", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
"integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ansi-regex": "^6.0.1" "ansi-regex": "^6.2.2"
}, },
"engines": { "engines": {
"node": ">=12" "node": ">=12"
@@ -2125,13 +2096,13 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/unicorn-magic": { "node_modules/unicorn-magic": {
"version": "0.3.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.0.tgz",
"integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", "integrity": "sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18" "node": ">=20"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"

View File

@@ -24,7 +24,7 @@
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"markdown-table": "^3.0.3", "markdown-table": "^3.0.3",
"markdown-table-formatter": "^1.6.0", "markdown-table-formatter": "^1.6.0",
"markdownlint-cli2": "^0.20.0", "markdownlint-cli2": "^0.21.0",
"prettier": "^3.3.3", "prettier": "^3.3.3",
"yaml-lint": "^1.7.0" "yaml-lint": "^1.7.0"
}, },

View File

@@ -376,7 +376,7 @@ runs:
composer clear-cache composer clear-cache
- name: Install Composer Dependencies - name: Install Composer Dependencies
uses: step-security/retry@e1d59ce1f574b32f0915e3a8df055cfe9f99be5d # v3.0.4 uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2
with: with:
timeout_minutes: 10 timeout_minutes: 10
max_attempts: ${{ inputs.max-retries }} max_attempts: ${{ inputs.max-retries }}

View File

@@ -118,7 +118,7 @@ runs:
- name: Setup Node.js - name: Setup Node.js
if: steps.detect-node.outputs.found == 'true' if: steps.detect-node.outputs.found == 'true'
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with: with:
node-version: '24' node-version: '24'
@@ -156,7 +156,7 @@ runs:
- name: Setup Bun - name: Setup Bun
if: steps.detect-node.outputs.found == 'true' && steps.detect-pm.outputs.package-manager == 'bun' if: steps.detect-node.outputs.found == 'true' && steps.detect-pm.outputs.package-manager == 'bun'
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2 uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2.1.3
with: with:
bun-version: latest bun-version: latest
@@ -621,18 +621,45 @@ runs:
- name: Setup Go - name: Setup Go
if: steps.detect-go.outputs.found == 'true' if: steps.detect-go.outputs.found == 'true'
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with: with:
go-version: ${{ steps.go-version.outputs.detected-version }} go-version: ${{ steps.go-version.outputs.detected-version }}
cache: true cache: true
# ╭──────────────────────────────────────────────────────────╮
# │ Dependency Review │
# ╰──────────────────────────────────────────────────────────╯
- name: Check Repository Visibility
id: repo-visibility
if: github.event_name == 'pull_request'
shell: sh
run: |
set -eu
is_private=$(jq -r '.repository.private' "$GITHUB_EVENT_PATH")
if [ "$is_private" = "false" ]; then
printf '%s\n' "is-public=true" >> "$GITHUB_OUTPUT"
fi
- name: Dependency Review
id: dependency-review
continue-on-error: true
if: >-
steps.repo-visibility.outputs.is-public == 'true'
&& github.event_name == 'pull_request'
uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0
with:
comment-summary-in-pr: always
fail-on-severity: critical
# ╭──────────────────────────────────────────────────────────╮ # ╭──────────────────────────────────────────────────────────╮
# │ MegaLinter │ # │ MegaLinter │
# ╰──────────────────────────────────────────────────────────╯ # ╰──────────────────────────────────────────────────────────╯
- name: MegaLinter - name: MegaLinter
# You can override MegaLinter flavor used to have faster performances # You can override MegaLinter flavor used to have faster performances
# More info at https://megalinter.io/latest/flavors/ # More info at https://megalinter.io/latest/flavors/
uses: oxsecurity/megalinter/flavors/cupcake@42bb470545e359597e7f12156947c436e4e3fb9a # v9.3.0 uses: oxsecurity/megalinter/flavors/cupcake@8fbdead70d1409964ab3d5afa885e18ee85388bb # v9.4.0
id: ml id: ml
# All available variables are described in documentation # All available variables are described in documentation
@@ -677,10 +704,17 @@ runs:
# Upload MegaLinter artifacts # Upload MegaLinter artifacts
- name: Archive production artifacts - name: Archive production artifacts
if: success() || failure() if: success() || failure()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: MegaLinter reports name: MegaLinter reports
include-hidden-files: 'true' include-hidden-files: 'true'
path: | path: |
megalinter-reports megalinter-reports
mega-linter.log mega-linter.log
- name: Fail if dependency review found critical issues
if: steps.dependency-review.outcome == 'failure'
shell: sh
run: |
printf '%s\n' "Dependency review found critical issues" >&2
exit 1

View File

@@ -274,7 +274,7 @@ runs:
echo "Detected package manager: $package_manager" echo "Detected package manager: $package_manager"
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with: with:
node-version: '24' node-version: '24'
@@ -305,7 +305,7 @@ runs:
- name: Setup Bun - name: Setup Bun
if: steps.detect-pm.outputs.package-manager == 'bun' if: steps.detect-pm.outputs.package-manager == 'bun'
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2 uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2.1.3
with: with:
bun-version: latest bun-version: latest

View File

@@ -370,7 +370,7 @@ runs:
- name: Upload SARIF Report - name: Upload SARIF Report
if: steps.check-files.outputs.result == 'found' if: steps.check-files.outputs.result == 'found'
uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with: with:
sarif_file: ${{ inputs.working-directory }}/reports/flake8.sarif sarif_file: ${{ inputs.working-directory }}/reports/flake8.sarif
category: 'python-lint' category: 'python-lint'

View File

@@ -99,7 +99,7 @@ runs:
- name: Run actionlint - name: Run actionlint
if: steps.check-configs.outputs.run_actionlint == 'true' if: steps.check-configs.outputs.run_actionlint == 'true'
uses: raven-actions/actionlint@e01d1ea33dd6a5ed517d95b4c0c357560ac6f518 # v2.1.1 uses: raven-actions/actionlint@205b530c5d9fa8f44ae9ed59f341a0db994aa6f8 # v2.1.2
with: with:
cache: true cache: true
fail-on-error: true fail-on-error: true
@@ -161,21 +161,21 @@ runs:
- name: Upload Trivy results - name: Upload Trivy results
if: steps.verify-sarif.outputs.has_trivy == 'true' if: steps.verify-sarif.outputs.has_trivy == 'true'
uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with: with:
sarif_file: 'trivy-results.sarif' sarif_file: 'trivy-results.sarif'
category: 'trivy' category: 'trivy'
- name: Upload Gitleaks results - name: Upload Gitleaks results
if: steps.verify-sarif.outputs.has_gitleaks == 'true' if: steps.verify-sarif.outputs.has_gitleaks == 'true'
uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with: with:
sarif_file: 'gitleaks-report.sarif' sarif_file: 'gitleaks-report.sarif'
category: 'gitleaks' category: 'gitleaks'
- name: Archive security reports - name: Archive security reports
if: always() if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: security-reports-${{ github.run_id }} name: security-reports-${{ github.run_id }}
path: | path: |

View File

@@ -52,7 +52,7 @@ runs:
- name: 🚀 Run stale - name: 🚀 Run stale
id: stale id: stale
uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1 uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
with: with:
repo-token: ${{ inputs.token || github.token }} repo-token: ${{ inputs.token || github.token }}
days-before-stale: ${{ inputs.days-before-stale }} days-before-stale: ${{ inputs.days-before-stale }}

View File

@@ -128,7 +128,7 @@ runs:
- name: Setup Terraform - name: Setup Terraform
if: steps.check-files.outputs.found == 'true' if: steps.check-files.outputs.found == 'true'
uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2 uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 # v4.0.0
with: with:
terraform_version: ${{ inputs.terraform-version }} terraform_version: ${{ inputs.terraform-version }}
terraform_wrapper: false terraform_wrapper: false
@@ -256,7 +256,7 @@ runs:
- name: Upload SARIF Report - name: Upload SARIF Report
if: steps.check-files.outputs.found == 'true' && inputs.format == 'sarif' if: steps.check-files.outputs.found == 'true' && inputs.format == 'sarif'
uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with: with:
sarif_file: ${{ env.VALIDATED_WORKING_DIR }}/reports/tflint.sarif sarif_file: ${{ env.VALIDATED_WORKING_DIR }}/reports/tflint.sarif
category: terraform-lint category: terraform-lint

38
uv.lock generated
View File

@@ -299,27 +299,27 @@ wheels = [
[[package]] [[package]]
name = "ruff" name = "ruff"
version = "0.15.1" version = "0.15.5"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/04/dc/4e6ac71b511b141cf626357a3946679abeba4cf67bc7cc5a17920f31e10d/ruff-0.15.1.tar.gz", hash = "sha256:c590fe13fb57c97141ae975c03a1aedb3d3156030cabd740d6ff0b0d601e203f", size = 4540855, upload-time = "2026-02-12T23:09:09.998Z" } sdist = { url = "https://files.pythonhosted.org/packages/77/9b/840e0039e65fcf12758adf684d2289024d6140cde9268cc59887dc55189c/ruff-0.15.5.tar.gz", hash = "sha256:7c3601d3b6d76dce18c5c824fc8d06f4eef33d6df0c21ec7799510cde0f159a2", size = 4574214, upload-time = "2026-03-05T20:06:34.946Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/23/bf/e6e4324238c17f9d9120a9d60aa99a7daaa21204c07fcd84e2ef03bb5fd1/ruff-0.15.1-py3-none-linux_armv6l.whl", hash = "sha256:b101ed7cf4615bda6ffe65bdb59f964e9f4a0d3f85cbf0e54f0ab76d7b90228a", size = 10367819, upload-time = "2026-02-12T23:09:03.598Z" }, { url = "https://files.pythonhosted.org/packages/47/20/5369c3ce21588c708bcbe517a8fbe1a8dfdb5dfd5137e14790b1da71612c/ruff-0.15.5-py3-none-linux_armv6l.whl", hash = "sha256:4ae44c42281f42e3b06b988e442d344a5b9b72450ff3c892e30d11b29a96a57c", size = 10478185, upload-time = "2026-03-05T20:06:29.093Z" },
{ url = "https://files.pythonhosted.org/packages/b3/ea/c8f89d32e7912269d38c58f3649e453ac32c528f93bb7f4219258be2e7ed/ruff-0.15.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:939c995e9277e63ea632cc8d3fae17aa758526f49a9a850d2e7e758bfef46602", size = 10798618, upload-time = "2026-02-12T23:09:22.928Z" }, { url = "https://files.pythonhosted.org/packages/44/ed/e81dd668547da281e5dce710cf0bc60193f8d3d43833e8241d006720e42b/ruff-0.15.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6edd3792d408ebcf61adabc01822da687579a1a023f297618ac27a5b51ef0080", size = 10859201, upload-time = "2026-03-05T20:06:32.632Z" },
{ url = "https://files.pythonhosted.org/packages/5e/0f/1d0d88bc862624247d82c20c10d4c0f6bb2f346559d8af281674cf327f15/ruff-0.15.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1d83466455fdefe60b8d9c8df81d3c1bbb2115cede53549d3b522ce2bc703899", size = 10148518, upload-time = "2026-02-12T23:08:58.339Z" }, { url = "https://files.pythonhosted.org/packages/c4/8f/533075f00aaf19b07c5cd6aa6e5d89424b06b3b3f4583bfa9c640a079059/ruff-0.15.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:89f463f7c8205a9f8dea9d658d59eff49db05f88f89cc3047fb1a02d9f344010", size = 10184752, upload-time = "2026-03-05T20:06:40.312Z" },
{ url = "https://files.pythonhosted.org/packages/f5/c8/291c49cefaa4a9248e986256df2ade7add79388fe179e0691be06fae6f37/ruff-0.15.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9457e3c3291024866222b96108ab2d8265b477e5b1534c7ddb1810904858d16", size = 10518811, upload-time = "2026-02-12T23:09:31.865Z" }, { url = "https://files.pythonhosted.org/packages/66/0e/ba49e2c3fa0395b3152bad634c7432f7edfc509c133b8f4529053ff024fb/ruff-0.15.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba786a8295c6574c1116704cf0b9e6563de3432ac888d8f83685654fe528fd65", size = 10534857, upload-time = "2026-03-05T20:06:19.581Z" },
{ url = "https://files.pythonhosted.org/packages/c3/1a/f5707440e5ae43ffa5365cac8bbb91e9665f4a883f560893829cf16a606b/ruff-0.15.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:92c92b003e9d4f7fbd33b1867bb15a1b785b1735069108dfc23821ba045b29bc", size = 10196169, upload-time = "2026-02-12T23:09:17.306Z" }, { url = "https://files.pythonhosted.org/packages/59/71/39234440f27a226475a0659561adb0d784b4d247dfe7f43ffc12dd02e288/ruff-0.15.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fd4b801e57955fe9f02b31d20375ab3a5c4415f2e5105b79fb94cf2642c91440", size = 10309120, upload-time = "2026-03-05T20:06:00.435Z" },
{ url = "https://files.pythonhosted.org/packages/2a/ff/26ddc8c4da04c8fd3ee65a89c9fb99eaa5c30394269d424461467be2271f/ruff-0.15.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fe5c41ab43e3a06778844c586251eb5a510f67125427625f9eb2b9526535779", size = 10990491, upload-time = "2026-02-12T23:09:25.503Z" }, { url = "https://files.pythonhosted.org/packages/f5/87/4140aa86a93df032156982b726f4952aaec4a883bb98cb6ef73c347da253/ruff-0.15.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391f7c73388f3d8c11b794dbbc2959a5b5afe66642c142a6effa90b45f6f5204", size = 11047428, upload-time = "2026-03-05T20:05:51.867Z" },
{ url = "https://files.pythonhosted.org/packages/fc/00/50920cb385b89413f7cdb4bb9bc8fc59c1b0f30028d8bccc294189a54955/ruff-0.15.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66a6dd6df4d80dc382c6484f8ce1bcceb55c32e9f27a8b94c32f6c7331bf14fb", size = 11843280, upload-time = "2026-02-12T23:09:19.88Z" }, { url = "https://files.pythonhosted.org/packages/5a/f7/4953e7e3287676f78fbe85e3a0ca414c5ca81237b7575bdadc00229ac240/ruff-0.15.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dc18f30302e379fe1e998548b0f5e9f4dff907f52f73ad6da419ea9c19d66c8", size = 11914251, upload-time = "2026-03-05T20:06:22.887Z" },
{ url = "https://files.pythonhosted.org/packages/5d/6d/2f5cad8380caf5632a15460c323ae326f1e1a2b5b90a6ee7519017a017ca/ruff-0.15.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a4a42cbb8af0bda9bcd7606b064d7c0bc311a88d141d02f78920be6acb5aa83", size = 11274336, upload-time = "2026-02-12T23:09:14.907Z" }, { url = "https://files.pythonhosted.org/packages/77/46/0f7c865c10cf896ccf5a939c3e84e1cfaeed608ff5249584799a74d33835/ruff-0.15.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc6e7f90087e2d27f98dc34ed1b3ab7c8f0d273cc5431415454e22c0bd2a681", size = 11333801, upload-time = "2026-03-05T20:05:57.168Z" },
{ url = "https://files.pythonhosted.org/packages/a3/1d/5f56cae1d6c40b8a318513599b35ea4b075d7dc1cd1d04449578c29d1d75/ruff-0.15.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ab064052c31dddada35079901592dfba2e05f5b1e43af3954aafcbc1096a5b2", size = 11137288, upload-time = "2026-02-12T23:09:07.475Z" }, { url = "https://files.pythonhosted.org/packages/d3/01/a10fe54b653061585e655f5286c2662ebddb68831ed3eaebfb0eb08c0a16/ruff-0.15.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1cb7169f53c1ddb06e71a9aebd7e98fc0fea936b39afb36d8e86d36ecc2636a", size = 11206821, upload-time = "2026-03-05T20:06:03.441Z" },
{ url = "https://files.pythonhosted.org/packages/cd/20/6f8d7d8f768c93b0382b33b9306b3b999918816da46537d5a61635514635/ruff-0.15.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5631c940fe9fe91f817a4c2ea4e81f47bee3ca4aa646134a24374f3c19ad9454", size = 11070681, upload-time = "2026-02-12T23:08:55.43Z" }, { url = "https://files.pythonhosted.org/packages/7a/0d/2132ceaf20c5e8699aa83da2706ecb5c5dcdf78b453f77edca7fb70f8a93/ruff-0.15.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9b037924500a31ee17389b5c8c4d88874cc6ea8e42f12e9c61a3d754ff72f1ca", size = 11133326, upload-time = "2026-03-05T20:06:25.655Z" },
{ url = "https://files.pythonhosted.org/packages/9a/67/d640ac76069f64cdea59dba02af2e00b1fa30e2103c7f8d049c0cff4cafd/ruff-0.15.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:68138a4ba184b4691ccdc39f7795c66b3c68160c586519e7e8444cf5a53e1b4c", size = 10486401, upload-time = "2026-02-12T23:09:27.927Z" }, { url = "https://files.pythonhosted.org/packages/72/cb/2e5259a7eb2a0f87c08c0fe5bf5825a1e4b90883a52685524596bfc93072/ruff-0.15.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:65bb414e5b4eadd95a8c1e4804f6772bbe8995889f203a01f77ddf2d790929dd", size = 10510820, upload-time = "2026-03-05T20:06:37.79Z" },
{ url = "https://files.pythonhosted.org/packages/65/3d/e1429f64a3ff89297497916b88c32a5cc88eeca7e9c787072d0e7f1d3e1e/ruff-0.15.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:518f9af03bfc33c03bdb4cb63fabc935341bb7f54af500f92ac309ecfbba6330", size = 10197452, upload-time = "2026-02-12T23:09:12.147Z" }, { url = "https://files.pythonhosted.org/packages/ff/20/b67ce78f9e6c59ffbdb5b4503d0090e749b5f2d31b599b554698a80d861c/ruff-0.15.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d20aa469ae3b57033519c559e9bc9cd9e782842e39be05b50e852c7c981fa01d", size = 10302395, upload-time = "2026-03-05T20:05:54.504Z" },
{ url = "https://files.pythonhosted.org/packages/78/83/e2c3bade17dad63bf1e1c2ffaf11490603b760be149e1419b07049b36ef2/ruff-0.15.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:da79f4d6a826caaea95de0237a67e33b81e6ec2e25fc7e1993a4015dffca7c61", size = 10693900, upload-time = "2026-02-12T23:09:34.418Z" }, { url = "https://files.pythonhosted.org/packages/5f/e5/719f1acccd31b720d477751558ed74e9c88134adcc377e5e886af89d3072/ruff-0.15.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:15388dd28c9161cdb8eda68993533acc870aa4e646a0a277aa166de9ad5a8752", size = 10754069, upload-time = "2026-03-05T20:06:06.422Z" },
{ url = "https://files.pythonhosted.org/packages/a1/27/fdc0e11a813e6338e0706e8b39bb7a1d61ea5b36873b351acee7e524a72a/ruff-0.15.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3dd86dccb83cd7d4dcfac303ffc277e6048600dfc22e38158afa208e8bf94a1f", size = 11227302, upload-time = "2026-02-12T23:09:36.536Z" }, { url = "https://files.pythonhosted.org/packages/c3/9c/d1db14469e32d98f3ca27079dbd30b7b44dbb5317d06ab36718dee3baf03/ruff-0.15.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b30da330cbd03bed0c21420b6b953158f60c74c54c5f4c1dabbdf3a57bf355d2", size = 11304315, upload-time = "2026-03-05T20:06:10.867Z" },
{ url = "https://files.pythonhosted.org/packages/f6/58/ac864a75067dcbd3b95be5ab4eb2b601d7fbc3d3d736a27e391a4f92a5c1/ruff-0.15.1-py3-none-win32.whl", hash = "sha256:660975d9cb49b5d5278b12b03bb9951d554543a90b74ed5d366b20e2c57c2098", size = 10462555, upload-time = "2026-02-12T23:09:29.899Z" }, { url = "https://files.pythonhosted.org/packages/28/3a/950367aee7c69027f4f422059227b290ed780366b6aecee5de5039d50fa8/ruff-0.15.5-py3-none-win32.whl", hash = "sha256:732e5ee1f98ba5b3679029989a06ca39a950cced52143a0ea82a2102cb592b74", size = 10551676, upload-time = "2026-03-05T20:06:13.705Z" },
{ url = "https://files.pythonhosted.org/packages/e0/5e/d4ccc8a27ecdb78116feac4935dfc39d1304536f4296168f91ed3ec00cd2/ruff-0.15.1-py3-none-win_amd64.whl", hash = "sha256:c820fef9dd5d4172a6570e5721704a96c6679b80cf7be41659ed439653f62336", size = 11599956, upload-time = "2026-02-12T23:09:01.157Z" }, { url = "https://files.pythonhosted.org/packages/b8/00/bf077a505b4e649bdd3c47ff8ec967735ce2544c8e4a43aba42ee9bf935d/ruff-0.15.5-py3-none-win_amd64.whl", hash = "sha256:821d41c5fa9e19117616c35eaa3f4b75046ec76c65e7ae20a333e9a8696bc7fe", size = 11678972, upload-time = "2026-03-05T20:06:45.379Z" },
{ url = "https://files.pythonhosted.org/packages/2a/07/5bda6a85b220c64c65686bc85bd0bbb23b29c62b3a9f9433fa55f17cda93/ruff-0.15.1-py3-none-win_arm64.whl", hash = "sha256:5ff7d5f0f88567850f45081fac8f4ec212be8d0b963e385c3f7d0d2eb4899416", size = 10874604, upload-time = "2026-02-12T23:09:05.515Z" }, { url = "https://files.pythonhosted.org/packages/fe/4e/cd76eca6db6115604b7626668e891c9dd03330384082e33662fb0f113614/ruff-0.15.5-py3-none-win_arm64.whl", hash = "sha256:b498d1c60d2fe5c10c45ec3f698901065772730b411f164ae270bb6bfcc4740b", size = 10965572, upload-time = "2026-03-05T20:06:16.984Z" },
] ]
[[package]] [[package]]

View File

@@ -332,7 +332,7 @@ class CustomValidator(BaseValidator):
## Quality Metrics ## Quality Metrics
- **Test Coverage**: 100% (769 tests) - **Test Coverage**: 100%
- **Validators**: 9 specialized + unlimited custom - **Validators**: 9 specialized + unlimited custom
- **Performance**: < 10ms typical validation time - **Performance**: < 10ms typical validation time
- **Zero Dependencies**: Uses only Python stdlib + PyYAML - **Zero Dependencies**: Uses only Python stdlib + PyYAML

View File

@@ -310,10 +310,6 @@ class ValidationRuleGenerator:
"common-file-check": { "common-file-check": {
"file-pattern": "file_path", "file-pattern": "file_path",
}, },
"common-retry": {
"backoff-strategy": "backoff_strategy",
"shell": "shell_type",
},
"docker-publish": { "docker-publish": {
"registry": "registry_enum", "registry": "registry_enum",
"cache-mode": "cache_mode", "cache-mode": "cache_mode",

View File

@@ -1,74 +0,0 @@
"""Tests for common-retry custom validator.
Generated by generate-tests.py - Do not edit manually.
"""
# pylint: disable=invalid-name # Test file name matches action name
import sys
from pathlib import Path
# Add action directory to path to import custom validator
action_path = Path(__file__).parent.parent.parent / "common-retry"
sys.path.insert(0, str(action_path))
# pylint: disable=wrong-import-position
from CustomValidator import CustomValidator
class TestCustomCommonRetryValidator:
"""Test cases for common-retry custom validator."""
def setup_method(self):
"""Set up test fixtures."""
self.validator = CustomValidator("common-retry")
def teardown_method(self):
"""Clean up after tests."""
self.validator.clear_errors()
def test_validate_inputs_valid(self):
"""Test validation with valid inputs."""
# TODO: Add specific valid inputs for common-retry
inputs = {}
result = self.validator.validate_inputs(inputs)
# Adjust assertion based on required inputs
assert isinstance(result, bool)
def test_validate_inputs_invalid(self):
"""Test validation with invalid inputs."""
# TODO: Add specific invalid inputs for common-retry
inputs = {"invalid_key": "invalid_value"}
result = self.validator.validate_inputs(inputs)
# Custom validators may have specific validation rules
assert isinstance(result, bool)
def test_required_inputs(self):
"""Test required inputs detection."""
required = self.validator.get_required_inputs()
assert isinstance(required, list)
# TODO: Assert specific required inputs for common-retry
def test_validation_rules(self):
"""Test validation rules."""
rules = self.validator.get_validation_rules()
assert isinstance(rules, dict)
# TODO: Assert specific validation rules for common-retry
def test_github_expressions(self):
"""Test GitHub expression handling."""
inputs = {
"test_input": "${{ github.token }}",
}
result = self.validator.validate_inputs(inputs)
assert isinstance(result, bool)
# GitHub expressions should generally be accepted
def test_error_propagation(self):
"""Test error propagation from sub-validators."""
# Custom validators often use sub-validators
# Test that errors are properly propagated
inputs = {"test": "value"}
self.validator.validate_inputs(inputs)
# Check error handling
if self.validator.has_errors():
assert len(self.validator.errors) > 0

View File

@@ -631,27 +631,27 @@ wheels = [
[[package]] [[package]]
name = "ruff" name = "ruff"
version = "0.15.1" version = "0.15.5"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/04/dc/4e6ac71b511b141cf626357a3946679abeba4cf67bc7cc5a17920f31e10d/ruff-0.15.1.tar.gz", hash = "sha256:c590fe13fb57c97141ae975c03a1aedb3d3156030cabd740d6ff0b0d601e203f", size = 4540855, upload-time = "2026-02-12T23:09:09.998Z" } sdist = { url = "https://files.pythonhosted.org/packages/77/9b/840e0039e65fcf12758adf684d2289024d6140cde9268cc59887dc55189c/ruff-0.15.5.tar.gz", hash = "sha256:7c3601d3b6d76dce18c5c824fc8d06f4eef33d6df0c21ec7799510cde0f159a2", size = 4574214, upload-time = "2026-03-05T20:06:34.946Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/23/bf/e6e4324238c17f9d9120a9d60aa99a7daaa21204c07fcd84e2ef03bb5fd1/ruff-0.15.1-py3-none-linux_armv6l.whl", hash = "sha256:b101ed7cf4615bda6ffe65bdb59f964e9f4a0d3f85cbf0e54f0ab76d7b90228a", size = 10367819, upload-time = "2026-02-12T23:09:03.598Z" }, { url = "https://files.pythonhosted.org/packages/47/20/5369c3ce21588c708bcbe517a8fbe1a8dfdb5dfd5137e14790b1da71612c/ruff-0.15.5-py3-none-linux_armv6l.whl", hash = "sha256:4ae44c42281f42e3b06b988e442d344a5b9b72450ff3c892e30d11b29a96a57c", size = 10478185, upload-time = "2026-03-05T20:06:29.093Z" },
{ url = "https://files.pythonhosted.org/packages/b3/ea/c8f89d32e7912269d38c58f3649e453ac32c528f93bb7f4219258be2e7ed/ruff-0.15.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:939c995e9277e63ea632cc8d3fae17aa758526f49a9a850d2e7e758bfef46602", size = 10798618, upload-time = "2026-02-12T23:09:22.928Z" }, { url = "https://files.pythonhosted.org/packages/44/ed/e81dd668547da281e5dce710cf0bc60193f8d3d43833e8241d006720e42b/ruff-0.15.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6edd3792d408ebcf61adabc01822da687579a1a023f297618ac27a5b51ef0080", size = 10859201, upload-time = "2026-03-05T20:06:32.632Z" },
{ url = "https://files.pythonhosted.org/packages/5e/0f/1d0d88bc862624247d82c20c10d4c0f6bb2f346559d8af281674cf327f15/ruff-0.15.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1d83466455fdefe60b8d9c8df81d3c1bbb2115cede53549d3b522ce2bc703899", size = 10148518, upload-time = "2026-02-12T23:08:58.339Z" }, { url = "https://files.pythonhosted.org/packages/c4/8f/533075f00aaf19b07c5cd6aa6e5d89424b06b3b3f4583bfa9c640a079059/ruff-0.15.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:89f463f7c8205a9f8dea9d658d59eff49db05f88f89cc3047fb1a02d9f344010", size = 10184752, upload-time = "2026-03-05T20:06:40.312Z" },
{ url = "https://files.pythonhosted.org/packages/f5/c8/291c49cefaa4a9248e986256df2ade7add79388fe179e0691be06fae6f37/ruff-0.15.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9457e3c3291024866222b96108ab2d8265b477e5b1534c7ddb1810904858d16", size = 10518811, upload-time = "2026-02-12T23:09:31.865Z" }, { url = "https://files.pythonhosted.org/packages/66/0e/ba49e2c3fa0395b3152bad634c7432f7edfc509c133b8f4529053ff024fb/ruff-0.15.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba786a8295c6574c1116704cf0b9e6563de3432ac888d8f83685654fe528fd65", size = 10534857, upload-time = "2026-03-05T20:06:19.581Z" },
{ url = "https://files.pythonhosted.org/packages/c3/1a/f5707440e5ae43ffa5365cac8bbb91e9665f4a883f560893829cf16a606b/ruff-0.15.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:92c92b003e9d4f7fbd33b1867bb15a1b785b1735069108dfc23821ba045b29bc", size = 10196169, upload-time = "2026-02-12T23:09:17.306Z" }, { url = "https://files.pythonhosted.org/packages/59/71/39234440f27a226475a0659561adb0d784b4d247dfe7f43ffc12dd02e288/ruff-0.15.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fd4b801e57955fe9f02b31d20375ab3a5c4415f2e5105b79fb94cf2642c91440", size = 10309120, upload-time = "2026-03-05T20:06:00.435Z" },
{ url = "https://files.pythonhosted.org/packages/2a/ff/26ddc8c4da04c8fd3ee65a89c9fb99eaa5c30394269d424461467be2271f/ruff-0.15.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fe5c41ab43e3a06778844c586251eb5a510f67125427625f9eb2b9526535779", size = 10990491, upload-time = "2026-02-12T23:09:25.503Z" }, { url = "https://files.pythonhosted.org/packages/f5/87/4140aa86a93df032156982b726f4952aaec4a883bb98cb6ef73c347da253/ruff-0.15.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391f7c73388f3d8c11b794dbbc2959a5b5afe66642c142a6effa90b45f6f5204", size = 11047428, upload-time = "2026-03-05T20:05:51.867Z" },
{ url = "https://files.pythonhosted.org/packages/fc/00/50920cb385b89413f7cdb4bb9bc8fc59c1b0f30028d8bccc294189a54955/ruff-0.15.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66a6dd6df4d80dc382c6484f8ce1bcceb55c32e9f27a8b94c32f6c7331bf14fb", size = 11843280, upload-time = "2026-02-12T23:09:19.88Z" }, { url = "https://files.pythonhosted.org/packages/5a/f7/4953e7e3287676f78fbe85e3a0ca414c5ca81237b7575bdadc00229ac240/ruff-0.15.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dc18f30302e379fe1e998548b0f5e9f4dff907f52f73ad6da419ea9c19d66c8", size = 11914251, upload-time = "2026-03-05T20:06:22.887Z" },
{ url = "https://files.pythonhosted.org/packages/5d/6d/2f5cad8380caf5632a15460c323ae326f1e1a2b5b90a6ee7519017a017ca/ruff-0.15.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a4a42cbb8af0bda9bcd7606b064d7c0bc311a88d141d02f78920be6acb5aa83", size = 11274336, upload-time = "2026-02-12T23:09:14.907Z" }, { url = "https://files.pythonhosted.org/packages/77/46/0f7c865c10cf896ccf5a939c3e84e1cfaeed608ff5249584799a74d33835/ruff-0.15.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc6e7f90087e2d27f98dc34ed1b3ab7c8f0d273cc5431415454e22c0bd2a681", size = 11333801, upload-time = "2026-03-05T20:05:57.168Z" },
{ url = "https://files.pythonhosted.org/packages/a3/1d/5f56cae1d6c40b8a318513599b35ea4b075d7dc1cd1d04449578c29d1d75/ruff-0.15.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ab064052c31dddada35079901592dfba2e05f5b1e43af3954aafcbc1096a5b2", size = 11137288, upload-time = "2026-02-12T23:09:07.475Z" }, { url = "https://files.pythonhosted.org/packages/d3/01/a10fe54b653061585e655f5286c2662ebddb68831ed3eaebfb0eb08c0a16/ruff-0.15.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1cb7169f53c1ddb06e71a9aebd7e98fc0fea936b39afb36d8e86d36ecc2636a", size = 11206821, upload-time = "2026-03-05T20:06:03.441Z" },
{ url = "https://files.pythonhosted.org/packages/cd/20/6f8d7d8f768c93b0382b33b9306b3b999918816da46537d5a61635514635/ruff-0.15.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5631c940fe9fe91f817a4c2ea4e81f47bee3ca4aa646134a24374f3c19ad9454", size = 11070681, upload-time = "2026-02-12T23:08:55.43Z" }, { url = "https://files.pythonhosted.org/packages/7a/0d/2132ceaf20c5e8699aa83da2706ecb5c5dcdf78b453f77edca7fb70f8a93/ruff-0.15.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9b037924500a31ee17389b5c8c4d88874cc6ea8e42f12e9c61a3d754ff72f1ca", size = 11133326, upload-time = "2026-03-05T20:06:25.655Z" },
{ url = "https://files.pythonhosted.org/packages/9a/67/d640ac76069f64cdea59dba02af2e00b1fa30e2103c7f8d049c0cff4cafd/ruff-0.15.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:68138a4ba184b4691ccdc39f7795c66b3c68160c586519e7e8444cf5a53e1b4c", size = 10486401, upload-time = "2026-02-12T23:09:27.927Z" }, { url = "https://files.pythonhosted.org/packages/72/cb/2e5259a7eb2a0f87c08c0fe5bf5825a1e4b90883a52685524596bfc93072/ruff-0.15.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:65bb414e5b4eadd95a8c1e4804f6772bbe8995889f203a01f77ddf2d790929dd", size = 10510820, upload-time = "2026-03-05T20:06:37.79Z" },
{ url = "https://files.pythonhosted.org/packages/65/3d/e1429f64a3ff89297497916b88c32a5cc88eeca7e9c787072d0e7f1d3e1e/ruff-0.15.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:518f9af03bfc33c03bdb4cb63fabc935341bb7f54af500f92ac309ecfbba6330", size = 10197452, upload-time = "2026-02-12T23:09:12.147Z" }, { url = "https://files.pythonhosted.org/packages/ff/20/b67ce78f9e6c59ffbdb5b4503d0090e749b5f2d31b599b554698a80d861c/ruff-0.15.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d20aa469ae3b57033519c559e9bc9cd9e782842e39be05b50e852c7c981fa01d", size = 10302395, upload-time = "2026-03-05T20:05:54.504Z" },
{ url = "https://files.pythonhosted.org/packages/78/83/e2c3bade17dad63bf1e1c2ffaf11490603b760be149e1419b07049b36ef2/ruff-0.15.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:da79f4d6a826caaea95de0237a67e33b81e6ec2e25fc7e1993a4015dffca7c61", size = 10693900, upload-time = "2026-02-12T23:09:34.418Z" }, { url = "https://files.pythonhosted.org/packages/5f/e5/719f1acccd31b720d477751558ed74e9c88134adcc377e5e886af89d3072/ruff-0.15.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:15388dd28c9161cdb8eda68993533acc870aa4e646a0a277aa166de9ad5a8752", size = 10754069, upload-time = "2026-03-05T20:06:06.422Z" },
{ url = "https://files.pythonhosted.org/packages/a1/27/fdc0e11a813e6338e0706e8b39bb7a1d61ea5b36873b351acee7e524a72a/ruff-0.15.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3dd86dccb83cd7d4dcfac303ffc277e6048600dfc22e38158afa208e8bf94a1f", size = 11227302, upload-time = "2026-02-12T23:09:36.536Z" }, { url = "https://files.pythonhosted.org/packages/c3/9c/d1db14469e32d98f3ca27079dbd30b7b44dbb5317d06ab36718dee3baf03/ruff-0.15.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b30da330cbd03bed0c21420b6b953158f60c74c54c5f4c1dabbdf3a57bf355d2", size = 11304315, upload-time = "2026-03-05T20:06:10.867Z" },
{ url = "https://files.pythonhosted.org/packages/f6/58/ac864a75067dcbd3b95be5ab4eb2b601d7fbc3d3d736a27e391a4f92a5c1/ruff-0.15.1-py3-none-win32.whl", hash = "sha256:660975d9cb49b5d5278b12b03bb9951d554543a90b74ed5d366b20e2c57c2098", size = 10462555, upload-time = "2026-02-12T23:09:29.899Z" }, { url = "https://files.pythonhosted.org/packages/28/3a/950367aee7c69027f4f422059227b290ed780366b6aecee5de5039d50fa8/ruff-0.15.5-py3-none-win32.whl", hash = "sha256:732e5ee1f98ba5b3679029989a06ca39a950cced52143a0ea82a2102cb592b74", size = 10551676, upload-time = "2026-03-05T20:06:13.705Z" },
{ url = "https://files.pythonhosted.org/packages/e0/5e/d4ccc8a27ecdb78116feac4935dfc39d1304536f4296168f91ed3ec00cd2/ruff-0.15.1-py3-none-win_amd64.whl", hash = "sha256:c820fef9dd5d4172a6570e5721704a96c6679b80cf7be41659ed439653f62336", size = 11599956, upload-time = "2026-02-12T23:09:01.157Z" }, { url = "https://files.pythonhosted.org/packages/b8/00/bf077a505b4e649bdd3c47ff8ec967735ce2544c8e4a43aba42ee9bf935d/ruff-0.15.5-py3-none-win_amd64.whl", hash = "sha256:821d41c5fa9e19117616c35eaa3f4b75046ec76c65e7ae20a333e9a8696bc7fe", size = 11678972, upload-time = "2026-03-05T20:06:45.379Z" },
{ url = "https://files.pythonhosted.org/packages/2a/07/5bda6a85b220c64c65686bc85bd0bbb23b29c62b3a9f9433fa55f17cda93/ruff-0.15.1-py3-none-win_arm64.whl", hash = "sha256:5ff7d5f0f88567850f45081fac8f4ec212be8d0b963e385c3f7d0d2eb4899416", size = 10874604, upload-time = "2026-02-12T23:09:05.515Z" }, { url = "https://files.pythonhosted.org/packages/fe/4e/cd76eca6db6115604b7626668e891c9dd03330384082e33662fb0f113614/ruff-0.15.5-py3-none-win_arm64.whl", hash = "sha256:b498d1c60d2fe5c10c45ec3f698901065772730b411f164ae270bb6bfcc4740b", size = 10965572, upload-time = "2026-03-05T20:06:16.984Z" },
] ]
[[package]] [[package]]