From bd59245cd730f649da8c5c2e57a58e584b82546e Mon Sep 17 00:00:00 2001 From: Ismo Vuorinen Date: Mon, 2 Mar 2026 02:31:26 +0200 Subject: [PATCH] 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. --- .github/workflows/test-actions.yml | 8 +- .serena/memories/repository_overview.md | 14 ++-- .serena/memories/validator_system.md | 4 +- _tests/README.md | 8 -- _tests/framework/validation.py | 2 +- _tests/shared/validation_core.py | 4 +- _tests/unit/spec_helper.sh | 12 --- ansible-lint-fix/action.yml | 2 +- csharp-build/action.yml | 4 +- csharp-publish/action.yml | 2 +- go-build/action.yml | 6 +- go-lint/action.yml | 2 +- php-tests/action.yml | 2 +- pr-lint/action.yml | 4 +- security-scan/action.yml | 2 +- validate-inputs/docs/README_ARCHITECTURE.md | 2 +- validate-inputs/scripts/update-validators.py | 4 - .../tests/test_common-retry_custom.py | 74 ------------------- 18 files changed, 29 insertions(+), 127 deletions(-) delete mode 100644 validate-inputs/tests/test_common-retry_custom.py diff --git a/.github/workflows/test-actions.yml b/.github/workflows/test-actions.yml index c6623e6..08b87d5 100644 --- a/.github/workflows/test-actions.yml +++ b/.github/workflows/test-actions.yml @@ -80,7 +80,7 @@ jobs: category: github-actions-tests - name: Upload unit test results - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 if: always() with: name: unit-test-results @@ -133,7 +133,7 @@ jobs: fi - 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' with: name: integration-test-results @@ -167,7 +167,7 @@ jobs: run: make test-coverage - name: Upload coverage report - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: coverage-report path: _tests/coverage/ @@ -263,7 +263,7 @@ jobs: steps: - name: Download test results - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: pattern: '*-test-results' merge-multiple: true diff --git a/.serena/memories/repository_overview.md b/.serena/memories/repository_overview.md index d4e564a..a2610b5 100644 --- a/.serena/memories/repository_overview.md +++ b/.serena/memories/repository_overview.md @@ -5,28 +5,28 @@ - **Path**: /Users/ivuorinen/Code/ivuorinen/actions - **Branch**: main - **External Usage**: `ivuorinen/actions/@main` -- **Total Actions**: 44 self-contained actions +- **Total Actions**: 43 self-contained actions - **Dogfooding**: Workflows use local actions (pr-lint, codeql-analysis, security-scan) ## Structure ```text / -├── / # 44 self-contained actions +├── / # 43 self-contained actions │ ├── action.yml # Action definition │ ├── README.md # Auto-generated │ └── CustomValidator.py # Optional validator ├── validate-inputs/ # Centralized validation │ ├── validators/ # 9 specialized modules │ ├── scripts/ # Rule/test generators -│ └── tests/ # 769 pytest tests +│ └── tests/ # pytest tests ├── _tests/ # ShellSpec framework ├── _tools/ # Development utilities ├── .github/workflows/ # CI/CD workflows └── 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 @@ -40,7 +40,7 @@ **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 @@ -77,12 +77,12 @@ make test # All tests (pytest + ShellSpec) ## Testing Framework - **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 ## Current Status -- ✅ All tests passing (769/769) +- ✅ All tests passing - ✅ Zero linting issues - ✅ Modular validator architecture - ✅ Convention-based validation diff --git a/.serena/memories/validator_system.md b/.serena/memories/validator_system.md index f71eb8c..f5911fb 100644 --- a/.serena/memories/validator_system.md +++ b/.serena/memories/validator_system.md @@ -2,7 +2,7 @@ ## Status: PRODUCTION READY ✅ -- 769 tests passing (100%) +- All tests passing (100%) - Zero linting issues - Modular architecture complete @@ -60,7 +60,7 @@ validate-inputs/ ├── scripts/ │ ├── update-validators.py # Rule generator │ └── generate-tests.py # Test generator -└── tests/ # 769 pytest tests +└── tests/ # pytest tests /CustomValidator.py # Action-specific validators ``` diff --git a/_tests/README.md b/_tests/README.md index c87507e..6b3c2f3 100644 --- a/_tests/README.md +++ b/_tests/README.md @@ -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" "../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 @@ -482,11 +479,6 @@ End ✅ **Always include**: ```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" When call validate_input_python "pre-commit" "config-file" "../etc/passwd" The status should be failure diff --git a/_tests/framework/validation.py b/_tests/framework/validation.py index 637ca56..cbc8b69 100755 --- a/_tests/framework/validation.py +++ b/_tests/framework/validation.py @@ -264,7 +264,7 @@ def get_input_property(action_file: str, input_name: str, property_check: str) - if property_check == "description": description = input_data.get("description", "") - return description if description else "no-description" + return description or "no-description" if property_check == "all_optional": # Check if all inputs are optional (none are required) diff --git a/_tests/shared/validation_core.py b/_tests/shared/validation_core.py index f2ac771..504036a 100755 --- a/_tests/shared/validation_core.py +++ b/_tests/shared/validation_core.py @@ -337,7 +337,7 @@ class ValidationCore: """ if not value: # Empty values are generally allowed, except for specific cases # 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 None, "" @@ -552,7 +552,7 @@ class ActionFileParser: def _get_description_property(input_data: dict) -> str: """Get the description property.""" description = input_data.get("description", "") - return description if description else "no-description" + return description or "no-description" @staticmethod def _get_all_optional_property(inputs: dict) -> str: diff --git a/_tests/unit/spec_helper.sh b/_tests/unit/spec_helper.sh index 22bd37f..b27443b 100755 --- a/_tests/unit/spec_helper.sh +++ b/_tests/unit/spec_helper.sh @@ -92,9 +92,6 @@ setup_default_inputs() { "go-build" | "go-lint") [[ "$input_name" != "go-version" ]] && export INPUT_GO_VERSION="1.21" ;; - "common-retry") - [[ "$input_name" != "command" ]] && export INPUT_COMMAND="echo test" - ;; "dotnet-version-detect") [[ "$input_name" != "default-version" ]] && export INPUT_DEFAULT_VERSION="8.0" ;; @@ -154,9 +151,6 @@ cleanup_default_inputs() { "go-build" | "go-lint") [[ "$input_name" != "go-version" ]] && unset INPUT_GO_VERSION ;; - "common-retry") - [[ "$input_name" != "command" ]] && unset INPUT_COMMAND - ;; "dotnet-version-detect") [[ "$input_name" != "default-version" ]] && unset INPUT_DEFAULT_VERSION ;; @@ -239,12 +233,6 @@ shellspec_mock_action_run() { "common-file-check") 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") echo "images_compressed=true" >>"$GITHUB_OUTPUT" printf "compression_report=## Compression Results\n- 3 images compressed\n- 25%% size reduction\n" >>"$GITHUB_OUTPUT" diff --git a/ansible-lint-fix/action.yml b/ansible-lint-fix/action.yml index 6ad1dee..970b6c4 100644 --- a/ansible-lint-fix/action.yml +++ b/ansible-lint-fix/action.yml @@ -83,7 +83,7 @@ runs: - name: Install ansible-lint id: install-ansible-lint 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: timeout_minutes: 5 max_attempts: ${{ inputs.max-retries }} diff --git a/csharp-build/action.yml b/csharp-build/action.yml index a51e9d6..04da496 100644 --- a/csharp-build/action.yml +++ b/csharp-build/action.yml @@ -155,7 +155,7 @@ runs: cache-dependency-path: '**/packages.lock.json' - name: Restore Dependencies - uses: step-security/retry@e1d59ce1f574b32f0915e3a8df055cfe9f99be5d # v3.0.4 + uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2 with: timeout_minutes: 10 max_attempts: ${{ inputs.max-retries }} @@ -203,7 +203,7 @@ runs: - name: Upload Test Results if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: csharp-test-results path: | diff --git a/csharp-publish/action.yml b/csharp-publish/action.yml index 53976d8..d9dbfa8 100644 --- a/csharp-publish/action.yml +++ b/csharp-publish/action.yml @@ -169,7 +169,7 @@ runs: cache-dependency-path: '**/packages.lock.json' - name: Restore Dependencies - uses: step-security/retry@e1d59ce1f574b32f0915e3a8df055cfe9f99be5d # v3.0.4 + uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2 with: timeout_minutes: 10 max_attempts: ${{ inputs.max-retries }} diff --git a/go-build/action.yml b/go-build/action.yml index 06a3198..a92ba9d 100644 --- a/go-build/action.yml +++ b/go-build/action.yml @@ -159,13 +159,13 @@ runs: echo "Final detected Go version: $detected_version" >&2 - name: Setup Go - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ steps.detect-go-version.outputs.detected-version }} cache: true - name: Download Dependencies - uses: step-security/retry@e1d59ce1f574b32f0915e3a8df055cfe9f99be5d # v3.0.4 + uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2 with: timeout_minutes: 10 max_attempts: ${{ inputs.max-retries }} @@ -253,7 +253,7 @@ runs: - name: Upload Build Artifacts if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: go-build-artifacts path: | diff --git a/go-lint/action.yml b/go-lint/action.yml index f8f252e..aa8464e 100644 --- a/go-lint/action.yml +++ b/go-lint/action.yml @@ -205,7 +205,7 @@ runs: validate_linter_list "$DISABLE_LINTERS" "disable-linters" - name: Setup Go - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ inputs.go-version }} cache: true diff --git a/php-tests/action.yml b/php-tests/action.yml index 85e0e59..0ddd0e6 100644 --- a/php-tests/action.yml +++ b/php-tests/action.yml @@ -376,7 +376,7 @@ runs: composer clear-cache - name: Install Composer Dependencies - uses: step-security/retry@e1d59ce1f574b32f0915e3a8df055cfe9f99be5d # v3.0.4 + uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2 with: timeout_minutes: 10 max_attempts: ${{ inputs.max-retries }} diff --git a/pr-lint/action.yml b/pr-lint/action.yml index d2f3972..faf5dff 100644 --- a/pr-lint/action.yml +++ b/pr-lint/action.yml @@ -621,7 +621,7 @@ runs: - name: Setup Go if: steps.detect-go.outputs.found == 'true' - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: ${{ steps.go-version.outputs.detected-version }} cache: true @@ -677,7 +677,7 @@ runs: # Upload MegaLinter artifacts - name: Archive production artifacts if: success() || failure() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: MegaLinter reports include-hidden-files: 'true' diff --git a/security-scan/action.yml b/security-scan/action.yml index d565c8d..dde3b9f 100644 --- a/security-scan/action.yml +++ b/security-scan/action.yml @@ -175,7 +175,7 @@ runs: - name: Archive security reports if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: security-reports-${{ github.run_id }} path: | diff --git a/validate-inputs/docs/README_ARCHITECTURE.md b/validate-inputs/docs/README_ARCHITECTURE.md index 4cf45db..dd3d038 100644 --- a/validate-inputs/docs/README_ARCHITECTURE.md +++ b/validate-inputs/docs/README_ARCHITECTURE.md @@ -332,7 +332,7 @@ class CustomValidator(BaseValidator): ## Quality Metrics -- **Test Coverage**: 100% (769 tests) +- **Test Coverage**: 100% - **Validators**: 9 specialized + unlimited custom - **Performance**: < 10ms typical validation time - **Zero Dependencies**: Uses only Python stdlib + PyYAML diff --git a/validate-inputs/scripts/update-validators.py b/validate-inputs/scripts/update-validators.py index 646dd7e..8a1d13b 100755 --- a/validate-inputs/scripts/update-validators.py +++ b/validate-inputs/scripts/update-validators.py @@ -310,10 +310,6 @@ class ValidationRuleGenerator: "common-file-check": { "file-pattern": "file_path", }, - "common-retry": { - "backoff-strategy": "backoff_strategy", - "shell": "shell_type", - }, "docker-publish": { "registry": "registry_enum", "cache-mode": "cache_mode", diff --git a/validate-inputs/tests/test_common-retry_custom.py b/validate-inputs/tests/test_common-retry_custom.py deleted file mode 100644 index 8b931b8..0000000 --- a/validate-inputs/tests/test_common-retry_custom.py +++ /dev/null @@ -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