Compare commits

..

1 Commits

Author SHA1 Message Date
7061aafd35 chore: add tests, update docs and actions (#299)
* docs: update documentation

* feat: validate-inputs has it's own pyproject

* security: mask DOCKERHUB_PASSWORD

* chore: add tokens, checkout, recrete docs, integration tests

* fix: add `statuses: write` permission to pr-lint
2025-10-18 13:09:19 +03:00
148 changed files with 5119 additions and 1897 deletions

View File

@@ -117,14 +117,14 @@ jobs:
- name: Upload Trivy results
if: steps.verify-sarif.outputs.has_trivy == 'true'
uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
with:
sarif_file: 'trivy-results.sarif'
category: 'trivy'
- name: Upload Gitleaks results
if: steps.verify-sarif.outputs.has_gitleaks == 'true'
uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
with:
sarif_file: 'gitleaks-report.sarif'
category: 'gitleaks'

View File

@@ -37,15 +37,15 @@ jobs:
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Initialize CodeQL
uses: github/codeql-action/init@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/init@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
with:
languages: ${{ matrix.language }}
queries: security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/autobuild@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/analyze@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
with:
category: '/language:${{matrix.language}}'

View File

@@ -60,6 +60,7 @@ jobs:
issues: write
pull-requests: write
security-events: write
statuses: write
steps:
- name: Checkout Code
@@ -100,7 +101,7 @@ jobs:
- name: Upload SARIF Report
if: always() && hashFiles('megalinter-reports/sarif/*.sarif')
uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
with:
sarif_file: megalinter-reports/sarif
category: megalinter

View File

@@ -73,7 +73,7 @@ jobs:
if: always()
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
if: always() && hashFiles('_tests/reports/test-results.sarif') != ''
with:
sarif_file: _tests/reports/test-results.sarif

View File

@@ -0,0 +1,115 @@
# Development Standards & Workflows
## Quality Standards (ZERO TOLERANCE)
### Production Ready Criteria
- ALL tests pass (100% success rate)
- ALL linting passes (zero issues)
- ALL validation checks pass
- NO warnings or errors
### Communication
- Direct, factual only
- Never claim "production ready" until literally everything passes
- No hype, buzzwords, or excessive enthusiasm
## Required Commands
### Development Cycle
```bash
make all # Complete: docs, format, lint, test
make dev # Format + lint (development)
make lint # All linters (MUST pass 100%)
make test # All tests (MUST pass 100%)
make format # Auto-fix formatting
```
### Task Completion Checklist
After ANY coding task:
- [ ] `make lint` - Fix all issues (blocking)
- [ ] `make test` - Ensure 100% pass
- [ ] EditorConfig compliance verified
### Validation System
```bash
make update-validators # Generate validation rules
make update-validators-dry # Preview changes
make generate-tests # Create missing tests
make generate-tests-dry # Preview test generation
```
## Code Style
### EditorConfig (BLOCKING ERRORS)
- **Indent**: 2 spaces (4 for Python, tabs for Makefile)
- **Charset**: UTF-8
- **Line Endings**: LF
- **Max Line**: 200 chars (120 for Markdown)
- **Final Newline**: Required
- **Trailing Whitespace**: Trimmed
### Shell Scripts (REQUIRED)
```bash
#!/usr/bin/env bash
set -euo pipefail # MANDATORY
IFS=$' \t\n'
trap cleanup EXIT
trap 'echo "Error at line $LINENO" >&2' ERR
# Always quote: "$variable", basename -- "$path"
# Check tools: command -v jq >/dev/null 2>&1
```
### Python (Ruff)
- **Line Length**: 100 chars
- **Indent**: 4 spaces
- **Quotes**: Double
- **Docstrings**: Google style
- **Type Hints**: Required
### YAML/Actions
- **Indent**: 2 spaces
- **Local Actions**: `uses: ./action-name` (never `../` or `@main`)
- **External Actions**: SHA-pinned (not `@main`/`@v1`)
- **Step IDs**: Required when outputs referenced
- **Permissions**: Minimal scope (contents: read default)
- **Output Sanitization**: Use `printf`, never `echo` for `$GITHUB_OUTPUT`
## Security Requirements
1. **SHA Pinning**: All external actions use commit SHAs
2. **Token Safety**: `${{ github.token }}`, never hardcoded
3. **Input Validation**: All inputs validated via centralized system
4. **Output Sanitization**: `printf '%s\n' "$value" >> $GITHUB_OUTPUT`
5. **Injection Prevention**: Validate for `;`, `&&`, `|`, backticks
6. **Tool Availability**: `command -v tool` checks before use
7. **Variable Quoting**: Always `"$var"` in shell
8. **No Secrets**: Never commit credentials/keys
## Never Do
- Never `git commit` (manual commits not allowed)
- Never use `--no-verify` flags
- Never modify linting config to make tests pass
- Never assume linting issues are acceptable
- Never skip testing after changes
- Never create files unless absolutely necessary
- Never nest `${{ }}` in quoted YAML strings (breaks hashFiles)
## Preferred Patterns
- Edit existing files over creating new ones
- Use centralized validation for all input handling
- Follow existing conventions in codebase
- Actions use composition, not dependencies
- Custom validators in action directories
- Convention-based automatic detection

View File

@@ -0,0 +1,101 @@
# Documentation Guide
## Documentation Locations
### Validation System Docs (`validate-inputs/docs/`)
Read when working with validators or validation logic:
**API.md** - Complete API reference
- BaseValidator methods and properties
- Core validators (Boolean, Version, Token, Numeric, Docker, File, Network, Security, CodeQL)
- Registry system usage
- Custom validator patterns
- Convention system
**DEVELOPER_GUIDE.md** - Creating new validators
- Quick start guide
- Creating core validators (in validators/ directory)
- Creating custom validators (in action directories)
- Adding convention patterns
- Writing tests, debugging, common patterns
**ACTION_MAINTAINER.md** - Using validation in actions
- How validation works (automatic integration)
- Validation flow (input collection, validator selection, execution, error reporting)
- Using automatic validation via conventions
- Custom validation for complex scenarios
- Testing validation, common scenarios, troubleshooting
**README_ARCHITECTURE.md** - System architecture
- Feature overview
- Quick start examples
- Architecture details
- Modular validator structure
- Convention-based detection
- Custom validator support
### Testing Framework (`_tests/README.md`)
Read when writing or debugging tests:
- ShellSpec framework overview
- Multi-level testing strategy (unit, integration, external usage)
- Directory structure explanation
- Test writing patterns
- Running tests (`make test`, `make test-unit`, `make test-action ACTION=name`)
- Coverage reporting
- Mocking and fixtures
- CI integration
### Docker Testing Tools (`_tools/docker-testing-tools/README.md`)
Read when working with CI or testing infrastructure:
- Pre-built Docker image with all testing tools
- Pre-installed tools (ShellSpec, nektos/act, TruffleHog, actionlint, etc.)
- Building locally (build.sh, test.sh)
- Performance benefits (saves ~3 minutes per run)
- Multi-stage build process
- Usage in workflows
### Top-Level Documentation
**README.md** - Main project readme (auto-generated)
- Actions catalog
- Usage examples
- Quick reference
**SECURITY.md** - Security policy
- Reporting vulnerabilities
- Security practices
**LICENSE.md** - MIT license
**CLAUDE.md** - Project instructions (covered in development_standards memory)
## When to Read What
**Starting new validator work**: Read `DEVELOPER_GUIDE.md`, then `API.md` for reference
**Using validation in action**: Read `ACTION_MAINTAINER.md`
**Understanding architecture**: Read `README_ARCHITECTURE.md`
**Writing tests**: Read `_tests/README.md`
**Setting up CI/testing**: Read `_tools/docker-testing-tools/README.md`
**API reference lookup**: Read `API.md` (has method tables, validator details)
## Documentation is Auto-Generated
- Action READMEs generated via `action-docs` (don't edit manually)
- Validation system README auto-generated
- Keep CLAUDE.md and docs/ files updated manually

View File

@@ -1,75 +0,0 @@
# Linting Improvements - September 2025
## Summary
Successfully reduced linting issues from 213 to 99 in the modular validator architecture.
## Issues Fixed
### Critical Issues Resolved
1. **Print Statements** - All converted to proper logging with logger
2. **F-string Logging** - Converted to lazy % formatting
3. **Mutable Class Attributes** - Added `ClassVar` type annotations
4. **Import Sorting** - Fixed and organized
5. **File Path Operations** - Replaced os.path with Path
6. **Exception Handling** - Improved specific exception catching
## Code Changes Made
### Logging Improvements
```python
# Before
print(f"::error::{error}")
# After
logger.error("::error::%s", error)
```
### Class Attributes
```python
# Before
SUPPORTED_LANGUAGES = {...}
# After
SUPPORTED_LANGUAGES: ClassVar[set[str]] = {...}
```
### Path Operations
```python
# Before
if os.path.exists(self.temp_output.name):
# After
if Path(self.temp_output.name).exists():
```
## Remaining Issues (99 total)
### Acceptable Issues
- **39 PLC0415** - Import-outside-top-level (intentional in tests for isolation)
- **27 PLR2004** - Magic value comparisons (domain-specific constants)
- **9 PLR0911** - Too many return statements (complex validation logic)
- **7 BLE001** - Blind except (appropriate for fallback scenarios)
- **7 TRY300** - Try-consider-else (current pattern is clearer)
- **3 S105** - Hardcoded password strings (test data)
- **3 SIM115** - Context managers (NamedTemporaryFile usage)
- **1 C901** - Complexity (validator.main function)
- **1 FIX002** - TODO comment (tracked in issue)
- **1 S110** - Try-except-pass (appropriate fallback)
- **1 S603** - Subprocess call (controlled input in tests)
## Test Status
- 286 tests passing
- 17 tests failing (output format changes)
- 94.4% pass rate
## Conclusion
All critical linting issues have been resolved. The remaining 99 issues are mostly style preferences or intentional patterns that are acceptable for this codebase.
The code quality has significantly improved while maintaining functionality.

View File

@@ -1,345 +0,0 @@
# Modular Validator Architecture - Complete Documentation
## Current Status: PRODUCTION READY ✅
**Last Updated**: 2025-09-16
**Branch**: feat/upgrades-and-restructuring
**Phase Completed**: 1-5 of 7 (Test Generation System Implemented)
**Test Status**: 100% pass rate (303/303 tests passing)
**Linting**: 0 issues
**Quality**: Production ready, zero defects
## Architecture Overview
Successfully transformed monolithic `validator.py` into a modular, extensible validation system for GitHub Actions inputs.
The architecture now provides specialized validators, convention-based auto-detection, support for custom validators, and an intelligent test generation system.
## Core Components
### 1. Base Framework
- **BaseValidator** (`validators/base.py`): Abstract base class defining validator interface
- **ValidatorRegistry** (`validators/registry.py`): Dynamic validator discovery and management
- **ConventionMapper** (`validators/conventions.py`): Automatic validation based on naming patterns
### 2. Specialized Validator Modules (9 Total)
| Module | Purpose | Status |
| ------------------------ | --------------------------------- | ----------- |
| `validators/token.py` | GitHub, NPM, PyPI, Docker tokens | ✅ Complete |
| `validators/version.py` | SemVer, CalVer, language versions | ✅ Complete |
| `validators/boolean.py` | Boolean value validation | ✅ Complete |
| `validators/numeric.py` | Numeric ranges and constraints | ✅ Complete |
| `validators/docker.py` | Docker images, tags, platforms | ✅ Complete |
| `validators/file.py` | File paths, extensions, security | ✅ Complete |
| `validators/network.py` | URLs, emails, IPs, ports | ✅ Complete |
| `validators/security.py` | Injection detection, secrets | ✅ Complete |
| `validators/codeql.py` | CodeQL queries, languages, config | ✅ Complete |
### 3. Custom Validators (4 Implemented)
| Action | Custom Validator | Features |
| ----------------- | ---------------- | ------------------------------------ |
| `sync-labels` | ✅ Implemented | YAML file validation, GitHub token |
| `docker-build` | ✅ Implemented | Complex build args, platforms, cache |
| `codeql-analysis` | ✅ Implemented | Language support, query validation |
| `docker-publish` | ✅ Implemented | Registry validation, credentials |
## Implementation Phases
### ✅ Phase 1: Core Infrastructure (COMPLETED)
- Created modular directory structure
- Implemented BaseValidator abstract class
- Built ValidatorRegistry with auto-discovery
- Established testing framework
### ✅ Phase 2: Specialized Validators (COMPLETED)
- Extracted validation logic into 9 specialized modules
- Created comprehensive test coverage
- Achieved full pytest compatibility
- Fixed all method signatures and interfaces
### ✅ Phase 3: Convention Mapper (COMPLETED)
- Implemented priority-based pattern matching (100+ patterns)
- Created ConventionBasedValidator for automatic validation
- Added YAML-based convention override support
- Integrated with ValidatorRegistry
### ✅ Phase 4: Custom Validator Support (COMPLETED)
- Implemented custom validator discovery in registry
- Created 4 custom validators for complex actions
- Fixed error propagation between parent/child validators
- Added full GitHub expression (`${{ }}`) support
- All custom validator tests passing (6/6)
### ✅ Phase 5: Test Generation System (COMPLETED)
- Implemented `generate-tests.py` script with intelligent pattern detection
- Created test templates for different validator types
- Added skip-existing-tests logic to prevent overwrites
- Integrated with Makefile (`make generate-tests`, `make generate-tests-dry`)
- Created comprehensive tests for the generator itself (11 tests passing)
- Supports both ShellSpec and pytest test generation
- Handles custom validators in action directories
#### Test Generation Features
- **Intelligent Input Detection**: Recognizes patterns like `token`, `version`, `path`, `url`, `email`, `dry-run`, etc.
- **Context-Aware Test Cases**: Generates appropriate test cases based on input types
- **GitHub Expression Support**: Includes tests for `${{ }}` expressions
- **Template System**: Different templates for version, token, boolean, numeric, file, network, docker, and security validators
- **Non-Destructive**: Never overwrites existing test files
- **Dry Run Mode**: Preview what would be generated without creating files
- **Comprehensive Coverage**: Generates ShellSpec tests for actions, pytest tests for validators, and tests for custom validators
#### Test Generation Commands
```bash
make generate-tests # Generate missing tests
make generate-tests-dry # Preview what would be generated
make test-generate-tests # Test the generator itself
```
### ⏳ Phase 6: Integration and Migration (NOT STARTED)
- Update YAML rules to new schema format
- Migrate remaining actions to custom validators
- Update rule generation scripts
### ⏳ Phase 7: Documentation and Tooling (NOT STARTED)
- Create validator development guide
- Add CLI tools for validator testing
- Update all documentation
## Convention-Based Detection
The ConventionMapper provides automatic validator selection based on input naming patterns:
```text
# Priority levels (higher = more specific)
100: Exact matches (e.g., "dry-run" → boolean)
95: Language-specific versions (e.g., "-python-version" → python_version)
90: Generic suffixes (e.g., "-token" → token)
85: Contains patterns (e.g., contains "email" → email)
80: Prefix patterns (e.g., "is-" → boolean)
```
## Key Technical Achievements
### Error Propagation Pattern
```python
# Proper error propagation from child to parent validators
result = self.child_validator.validate_something(value)
for error in self.child_validator.errors:
if error not in self.errors:
self.add_error(error)
self.child_validator.clear_errors()
return result
```
### GitHub Expression Support
All validators properly handle GitHub Actions expressions:
```python
# Allow GitHub Actions expressions
if self.is_github_expression(value):
return True
```
### Platform Validation
Docker platform validation accepts full platform strings:
- `linux/amd64`, `linux/arm64`, `linux/arm/v7`
- `windows/amd64` (where applicable)
- `darwin/arm64` (where applicable)
## Testing Infrastructure
### Test Statistics
- **Total Tests**: 303 (including 11 test generator tests)
- **Passing**: 303 (100%)
- **Coverage by Module**: All modules have dedicated test files
- **Custom Validators**: 6 comprehensive tests
- **Test Generator**: 11 tests for the generation system
### Test Files
```text
validate-inputs/tests/
├── test_base.py ✅
├── test_registry.py ✅
├── test_convention_mapper.py ✅
├── test_boolean_validator.py ✅
├── test_codeql_validator.py ✅
├── test_docker_validator.py ✅
├── test_file_validator.py ✅
├── test_network_validator.py ✅
├── test_numeric_validator.py ✅
├── test_security_validator.py ✅
├── test_token_validator.py ✅
├── test_version_validator.py ✅
├── test_custom_validators.py ✅ (6 tests)
├── test_integration.py ✅
├── test_validator.py ✅
└── test_generate_tests.py ✅ (11 tests)
```
### Test Generation System
```text
validate-inputs/scripts/
└── generate-tests.py ✅ Intelligent test generator
```
## Production Readiness Criteria
**ALL CRITERIA MET**:
- Zero failing tests (303/303 passing)
- Zero linting issues
- Zero type checking issues
- Full backward compatibility maintained
- Comprehensive error handling
- Security patterns validated
- Performance optimized (lazy loading, caching)
- Custom validator support proven
- GitHub expression handling complete
- Test generation system operational
## Usage Examples
### Basic Validation
```python
from validators.registry import ValidatorRegistry
registry = ValidatorRegistry()
validator = registry.get_validator("docker-build")
result = validator.validate_inputs({
"context": ".",
"dockerfile": "Dockerfile",
"platforms": "linux/amd64,linux/arm64"
})
```
### Custom Validator
```python
# Automatically loads docker-build/CustomValidator.py
validator = registry.get_validator("docker-build")
# Uses specialized validation logic for docker-build action
```
### Test Generation
```bash
# Generate missing tests for all actions and validators
python3 validate-inputs/scripts/generate-tests.py
# Preview what would be generated (dry run)
python3 validate-inputs/scripts/generate-tests.py --dry-run --verbose
# Generated test example
#!/usr/bin/env bash
Describe 'Action Name Input Validation'
Context 'Required inputs validation'
It 'should fail when required inputs are missing'
When run validate_inputs 'action-name'
The status should be failure
End
End
End
```
## File Structure
```text
validate-inputs/
├── validator.py # Main entry point
├── validators/
│ ├── __init__.py
│ ├── base.py # BaseValidator abstract class
│ ├── registry.py # ValidatorRegistry
│ ├── conventions.py # ConventionBasedValidator
│ ├── [9 specialized validators]
│ └── ...
├── rules/ # YAML validation rules
├── tests/ # Comprehensive test suite
│ ├── [validator tests]
│ └── test_generate_tests.py # Test generator tests
└── scripts/
├── update-validators.py # Rule generator
└── generate-tests.py # Test generator ✅
# Custom validators in action directories
sync-labels/CustomValidator.py ✅
docker-build/CustomValidator.py ✅
codeql-analysis/CustomValidator.py ✅
docker-publish/CustomValidator.py ✅
```
## Benefits Achieved
### 1. Modularity
- Each validator is self-contained
- Clear separation of concerns
- Easy to test individually
### 2. Extensibility
- New validators easily added
- Custom validators for complex actions
- Convention-based auto-detection
- Automatic test generation
### 3. Maintainability
- Individual test files per validator
- Consistent interfaces
- Clear error messages
- Tests generated with consistent patterns
### 4. Performance
- Lazy loading of validators
- Efficient pattern matching
- Minimal overhead
- Fast test generation
### 5. Developer Experience
- Automatic test scaffolding
- Intelligent pattern detection
- Non-destructive generation
- Comprehensive test coverage
## Next Steps
1. **Phase 6**: Integration and Migration
- Update YAML rules to new schema format
- Migrate more actions to custom validators
2. **Phase 7**: Documentation and Tooling
- Create comprehensive validator development guide
- Add CLI tools for validator testing
3. **Optional Enhancements**:
- Create more custom validators (github-release, npm-publish)
- Enhance test generation templates
- Add performance benchmarks
## Summary
The modular validator architecture with test generation is **complete and production-ready**. Phases 1-5 are done, providing a robust, extensible,
and well-tested validation system for GitHub Actions. The test generation system ensures consistent test coverage and reduces manual test writing effort.
The system maintains 100% test coverage with zero defects, follows SOLID principles, and maintains full backward compatibility.

View File

@@ -1,200 +0,0 @@
# Modular Validator Architecture - COMPLETED
## Overview
Successfully implemented a comprehensive modular validation system for GitHub Actions, replacing the monolithic validator.py with a flexible, extensible architecture.
## Implementation Status: COMPLETED (September 2025)
All 7 phases completed with 100% test pass rate and zero linting issues.
## Architecture Components
### Core System
1. **BaseValidator** (`validators/base.py`)
- Abstract base class defining validation interface
- Standard methods: validate_inputs, add_error, clear_errors
- Extensible for custom validators
2. **ValidatorRegistry** (`validators/registry.py`)
- Dynamic validator discovery and loading
- Custom validator support via action-specific `<action-name>/CustomValidator.py` files
- Searches project root for `<action-dir>/CustomValidator.py` (e.g., `docker-build/CustomValidator.py`)
- Fallback to convention-based validation when no custom validator exists
- Added get_validator_by_type method for direct type access
3. **ConventionBasedValidator** (`validators/conventions.py`)
- Pattern-based automatic validation
- Detects validation needs from input names
- Delegates to specific validators based on conventions
4. **ConventionMapper** (`validators/convention_mapper.py`)
- Maps input patterns to validator types
- Supports exact, prefix, suffix, and contains patterns
- Efficient pattern matching with caching
### Specialized Validators
- **BooleanValidator**: Boolean values (true/false)
- **VersionValidator**: SemVer, CalVer, flexible versioning
- **TokenValidator**: GitHub tokens, API keys
- **NumericValidator**: Integer/float ranges
- **FileValidator**: File/directory paths
- **NetworkValidator**: URLs, emails, hostnames
- **DockerValidator**: Images, tags, platforms
- **SecurityValidator**: Injection protection, security patterns
- **CodeQLValidator**: Languages, queries, config
### Custom Validators
- Action-specific validation via `<action-name>/CustomValidator.py` files
- Located in each action's directory (e.g., `docker-build/CustomValidator.py`, `npm-publish/CustomValidator.py`)
- Extends ConventionBasedValidator or BaseValidator
- Registry discovers custom validators by searching action directories in project root
- Examples: docker-build, sync-labels, npm-publish, php-laravel-phpunit, validate-inputs
## Testing Infrastructure
### Test Generation System
- **generate-tests.py**: Non-destructive test generation
- Preserves existing tests
- Generates ShellSpec and pytest tests
- Pattern-based test case creation
- 900+ lines of intelligent test scaffolding
### Test Coverage
- 303 total tests passing
- ShellSpec for action validation
- pytest for Python validators
- Integration tests for end-to-end validation
- Performance benchmarks available
## Documentation & Tools
### Documentation
- **API.md**: Complete API reference
- **DEVELOPER_GUIDE.md**: Adding new validators
- **ACTION_MAINTAINER.md**: Using validation system
- **README_ARCHITECTURE.md**: System overview
### Debug & Performance Tools
- **debug-validator.py**: Interactive debugging
- **benchmark-validator.py**: Performance profiling
- **update-validators.py**: Rule generation
## Code Quality
### Standards Achieved
- ✅ Zero linting issues (ruff, pyright)
- ✅ 100% test pass rate (303 tests)
- ✅ Full backward compatibility
- ✅ Type hints throughout
- ✅ Comprehensive documentation
- ✅ EditorConfig compliance
### Fixed Issues
- Import sorting and organization
- F-string logging converted to lazy format
- Boolean arguments made keyword-only
- Type annotations using proper types
- Private member access via public methods
- Exception handling improvements
- Added missing registry methods
## Integration
### Main Validator Integration
- validator.py uses ValidatorRegistry
- Transparent migration from old system
- All existing actions work unchanged
- Custom validators take precedence
### GitHub Expression Support
- Proper handling of ${{ }} expressions
- Expression validation in appropriate contexts
- Security-aware expression checking
## File Structure
```text
validate-inputs/
├── validators/
│ ├── __init__.py
│ ├── base.py # Abstract base
│ ├── registry.py # Discovery & loading
│ ├── conventions.py # Pattern-based
│ ├── convention_mapper.py # Pattern mapping
│ ├── boolean.py # Specialized validators...
│ ├── version.py
│ └── ...
├── rules/ # Auto-generated YAML
├── tests/ # pytest tests
├── scripts/
│ ├── generate-tests.py # Test generation
│ ├── debug-validator.py # Debugging
│ ├── benchmark-validator.py # Performance
│ └── update-validators.py # Rule generation
├── docs/ # Documentation
├── CustomValidator.py # Custom validator for validate-inputs action
└── validator.py # Main entry point
# Custom validators in action directories (examples):
docker-build/CustomValidator.py
npm-publish/CustomValidator.py
php-laravel-phpunit/CustomValidator.py
version-validator/CustomValidator.py
```
## Key Achievements
1. **Modular Architecture**: Clean separation of concerns
2. **Convention-Based**: Automatic validation from naming patterns
3. **Extensible**: Easy to add new validators
4. **Backward Compatible**: No breaking changes
5. **Well Tested**: Comprehensive test coverage
6. **Documented**: Complete API and guides
7. **Production Ready**: Zero defects, all quality gates passed
## Usage Examples
### Custom Validator
```python
# docker-build/CustomValidator.py
from validate-inputs.validators.conventions import ConventionBasedValidator
from validate-inputs.validators.docker import DockerValidator
class CustomValidator(ConventionBasedValidator):
def __init__(self, action_type: str):
super().__init__(action_type)
self.docker_validator = DockerValidator(action_type)
def validate_inputs(self, inputs: dict[str, str]) -> bool:
# Custom validation logic
if not self.validate_required_inputs(inputs, ["context"]):
return False
return super().validate_inputs(inputs)
```
### Debug Usage
```bash
# Debug an action
python validate-inputs/scripts/debug-validator.py docker-build --inputs '{"context": ".", "platforms": "linux/amd64,linux/arm64"}'
# Benchmark performance
python validate-inputs/scripts/benchmark-validator.py --action docker-build --iterations 1000
```
## Migration Complete
The modular validator architecture is fully implemented, tested, documented, and integrated. All quality standards met with zero defects.

View File

@@ -1,199 +0,0 @@
# Project Overview - GitHub Actions Monorepo
## Purpose
This repository contains a collection of reusable GitHub Actions designed to streamline CI/CD processes and ensure code quality.
Each action is fully self-contained and can be used independently in any GitHub repository.
## Repository Information
- **Branch**: feat/upgrades-and-restructuring
- **Location**: /Users/ivuorinen/Code/ivuorinen/actions
- **External Usage**: `ivuorinen/actions/action-name@main`
- **Last Updated**: January 2025
## Key Features
- **Production-Ready Actions** covering setup, linting, building, testing, and deployment
- **Self-Contained Design** - each action works independently without dependencies
- **Modular Validator Architecture** - specialized validators with convention-based auto-detection
- **Custom Validator Support** - complex actions have dedicated validation logic
- **Test Generation System** - automatic test scaffolding with intelligent pattern detection
- **Multi-Language Support** including Node.js, PHP, Python, Go, C#, Docker, and more
- **Comprehensive Testing** with dual framework (ShellSpec + pytest)
- **Zero Defect Policy** - 100% test pass rate, zero linting issues required
## Architecture Highlights
### Directory Structure
- **Flat Action Layout**: Each action in its own directory with `action.yml`
- **Centralized Validation**: `validate-inputs/` with modular validator system
- **Custom Validators**: Action-specific validators (e.g., `docker-build/CustomValidator.py`)
- **Testing Infrastructure**: `_tests/` for ShellSpec, `validate-inputs/tests/` for pytest
- **Build Tools**: `_tools/` for helper scripts and development utilities
- **Test Generation**: `validate-inputs/scripts/generate-tests.py` for automatic test creation
### Validation System (Modular Architecture)
```text
validate-inputs/
├── validator.py # Main entry point
├── validators/
│ ├── base.py # Abstract base class
│ ├── registry.py # Dynamic validator discovery
│ ├── conventions.py # Convention-based auto-detection
│ └── [9 specialized modules]
├── scripts/
│ ├── update-validators.py # Auto-generates validation rules
│ └── generate-tests.py # Non-destructive test generation
└── tests/ # Comprehensive test suite
```
### Testing Framework
- **ShellSpec**: For testing shell scripts and GitHub Actions
- **pytest**: For Python validation system (303 tests, 100% passing)
- **Test Generator**: Automatic test scaffolding for new actions/validators
- **Coverage**: Full test coverage for all validators
## Action Categories
**Total: 43 actions** across 8 categories
### Setup Actions (7)
- `node-setup`, `set-git-config`, `php-version-detect`, `python-version-detect`,
- `python-version-detect-v2`, `go-version-detect`, `dotnet-version-detect`
### Linting Actions (13)
- `ansible-lint-fix`, `biome-check`, `biome-fix`, `csharp-lint-check`
- `eslint-check`, `eslint-fix`, `go-lint`, `pr-lint`, `pre-commit`
- `prettier-check`, `prettier-fix`, `python-lint-fix`, `terraform-lint-fix`
### Build Actions (3)
- `csharp-build`, `go-build`, `docker-build`
### Publishing Actions (5)
- `npm-publish`, `docker-publish`, `docker-publish-gh`, `docker-publish-hub`, `csharp-publish`
### Testing Actions (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` (security analysis)
### Utilities (2)
- `version-file-parser`, `version-validator`
### Validation (1)
- `validate-inputs` (centralized input validation system)
## Development Workflow
### Core Commands
```bash
make all # Generate docs, format, lint, test
make dev # Format then lint
make lint # Run all linters
make test # Run all tests
make update-validators # Update validation rules
make generate-tests # Generate missing tests (non-destructive)
make generate-tests-dry # Preview test generation
```
### Quality Standards
- **ZERO TOLERANCE**: No failing tests, no linting issues
- **Production Ready**: Only when ALL checks pass
- **Convention Priority**: EditorConfig rules are blocking
- **Security First**: No secrets, tokens, or sensitive data in code
## Recent Accomplishments (January 2025)
### Phase 1-4: Modular Validator Architecture ✅
- Transformed monolithic validator into 11 specialized modules
- Implemented convention-based auto-detection (100+ patterns)
- Created 3 custom validators for complex actions
- Achieved 100% test pass rate (292/292 tests)
- Zero linting issues across all code
### Phase 5: Test Generation System ✅
- Created non-destructive test generation (preserves existing tests)
- Intelligent pattern detection for input types
- Template-based scaffolding for different validator types
- ShellSpec test generation for GitHub Actions
- pytest test generation for validators
- Custom validator test support
- 11 comprehensive tests for the generator itself
- Makefile integration with three new commands
### Custom Validators Implemented
1. `docker-build` - Complex build args, platforms, cache validation
2. `codeql-analysis` - Language support, query validation
3. `docker-publish` - Registry, credentials, platform validation
### Technical Improvements
- Full GitHub expression support (`${{ }}`)
- Error propagation between parent/child validators
- Platform-specific validation (Docker architectures)
- Registry validation (Docker Hub, GHCR, etc.)
- Security pattern detection and injection prevention
- Non-destructive test generation system
- Template-based test scaffolding
## Project Status
**Phases Completed**:
- ✅ Phase 1: Base Architecture (100% complete)
- ✅ Phase 2: Core Validators (100% complete)
- ✅ Phase 3: Registry System (100% complete)
- ✅ Phase 4: Custom Validators (100% complete)
- ✅ Phase 5: Test Generation (100% complete)
- ⏳ Phase 6: Integration and Migration (in progress)
- ⏳ Phase 7: Documentation and Tooling (not started)
**Quality Metrics**:
- ✅ 100% test pass rate (303 total tests)
- ✅ Zero linting issues
- ✅ Modular, extensible architecture
- ✅ Custom validator support
- ✅ Convention-based auto-detection
- ✅ Full backward compatibility
- ✅ Comprehensive error handling
- ✅ Security validations
- ✅ Test generation system
## Next Steps
1. Complete Phase 6: Integration and Migration
- Integrate modular validators with main validator.py
- Ensure full backward compatibility
- Test all 50+ actions with integrated system
2. Phase 7: Documentation and Tooling
3. Performance optimization
4. Production deployment
## IDE Configuration Note
For Pyright/Pylance import resolution in IDEs like Zed, VSCode:
- The project uses relative imports within validate-inputs
- Python path includes validate-inputs directory
- Tests use sys.path manipulation for imports

View File

@@ -1,171 +0,0 @@
# Project Structure and Architecture
## Repository Structure
```text
/Users/ivuorinen/Code/ivuorinen/actions/
├── Action Directories/ # Each action is self-contained
│ ├── action.yml # Action definition
│ ├── README.md # Auto-generated documentation
│ └── CustomValidator.py # Optional custom validator
├── validate-inputs/ # Centralized validation system
│ ├── validator.py # Main entry point
│ ├── validators/ # Modular validator architecture
│ │ ├── base.py # Abstract base class
│ │ ├── registry.py # Dynamic validator discovery
│ │ ├── conventions.py # Convention-based detection
│ │ ├── boolean.py # Boolean validation
│ │ ├── codeql.py # CodeQL-specific validation
│ │ ├── docker.py # Docker validation
│ │ ├── file.py # File path validation
│ │ ├── network.py # Network/URL validation
│ │ ├── numeric.py # Numeric validation
│ │ ├── security.py # Security pattern detection
│ │ ├── token.py # Token validation
│ │ └── version.py # Version validation
│ ├── rules/ # Auto-generated YAML rules
│ ├── scripts/ # Rule generation utilities
│ └── tests/ # Comprehensive pytest suite (292 tests)
├── _tests/ # ShellSpec testing framework
│ ├── unit/ # Unit tests for actions
│ ├── framework/ # Testing utilities
│ └── shared/ # Shared test components
├── _tools/ # Development utilities
│ ├── docker-testing-tools/ # Docker test environment
│ └── fix-local-action-refs.py # Action reference fixer
├── .github/ # GitHub configuration
│ └── workflows/ # CI/CD workflows
├── .serena/ # Serena AI configuration
│ └── memories/ # Project knowledge base
├── Makefile # Build automation
├── pyproject.toml # Python configuration
├── CLAUDE.md # Project instructions
└── README.md # Auto-generated catalog
```
## Modular Validator Architecture
### Core Components
- **BaseValidator**: Abstract interface for all validators
- **ValidatorRegistry**: Dynamic discovery and loading
- **ConventionMapper**: Automatic validation based on naming patterns
### Specialized Validators
1. **TokenValidator**: GitHub, NPM, PyPI, Docker tokens
2. **VersionValidator**: SemVer, CalVer, language-specific
3. **BooleanValidator**: Case-insensitive boolean values
4. **NumericValidator**: Ranges and numeric constraints
5. **DockerValidator**: Images, tags, platforms, registries
6. **FileValidator**: Paths, extensions, security checks
7. **NetworkValidator**: URLs, emails, IPs, ports
8. **SecurityValidator**: Injection detection, secrets
9. **CodeQLValidator**: Queries, languages, categories
### Custom Validators
- `sync-labels/CustomValidator.py` - YAML file validation
- `docker-build/CustomValidator.py` - Complex build validation
- `codeql-analysis/CustomValidator.py` - Language and query validation
- `docker-publish/CustomValidator.py` - Registry and credential validation
## Action Categories
### Setup Actions (7)
- `node-setup`, `set-git-config`, `php-version-detect`
- `python-version-detect`, `python-version-detect-v2`
- `go-version-detect`, `dotnet-version-detect`
### Linting Actions (13)
- `ansible-lint-fix`, `biome-check`, `biome-fix`
- `csharp-lint-check`, `eslint-check`, `eslint-fix`
- `go-lint`, `pr-lint`, `pre-commit`
- `prettier-check`, `prettier-fix`
- `python-lint-fix`, `terraform-lint-fix`
### Build Actions (3)
- `csharp-build`, `go-build`, `docker-build`
### Publishing Actions (5)
- `npm-publish`, `docker-publish`
- `docker-publish-gh`, `docker-publish-hub`
- `csharp-publish`
### Testing Actions (3)
- `php-tests`, `php-laravel-phpunit`, `php-composer`
### Repository Management (9)
- `github-release`, `release-monthly`
- `sync-labels`, `stale`
- `compress-images`, `common-cache`
- `common-file-check`, `common-retry`
- `codeql-analysis`
### Utilities (2)
- `version-file-parser`, `version-validator`
## Key Architectural Principles
### Self-Contained Design
- Each action directory contains everything needed
- No dependencies between actions
- External usability via `ivuorinen/actions/action-name@main`
- Custom validators colocated with actions
### Modular Validation System
- Specialized validators for different input types
- Convention-based automatic detection (100+ patterns)
- Priority system for pattern matching
- Error propagation between validators
- Full GitHub expression support (`${{ }}`)
### Testing Strategy
- **ShellSpec**: Shell scripts and GitHub Actions
- **pytest**: Python validation system (100% pass rate)
- **Coverage**: All validators have dedicated test files
- **Standards**: Zero tolerance for failures
### Security Model
- SHA-pinned external actions
- Token pattern validation
- Injection detection
- Path traversal protection
- Security validator for sensitive data
## Development Workflow
### Core Commands
```bash
make all # Full build pipeline
make dev # Format and lint
make lint # All linters
make test # All tests
make update-validators # Generate validation rules
```
### Quality Standards
- **EditorConfig**: Blocking enforcement
- **Linting**: Zero issues required
- **Testing**: 100% pass rate required
- **Production Ready**: Only when ALL checks pass
### Documentation
- Auto-generated README files via `action-docs`
- Consistent formatting and structure
- Cross-referenced action catalog
- Comprehensive inline documentation

View File

@@ -1,36 +0,0 @@
# Quality Standards and Communication Guidelines
## Critical Quality Standards
### ZERO TOLERANCE POLICY
- **ANY failing tests** = Project is NOT production ready
- **ANY linting issues** = Project is NOT production ready
- **NO EXCEPTIONS** to these rules
### Production Ready Definition
A project is only production ready when:
- ALL tests pass (100% success rate)
- ALL linting passes with zero issues
- ALL validation checks pass
- NO warnings or errors in any tooling
### Communication Style
- **Tone down language** - avoid excessive enthusiasm or verbose descriptions
- Be direct and factual
- Don't claim success until ALL issues are resolved
- Don't use terms like "production ready" unless literally everything passes
- Focus on facts, not marketing language
### Work Standards
- Fix ALL issues before declaring completion
- Never compromise on quality standards
- Test everything thoroughly
- Maintain zero-defect mentality
- Quality over speed
This represents the user's absolute standards for code quality and communication.

View File

@@ -0,0 +1,87 @@
# GitHub Actions Monorepo - Overview
## Repository Info
- **Path**: /Users/ivuorinen/Code/ivuorinen/actions
- **Branch**: main
- **External Usage**: `ivuorinen/actions/<action-name>@main`
- **Total Actions**: 43 self-contained actions
## Structure
```text
/
├── <action-dirs>/ # 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/ # ShellSpec framework
├── _tools/ # Development utilities
├── .github/workflows/ # CI/CD workflows
└── Makefile # Build automation
```
## 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
**Linting (13)**: ansible-lint-fix, biome-check/fix, csharp-lint-check, eslint-check/fix, go-lint, pr-lint, pre-commit, prettier-check/fix, python-lint-fix, terraform-lint-fix
**Build (3)**: csharp-build, go-build, docker-build
**Publishing (5)**: npm-publish, docker-publish, docker-publish-gh, docker-publish-hub, csharp-publish
**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
**Utilities (3)**: version-file-parser, version-validator, validate-inputs
## Key Principles
### Self-Contained Design
- No dependencies between actions
- Externally usable via GitHub Actions marketplace
- Custom validators colocated with actions
### Quality Standards
- **Zero Tolerance**: No failing tests, no linting issues
- **Production Ready**: Only when ALL checks pass
- **EditorConfig**: 2-space indent, LF, UTF-8, max 200 chars (120 for MD)
### Security Model
- SHA-pinned external actions (55 SHA-pinned, 0 unpinned)
- Token validation, injection detection
- Path traversal protection
- `set -euo pipefail` in all shell scripts
## Development Workflow
```bash
make all # Full pipeline: docs, format, lint, test
make dev # Format + lint
make lint # All linters (markdownlint, yaml-lint, shellcheck, ruff)
make test # All tests (pytest + ShellSpec)
```
## Testing Framework
- **ShellSpec**: GitHub Actions and shell scripts
- **pytest**: Python validators (769 tests, 100% pass rate)
- **Test Generator**: Automatic scaffolding for new actions
## Current Status
- ✅ All tests passing (769/769)
- ✅ Zero linting issues
- ✅ Modular validator architecture
- ✅ Convention-based validation
- ✅ Test generation system
- ✅ Full backward compatibility

View File

@@ -1,111 +0,0 @@
# ShellSpec Test Fixes Tracking
## Status
**Branch**: feat/upgrades-and-restructuring
**Date**: 2025-09-17
**Progress**: Fixed critical test failures
## Summary
- Initial failing tests: 27 actions
- **Fixed completely**: 3 actions (codeql-analysis, common-cache, common-file-check)
- **Partially fixed**: Several others have reduced failures
- **Key achievement**: Established patterns for fixing remaining tests
## ✅ Completed Fixes (3 actions)
### 1. codeql-analysis
- Created comprehensive CustomValidator
- Fixed all language, token, path, and query validations
- Result: **65 examples, 0 failures**
### 2. common-cache
- Created CustomValidator for comma-separated paths
- Added cache type, paths, keys, env-vars validation
- Result: **29 examples, 0 failures** (23 warnings)
### 3. common-file-check
- Created CustomValidator for glob patterns
- Supports \*, ?, \*\*, {}, [] in file patterns
- Result: **17 examples, 0 failures** (12 warnings)
## 🎯 Key Patterns Established
### CustomValidator Template
```python
class CustomValidator(BaseValidator):
def validate_inputs(self, inputs: dict[str, str]) -> bool:
# Handle required inputs first
# Use specific validation methods
# Check for GitHub expressions: if "${{" in value
# Validate security patterns
return valid
```
### Common Validation Patterns
1. **Token Validation**
- ghp\_ tokens: 40-44 chars
- github*pat* tokens: 82-95 chars
- ghs\_ tokens: 40-44 chars
2. **Path Validation**
- Reject absolute paths: `/path`
- Reject traversal: `..`
- Allow comma-separated: split and validate each
3. **Error Messages**
- "Required input 'X' is missing"
- "Absolute path not allowed"
- "Path traversal detected"
- "Command injection detected"
4. **Test Output**
- Python logger outputs to stderr
- Tests checking stdout need updating to stderr
- Warnings about unexpected output are non-critical
## 📋 Remaining Work
### Quick Fixes (Similar patterns)
- common-retry: Add backoff-strategy, shell validation
- compress-images: File pattern validation
- eslint-check, prettier-fix: Token validation
### Docker Actions (Need CustomValidators)
- docker-build, docker-publish, docker-publish-gh, docker-publish-hub
- Common issues: image-name, registry, platforms validation
### Version Detection Actions
- go-version-detect, python-version-detect, php-version-detect
- Need version format validation
### Complex Actions (Need detailed CustomValidators)
- node-setup: Package manager, caching logic
- pre-commit: Hook configuration
- terraform-lint-fix: HCL-specific validation
## 🚀 Next Steps
To complete all fixes:
1. Create CustomValidators for remaining actions with failures
2. Use established patterns for quick wins
3. Test each action individually before full suite
4. Update tests expecting stdout to check stderr where needed
## 📊 Success Criteria
- All ShellSpec tests pass (0 failures)
- Warnings are acceptable (output format issues)
- Maintain backward compatibility
- Follow established validation patterns

View File

@@ -1,125 +0,0 @@
# Task Completion Requirements
## Mandatory Steps After Completing Any Task
### 1. Linting (BLOCKING REQUIREMENT)
```bash
make lint # Run all linters - must pass 100%
```
**Critical Rules:**
- EditorConfig violations are BLOCKING errors - fix always
- All linting issues are NOT ACCEPTABLE and must be resolved
- Never simplify linting configuration to make tests pass
- Linting tools decisions are final and must be obeyed
- Consider ALL linting errors as blocking errors
**Specific Linting Steps:**
```bash
make lint-markdown # Fix markdown issues
make lint-yaml # Fix YAML issues
make lint-shell # Fix shell script issues
make lint-python # Fix Python code issues
```
### 2. Testing (VERIFICATION REQUIREMENT)
```bash
make test # Run all tests - must pass 100%
```
**Test Categories:**
- Python validation tests (pytest)
- GitHub Actions tests (ShellSpec)
- Integration tests
- Coverage reporting
### 3. Formatting (AUTO-FIX REQUIREMENT)
```bash
make format # Auto-fix all formatting issues
```
**Always use autofixers before running linters:**
- Markdown formatting and table formatting
- YAML/JSON formatting with prettier
- Python formatting with ruff
- Line ending and whitespace fixes
## Verification Checklist
### Before Considering Task Complete
- [ ] `make lint` passes with zero issues
- [ ] `make test` passes with 100% success
- [ ] EditorConfig rules followed (2-space indent, LF endings, UTF-8)
- [ ] No trailing whitespace or missing final newlines
- [ ] Shell scripts pass shellcheck
- [ ] Python code passes ruff with comprehensive rules
- [ ] YAML files pass yaml-lint and actionlint
- [ ] Markdown passes markdownlint-cli2
### Security and Quality Gates
- [ ] No secrets or credentials committed
- [ ] No hardcoded tokens or API keys
- [ ] Proper error handling with `set -euo pipefail`
- [ ] External actions are SHA-pinned
- [ ] Input validation through centralized system
## Error Resolution Strategy
### When Linting Fails
1. **Read the error message carefully** - don't ignore details
2. **Read the linting tool schema** - understand the rules
3. **Compare against schema** - schema is the truth
4. **Fix the actual issue** - don't disable rules
5. **Use autofix first** - `make format` before manual fixes
### When Tests Fail
1. **Fix all errors and warnings** - no exceptions
2. **Ensure proper test coverage** - comprehensive testing required
3. **Verify integration points** - actions must work together
4. **Check validation logic** - centralized validation must pass
### Common Issues and Solutions
- **EditorConfig**: Use exactly 2 spaces, LF endings, UTF-8
- **Python**: Follow Google docstring style, 100 char lines
- **Shell**: Use shellcheck-compliant patterns
- **YAML**: Proper indentation, no trailing spaces
- **Markdown**: Tables formatted, links valid, consistent style
## Never Do These
- Never use `git commit` without explicit user request
- Never use `--no-verify` flags
- Never modify linting configuration to make tests pass
- Never assume linting issues are acceptable
- Never skip testing after code changes
- Never create files unless absolutely necessary
## File Modification Preferences
- **Always prefer editing existing files** over creating new ones
- **Never proactively create documentation** unless requested
- **Read project patterns** before making changes
- **Follow existing conventions** in the codebase
- **Use centralized validation** for all input handling
## Final Verification
After ALL tasks are complete, run the full development cycle:
```bash
make all # Complete workflow: docs, format, lint, test
```
This ensures the project maintains its excellent state and all quality gates pass.

View File

@@ -0,0 +1,76 @@
# Validation System Architecture
## Status: PRODUCTION READY ✅
- 769 tests passing (100%)
- Zero linting issues
- Modular architecture complete
## Architecture
### Core Components
- **BaseValidator**: Abstract interface for all validators
- **ValidatorRegistry**: Dynamic discovery, loads custom validators from `<action>/CustomValidator.py`
- **ConventionMapper**: Auto-detection via 100+ naming patterns (priority-based matching)
### Specialized Validators (9)
`token.py`, `version.py` (SemVer/CalVer), `boolean.py`, `numeric.py`, `docker.py`, `file.py`, `network.py`, `security.py`, `codeql.py`
### Custom Validators (20+)
Actions with complex validation have `CustomValidator.py` in their directory. Registry auto-discovers them.
Examples: `docker-build/CustomValidator.py`, `sync-labels/CustomValidator.py`, `codeql-analysis/CustomValidator.py`
## Convention-Based Detection
Automatic validator selection from input names:
- Priority 100: Exact (`dry-run` → boolean)
- Priority 95: Language-specific (`-python-version` → python_version)
- Priority 90: Suffixes (`-token` → token)
- Priority 85: Contains (`email` → email)
- Priority 80: Prefixes (`is-` → boolean)
## Test Generation
`validate-inputs/scripts/generate-tests.py`:
- Non-destructive (preserves existing tests)
- Intelligent pattern detection for input types
- Template-based scaffolding for validators
- ShellSpec + pytest generation
## Usage
```python
from validators.registry import ValidatorRegistry
validator = ValidatorRegistry().get_validator("docker-build")
result = validator.validate_inputs({"context": ".", "platforms": "linux/amd64"})
```
## File Structure
```text
validate-inputs/
├── validator.py # Main entry
├── validators/ # 9 specialized + base + registry + conventions
├── scripts/
│ ├── update-validators.py # Rule generator
│ └── generate-tests.py # Test generator
└── tests/ # 769 pytest tests
<action>/CustomValidator.py # Action-specific validators
```
## Key Features
- Convention-based auto-detection
- GitHub expression support (`${{ }}`)
- Error propagation between validators
- Security validation (injection, secrets)
- CalVer, SemVer, flexible versioning
- Docker platforms, registries
- Token formats (GitHub, NPM, PyPI)

View File

@@ -31,6 +31,42 @@
- `validate-inputs/` Python validation system + tests
- `*/rules.yml` Auto-generated validation rules
### Memory System
**Location**: `.serena/memories/` (9 consolidated memories for context)
**When to Use**: Read memories at session start or when needed for specific context. Be token-efficient - read only relevant memories for the task.
**Core Memories** (read first for project understanding):
- `repository_overview` 43 actions, categories, structure, status
- `validator_system` Validation architecture, components, usage patterns
- `development_standards` Quality rules, workflows, security, completion checklist
**Reference Guides** (read when working on specific areas):
- `code_style_conventions` EditorConfig, Shell/Python/YAML style, 10 critical prevention rules
- `suggested_commands` Make targets, testing commands, tool usage
- `tech_stack` Python/Node.js/Shell tools, paths, versions
**GitHub Actions Reference** (read when working with workflows):
- `github-workflow-expressions` Expression syntax, contexts, operators, common patterns
- `github-workflow-commands` Workflow commands (outputs, env, logging, masking)
- `github-workflow-secure-use` Security best practices, secrets, injection prevention
**Memory Maintenance**: Update existing memories rather than create new ones. Keep content token-efficient and factual.
### Documentation Locations
**Validation System**: `validate-inputs/docs/` (4 guides: API.md, DEVELOPER_GUIDE.md, ACTION_MAINTAINER.md, README_ARCHITECTURE.md)
**Testing**: `_tests/README.md` (ShellSpec framework, test patterns, running tests)
**Docker Tools**: `_tools/docker-testing-tools/README.md` (CI setup, pre-built testing image)
**See**: `documentation_guide` memory for detailed descriptions and when to read each
## Repository Structure
Flat structure. Each action self-contained with `action.yml`.

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2024 Ismo Vuorinen
Copyright (c) 2024-2025 Ismo Vuorinen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -38,11 +38,12 @@ run: |
### 2. Secret Masking
**Status**: ✅ Implemented in 6 critical actions
**Status**: ✅ Implemented in 7 critical actions
Actions that handle sensitive data use GitHub Actions secret masking to prevent accidental exposure in logs:
- `npm-publish` - NPM authentication tokens
- `docker-publish` - Docker Hub credentials (defense-in-depth masking)
- `docker-publish-hub` - Docker Hub passwords
- `docker-publish-gh` - GitHub tokens
- `csharp-publish` - NuGet API keys
@@ -225,11 +226,11 @@ When security issues are fixed:
- Added comprehensive input validation
- Status: ✅ Complete
### Phase 2: Enhanced Security (2024)
### Phase 2: Enhanced Security (2024-2025)
- Replaced custom Bun installation with official action
- Replaced custom Trivy installation with official action
- Added secret masking to 6 critical actions
- Added secret masking to 7 critical actions (including docker-publish)
- Optimized file hashing in common-cache
- Status: ✅ Complete

View File

@@ -1,6 +1,6 @@
# GitHub Actions Testing Framework
A comprehensive testing framework for validating GitHub Actions in this monorepo. This guide covers everything from basic usage to advanced testing patterns.
A comprehensive testing framework for validating GitHub Actions in this monorepo using ShellSpec and Python-based input validation.
## 🚀 Quick Start
@@ -36,16 +36,15 @@ brew install act # macOS
The testing framework uses a **multi-level testing strategy**:
1. **Unit Tests** - Fast validation of action logic, inputs, and outputs
1. **Unit Tests** - Fast validation of action logic, inputs, and outputs using Python validation
2. **Integration Tests** - Test actions in realistic workflow environments
3. **External Usage Tests** - Validate actions work as `ivuorinen/actions/action-name@main`
### Technology Stack
- **Primary Framework**: [ShellSpec](https://shellspec.info/) - BDD testing for shell scripts
- **Validation**: Python-based input validation via `validate-inputs/validator.py`
- **Local Execution**: [nektos/act](https://github.com/nektos/act) - Run GitHub Actions locally
- **Coverage**: kcov integration for shell script coverage
- **Mocking**: Custom GitHub API and service mocks
- **CI Integration**: GitHub Actions workflows
### Directory Structure
@@ -54,19 +53,20 @@ The testing framework uses a **multi-level testing strategy**:
_tests/
├── README.md # This documentation
├── run-tests.sh # Main test runner script
├── framework/ # Core testing utilities
│ ├── setup.sh # Test environment setup
│ ├── utils.sh # Common testing functions
│ ├── validation_helpers.sh # Validation helper functions
│ ├── validation.py # Python validation utilities
│ └── mocks/ # Mock services (GitHub API, etc.)
├── unit/ # Unit tests by action
│ ├── spec_helper.sh # ShellSpec helper with validation functions
│ ├── version-file-parser/ # Example unit tests
│ ├── node-setup/ # Example unit tests
│ └── ... # One directory per action
├── framework/ # Core testing utilities
│ ├── setup.sh # Test environment setup
│ ├── utils.sh # Common testing functions
│ ├── validation.py # Python validation utilities
│ └── fixtures/ # Test fixtures
├── integration/ # Integration tests
│ ├── workflows/ # Test workflows for nektos/act
── external-usage/ # External reference tests
── external-usage/ # External reference tests
│ └── action-chains/ # Multi-action workflow tests
├── coverage/ # Coverage reports
└── reports/ # Test execution reports
```
@@ -79,44 +79,39 @@ _tests/
#!/usr/bin/env shellspec
# _tests/unit/my-action/validation.spec.sh
Include _tests/framework/utils.sh
Describe "my-action validation"
ACTION_DIR="my-action"
ACTION_FILE="$ACTION_DIR/action.yml"
ACTION_DIR="my-action"
ACTION_FILE="$ACTION_DIR/action.yml"
BeforeAll "init_testing_framework"
Context "input validation"
It "validates all inputs comprehensively"
# Use validation helpers for comprehensive testing
test_boolean_input "verbose"
test_boolean_input "dry-run"
# Numeric range validations (use test_input_validation helper)
test_input_validation "$ACTION_DIR" "max-retries" "1" "success"
test_input_validation "$ACTION_DIR" "max-retries" "10" "success"
test_input_validation "$ACTION_DIR" "timeout" "3600" "success"
# Enum validations (use test_input_validation helper)
test_input_validation "$ACTION_DIR" "strategy" "fast" "success"
test_input_validation "$ACTION_DIR" "format" "json" "success"
# Version validations (use test_input_validation helper)
test_input_validation "$ACTION_DIR" "tool-version" "1.0.0" "success"
# Security and path validations (use test_input_validation helper)
test_input_validation "$ACTION_DIR" "command" "echo test" "success"
test_input_validation "$ACTION_DIR" "working-directory" "." "success"
End
Context "when validating required inputs"
It "accepts valid input"
When call validate_input_python "my-action" "input-name" "valid-value"
The status should be success
End
Context "action structure"
It "has valid structure and metadata"
test_standard_action_structure "$ACTION_FILE" "Expected Action Name"
End
It "rejects invalid input"
When call validate_input_python "my-action" "input-name" "invalid@value"
The status should be failure
End
End
Context "when validating boolean inputs"
It "accepts true"
When call validate_input_python "my-action" "dry-run" "true"
The status should be success
End
It "accepts false"
When call validate_input_python "my-action" "dry-run" "false"
The status should be success
End
It "rejects invalid boolean"
When call validate_input_python "my-action" "dry-run" "maybe"
The status should be failure
End
End
End
```
### Integration Test Example
@@ -149,66 +144,68 @@ jobs:
required-input: 'test-value'
```
## 🛠️ Testing Helpers
## 🛠️ Testing Functions
### Available Validation Helpers
### Primary Validation Function
The framework provides comprehensive validation helpers that handle common testing patterns:
The framework provides one main validation function that uses the Python validation system:
#### Boolean Input Testing
#### validate_input_python
Tests input validation using the centralized Python validator:
```bash
test_boolean_input "verbose" # Tests: true, false, rejects invalid
test_boolean_input "enable-cache"
test_boolean_input "dry-run"
validate_input_python "action-name" "input-name" "test-value"
```
#### Numeric Range Testing
**Examples:**
```bash
# Note: test_numeric_range_input helper is not yet implemented.
# Use test_input_validation with appropriate test values instead:
test_input_validation "$ACTION_DIR" "max-retries" "1" "success" # min value
test_input_validation "$ACTION_DIR" "max-retries" "10" "success" # max value
test_input_validation "$ACTION_DIR" "max-retries" "0" "failure" # below min
test_input_validation "$ACTION_DIR" "timeout" "3600" "success"
test_input_validation "$ACTION_DIR" "parallel-jobs" "8" "success"
# Boolean validation
validate_input_python "pre-commit" "dry-run" "true" # success
validate_input_python "pre-commit" "dry-run" "false" # success
validate_input_python "pre-commit" "dry-run" "maybe" # failure
# Version validation
validate_input_python "node-setup" "node-version" "18.0.0" # success
validate_input_python "node-setup" "node-version" "v1.2.3" # success
validate_input_python "node-setup" "node-version" "invalid" # failure
# Token validation
validate_input_python "npm-publish" "npm-token" "ghp_123..." # success
validate_input_python "npm-publish" "npm-token" "invalid" # failure
# Docker validation
validate_input_python "docker-build" "image-name" "myapp" # success
validate_input_python "docker-build" "tag" "v1.0.0" # success
# Path validation (security)
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
```
#### Version Testing
### Helper Functions from spec_helper.sh
```bash
# Note: test_version_input helper is not yet implemented.
# Use test_input_validation with appropriate test values instead:
test_input_validation "$ACTION_DIR" "version" "1.0.0" "success" # semver
test_input_validation "$ACTION_DIR" "version" "v1.0.0" "success" # v-prefix
test_input_validation "$ACTION_DIR" "version" "1.0.0-rc.1" "success" # pre-release
test_input_validation "$ACTION_DIR" "tool-version" "2.3.4" "success"
```
# Setup/cleanup
setup_default_inputs "action-name" "input-name" # Set required defaults
cleanup_default_inputs "action-name" "input-name" # Clean up defaults
shellspec_setup_test_env "test-name" # Setup test environment
shellspec_cleanup_test_env "test-name" # Cleanup test environment
#### Enum Testing
# Mock execution
shellspec_mock_action_run "action-dir" key1 value1 key2 value2
shellspec_validate_action_output "expected-key" "expected-value"
```bash
# Note: test_enum_input helper is not yet implemented.
# Use test_input_validation with appropriate test values instead:
test_input_validation "$ACTION_DIR" "strategy" "linear" "success"
test_input_validation "$ACTION_DIR" "strategy" "exponential" "success"
test_input_validation "$ACTION_DIR" "strategy" "invalid" "failure"
test_input_validation "$ACTION_DIR" "format" "json" "success"
test_input_validation "$ACTION_DIR" "format" "yaml" "success"
```
#### Docker-Specific Testing
```bash
# Available framework helpers:
test_input_validation "$action_dir" "$input_name" "$test_value" "$expected_result"
test_action_outputs "$action_dir"
test_external_usage "$action_dir"
# Note: Docker-specific helpers (test_docker_image_input, test_docker_tag_input,
# test_docker_platforms_input) are referenced in examples but not yet implemented.
# Use test_input_validation with appropriate test values instead.
# Action metadata
validate_action_yml "action.yml" # Validate YAML structure
get_action_inputs "action.yml" # Get action inputs
get_action_outputs "action.yml" # Get action outputs
get_action_name "action.yml" # Get action name
```
### Complete Action Validation Example
@@ -218,41 +215,47 @@ Describe "comprehensive-action validation"
ACTION_DIR="comprehensive-action"
ACTION_FILE="$ACTION_DIR/action.yml"
Context "complete input validation"
It "validates all input types systematically"
# Boolean inputs
test_boolean_input "verbose"
test_boolean_input "enable-cache"
test_boolean_input "dry-run"
Context "when validating all input types"
It "validates boolean inputs"
When call validate_input_python "$ACTION_DIR" "verbose" "true"
The status should be success
# Numeric ranges (use test_input_validation helper)
test_input_validation "$ACTION_DIR" "max-retries" "1" "success"
test_input_validation "$ACTION_DIR" "max-retries" "10" "success"
test_input_validation "$ACTION_DIR" "timeout" "3600" "success"
test_input_validation "$ACTION_DIR" "parallel-jobs" "8" "success"
When call validate_input_python "$ACTION_DIR" "verbose" "false"
The status should be success
# Enums (use test_input_validation helper)
test_input_validation "$ACTION_DIR" "strategy" "fast" "success"
test_input_validation "$ACTION_DIR" "format" "json" "success"
When call validate_input_python "$ACTION_DIR" "verbose" "invalid"
The status should be failure
End
# Docker-specific (use test_input_validation helper)
test_input_validation "$ACTION_DIR" "image-name" "myapp:latest" "success"
test_input_validation "$ACTION_DIR" "tag" "1.0.0" "success"
test_input_validation "$ACTION_DIR" "platforms" "linux/amd64,linux/arm64" "success"
It "validates numeric inputs"
When call validate_input_python "$ACTION_DIR" "max-retries" "3"
The status should be success
# Security validation (use test_input_validation helper)
test_input_validation "$ACTION_DIR" "command" "echo test" "success"
test_input_validation "$ACTION_DIR" "build-args" "ARG1=value" "success"
When call validate_input_python "$ACTION_DIR" "max-retries" "999"
The status should be failure
End
# Paths (use test_input_validation helper)
test_input_validation "$ACTION_DIR" "working-directory" "." "success"
test_input_validation "$ACTION_DIR" "output-directory" "./output" "success"
It "validates version inputs"
When call validate_input_python "$ACTION_DIR" "tool-version" "1.0.0"
The status should be success
# Versions (use test_input_validation helper)
test_input_validation "$ACTION_DIR" "tool-version" "1.0.0" "success"
When call validate_input_python "$ACTION_DIR" "tool-version" "v1.2.3-rc.1"
The status should be success
End
# Action structure
test_standard_action_structure "$ACTION_FILE" "Comprehensive Action"
It "validates security patterns"
When call validate_input_python "$ACTION_DIR" "command" "echo test"
The status should be success
When call validate_input_python "$ACTION_DIR" "command" "rm -rf /; "
The status should be failure
End
End
Context "when validating action structure"
It "has valid YAML structure"
When call validate_action_yml "$ACTION_FILE"
The status should be success
End
End
End
@@ -265,45 +268,37 @@ End
Focus on version detection and environment setup:
```bash
Context "version detection"
Context "when detecting versions"
It "detects version from config files"
create_mock_node_repo # or appropriate repo type
# Test version detection logic
export INPUT_LANGUAGE="node"
echo "detected-version=18.0.0" >> "$GITHUB_OUTPUT"
When call validate_action_output "detected-version" "18.0.0"
When call validate_input_python "node-setup" "node-version" "18.0.0"
The status should be success
End
It "falls back to default when no version found"
# Use test_input_validation helper for version validation
test_input_validation "$ACTION_DIR" "default-version" "1.0.0" "success"
It "accepts default version"
When call validate_input_python "python-version-detect" "default-version" "3.11"
The status should be success
End
End
```
### Linting Actions (eslint-fix, prettier-fix, etc.)
Focus on file processing and fix capabilities:
Focus on file processing and security:
```bash
Context "file processing"
BeforeEach "setup_test_env 'lint-test'"
AfterEach "cleanup_test_env 'lint-test'"
Context "when processing files"
It "validates working directory"
When call validate_input_python "eslint-fix" "working-directory" "."
The status should be success
End
It "validates inputs and processes files"
test_boolean_input "fix-only"
# Use test_input_validation helper for path and security validations
test_input_validation "$ACTION_DIR" "working-directory" "." "success"
test_input_validation "$ACTION_DIR" "custom-command" "echo test" "success"
It "rejects path traversal"
When call validate_input_python "eslint-fix" "working-directory" "../etc"
The status should be failure
End
# Mock file processing
echo "files_changed=3" >> "$GITHUB_OUTPUT"
echo "status=changes_made" >> "$GITHUB_OUTPUT"
When call validate_action_output "status" "changes_made"
It "validates boolean flags"
When call validate_input_python "eslint-fix" "fix-only" "true"
The status should be success
End
End
@@ -311,25 +306,22 @@ End
### Build Actions (docker-build, go-build, etc.)
Focus on build processes and artifact generation:
Focus on build configuration:
```bash
Context "build process"
BeforeEach "setup_test_env 'build-test'"
AfterEach "cleanup_test_env 'build-test'"
Context "when building"
It "validates image name"
When call validate_input_python "docker-build" "image-name" "myapp"
The status should be success
End
It "validates build inputs"
# Use test_input_validation helper for Docker inputs
test_input_validation "$ACTION_DIR" "image-name" "myapp:latest" "success"
test_input_validation "$ACTION_DIR" "tag" "1.0.0" "success"
test_input_validation "$ACTION_DIR" "platforms" "linux/amd64,linux/arm64" "success"
test_input_validation "$ACTION_DIR" "parallel-builds" "8" "success"
It "validates tag format"
When call validate_input_python "docker-build" "tag" "v1.0.0"
The status should be success
End
# Mock successful build
echo "build-status=success" >> "$GITHUB_OUTPUT"
echo "build-time=45" >> "$GITHUB_OUTPUT"
When call validate_action_output "build-status" "success"
It "validates platforms"
When call validate_input_python "docker-build" "platforms" "linux/amd64,linux/arm64"
The status should be success
End
End
@@ -337,25 +329,22 @@ End
### Publishing Actions (npm-publish, docker-publish, etc.)
Focus on registry interactions using mocks:
Focus on credentials and registry validation:
```bash
Context "publishing"
BeforeEach "setup_mock_environment"
AfterEach "cleanup_mock_environment"
Context "when publishing"
It "validates token format"
When call validate_input_python "npm-publish" "npm-token" "ghp_123456789012345678901234567890123456"
The status should be success
End
It "validates publishing inputs"
# Use test_input_validation helper for version, security, and enum validations
test_input_validation "$ACTION_DIR" "package-version" "1.0.0" "success"
test_input_validation "$ACTION_DIR" "registry-token" "ghp_test123" "success"
test_input_validation "$ACTION_DIR" "registry" "npm" "success"
test_input_validation "$ACTION_DIR" "registry" "github" "success"
It "rejects invalid token"
When call validate_input_python "npm-publish" "npm-token" "invalid-token"
The status should be failure
End
# Mock successful publish
echo "publish-status=success" >> "$GITHUB_OUTPUT"
echo "registry-url=https://registry.npmjs.org/" >> "$GITHUB_OUTPUT"
When call validate_action_output "publish-status" "success"
It "validates version"
When call validate_input_python "npm-publish" "package-version" "1.0.0"
The status should be success
End
End
@@ -409,33 +398,33 @@ make test-action ACTION=name # Test specific action
mkdir -p _tests/unit/new-action
```
2. **Write Comprehensive Unit Tests**
2. **Write Unit Tests**
```bash
# Copy template and customize
cp _tests/unit/version-file-parser/validation.spec.sh \
_tests/unit/new-action/validation.spec.sh
# _tests/unit/new-action/validation.spec.sh
#!/usr/bin/env shellspec
Describe "new-action validation"
ACTION_DIR="new-action"
ACTION_FILE="$ACTION_DIR/action.yml"
Context "when validating inputs"
It "validates required input"
When call validate_input_python "new-action" "required-input" "value"
The status should be success
End
End
End
```
3. **Use Validation Helpers**
3. **Create Integration Test**
```bash
# Focus on using helpers for comprehensive coverage
test_boolean_input "verbose"
# Use test_input_validation helper for numeric, security, and other validations
test_input_validation "$ACTION_DIR" "timeout" "3600" "success"
test_input_validation "$ACTION_DIR" "command" "echo test" "success"
test_standard_action_structure "$ACTION_FILE" "New Action"
# _tests/integration/workflows/new-action-test.yml
# (See integration test example above)
```
4. **Create Integration Test**
```bash
cp _tests/integration/workflows/version-file-parser-test.yml \
_tests/integration/workflows/new-action-test.yml
```
5. **Test Your Tests**
4. **Test Your Tests**
```bash
make test-action ACTION=new-action
@@ -443,7 +432,7 @@ make test-action ACTION=name # Test specific action
### Pull Request Checklist
- [ ] Tests use validation helpers for common patterns
- [ ] Tests use `validate_input_python` for input validation
- [ ] All test types pass locally (`make test`)
- [ ] Integration test workflow created
- [ ] Security testing included for user inputs
@@ -453,24 +442,21 @@ make test-action ACTION=name # Test specific action
## 💡 Best Practices
### 1. Use Validation Helpers
### 1. Use validate_input_python for All Input Testing
✅ **Good**:
```bash
test_boolean_input "verbose"
# Use test_input_validation helper for other validations
test_input_validation "$ACTION_DIR" "timeout" "3600" "success"
test_input_validation "$ACTION_DIR" "format" "json" "success"
When call validate_input_python "my-action" "verbose" "true"
The status should be success
```
❌ **Avoid**:
```bash
# Don't write manual tests for boolean inputs when test_boolean_input exists
When call test_input_validation "$ACTION_DIR" "verbose" "true" "success"
When call test_input_validation "$ACTION_DIR" "verbose" "false" "success"
# Use test_boolean_input "verbose" instead
# Don't manually test validation - use the Python validator
export INPUT_VERBOSE="true"
python3 validate-inputs/validator.py
```
### 2. Group Related Validations
@@ -478,26 +464,33 @@ When call test_input_validation "$ACTION_DIR" "verbose" "false" "success"
✅ **Good**:
```bash
Context "complete input validation"
It "validates all input types"
test_boolean_input "verbose"
# Use test_input_validation helper for other validations
test_input_validation "$ACTION_DIR" "timeout" "3600" "success"
test_input_validation "$ACTION_DIR" "format" "json" "success"
test_input_validation "$ACTION_DIR" "command" "echo test" "success"
Context "when validating configuration"
It "accepts valid boolean"
When call validate_input_python "my-action" "dry-run" "true"
The status should be success
End
It "accepts valid version"
When call validate_input_python "my-action" "tool-version" "1.0.0"
The status should be success
End
End
```
### 3. Include Security Testing
### 3. Always Include Security Testing
✅ **Always include**:
```bash
# Use test_input_validation helper for security and path validations
test_input_validation "$ACTION_DIR" "command" "echo test" "success"
test_input_validation "$ACTION_DIR" "user-script" "#!/bin/bash" "success"
test_input_validation "$ACTION_DIR" "working-directory" "." "success"
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
End
```
### 4. Write Descriptive Test Names
@@ -528,46 +521,34 @@ It "works correctly"
### Test Environment Setup
```bash
# Setup test environment
setup_test_env "test-name"
# Create mock repositories
create_mock_repo "node" # Node.js project
create_mock_repo "php" # PHP project
create_mock_repo "python" # Python project
create_mock_repo "go" # Go project
create_mock_repo "dotnet" # .NET project
# Cleanup
cleanup_test_env "test-name"
```
### Mock Services
Built-in mocks for external services:
- **GitHub API** - Repository, releases, packages, workflows
- **NPM Registry** - Package publishing and retrieval
- **Docker Registry** - Image push/pull operations
- **Container Registries** - GitHub Container Registry, Docker Hub
### Available Environment Variables
The framework automatically sets up test environments via `spec_helper.sh`:
```bash
# Test environment paths
$TEST_WORKSPACE # Current test workspace
$GITHUB_OUTPUT # Mock GitHub outputs file
$GITHUB_ENV # Mock GitHub environment file
$GITHUB_STEP_SUMMARY # Mock step summary file
# Automatic setup on load
- GitHub Actions environment variables
- Temporary directories
- Mock GITHUB_OUTPUT files
- Default required inputs for actions
# Test framework paths
$TEST_ROOT # _tests/ directory
$FRAMEWORK_DIR # _tests/framework/ directory
$FIXTURES_DIR # _tests/framework/fixtures/
$MOCKS_DIR # _tests/framework/mocks/
# Available variables
$PROJECT_ROOT # Repository root
$TEST_ROOT # _tests/ directory
$FRAMEWORK_DIR # _tests/framework/
$FIXTURES_DIR # _tests/framework/fixtures/
$TEMP_DIR # Temporary test directory
$GITHUB_OUTPUT # Mock outputs file
$GITHUB_ENV # Mock environment file
```
### Python Validation Integration
All input validation uses the centralized Python validation system from `validate-inputs/`:
- Convention-based automatic validation
- 9 specialized validators (Boolean, Version, Token, Numeric, File, Network, Docker, Security, CodeQL)
- Custom validator support per action
- Injection and security pattern detection
## 🚨 Troubleshooting
### Common Issues
@@ -618,58 +599,67 @@ find _tests/ -name "*.sh" -exec chmod +x {} \;
shellspec _tests/unit/my-action/validation.spec.sh
```
3. **Check Test Output**
3. **Enable Debug Mode**
```bash
export SHELLSPEC_DEBUG=1
shellspec _tests/unit/my-action/validation.spec.sh
```
4. **Check Test Output**
```bash
# Test results stored in _tests/reports/
cat _tests/reports/unit/my-action.txt
```
4. **Debug Mock Environment**
```bash
# Enable mock debugging
export MOCK_DEBUG=true
```
## 📚 Resources
- [ShellSpec Documentation](https://shellspec.info/)
- [nektos/act Documentation](https://nektosact.com/)
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
- [Testing GitHub Actions Best Practices](https://docs.github.com/en/actions/creating-actions/creating-a-composite-action#testing-your-action)
---
- [validate-inputs Documentation](../validate-inputs/docs/README_ARCHITECTURE.md)
## Framework Development
### Adding New Framework Features
### Framework File Structure
1. **New Test Utilities**
```text
_tests/
├── unit/
│ └── spec_helper.sh # ShellSpec configuration and helpers
├── framework/
│ ├── setup.sh # Test environment initialization
│ ├── utils.sh # Common utility functions
│ ├── validation.py # Python validation helpers
│ └── fixtures/ # Test fixtures
└── integration/
├── workflows/ # Integration test workflows
├── external-usage/ # External reference tests
└── action-chains/ # Multi-action tests
```
```bash
# Add to _tests/framework/utils.sh
your_new_function() {
local param="$1"
# Implementation
}
### Available Functions
# Export for availability
export -f your_new_function
```
**From spec_helper.sh (\_tests/unit/spec_helper.sh):**
2. **New Mock Services**
- `validate_input_python(action, input_name, value)` - Main validation function
- `setup_default_inputs(action, input_name)` - Set default required inputs
- `cleanup_default_inputs(action, input_name)` - Clean up default inputs
- `shellspec_setup_test_env(name)` - Setup test environment
- `shellspec_cleanup_test_env(name)` - Cleanup test environment
- `shellspec_mock_action_run(action_dir, ...)` - Mock action execution
- `shellspec_validate_action_output(key, value)` - Validate outputs
```bash
# Create _tests/framework/mocks/new-service.sh
# Follow existing patterns in github-api.sh
```
**From utils.sh (\_tests/framework/utils.sh):**
3. **New Validation Helpers**
- `validate_action_yml(file)` - Validate action YAML
- `get_action_inputs(file)` - Extract action inputs
- `get_action_outputs(file)` - Extract action outputs
- `get_action_name(file)` - Get action name
- `test_input_validation(dir, name, value, expected)` - Test input
- `test_action_outputs(dir)` - Test action outputs
- `test_external_usage(dir)` - Test external usage
```bash
# Add to _tests/framework/validation_helpers.sh
# Update this documentation
```
**Last Updated:** August 17, 2025
**Last Updated:** October 15, 2025

View File

@@ -0,0 +1,471 @@
---
name: Integration Test - Common Cache
on:
workflow_dispatch:
push:
paths:
- 'common-cache/**'
- '_tests/integration/workflows/common-cache-test.yml'
jobs:
test-common-cache-key-generation:
name: Test Cache Key Generation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test basic key generation
run: |
RUNNER_OS="Linux"
CACHE_TYPE="npm"
KEY_PREFIX=""
cache_key="$RUNNER_OS"
[ -n "$CACHE_TYPE" ] && cache_key="${cache_key}-${CACHE_TYPE}"
expected="Linux-npm"
if [[ "$cache_key" != "$expected" ]]; then
echo "❌ ERROR: Expected '$expected', got '$cache_key'"
exit 1
fi
echo "✓ Basic cache key generation works"
- name: Test key with prefix
run: |
RUNNER_OS="Linux"
CACHE_TYPE="npm"
KEY_PREFIX="node-20"
cache_key="$RUNNER_OS"
[ -n "$KEY_PREFIX" ] && cache_key="${cache_key}-${KEY_PREFIX}"
[ -n "$CACHE_TYPE" ] && cache_key="${cache_key}-${CACHE_TYPE}"
expected="Linux-node-20-npm"
if [[ "$cache_key" != "$expected" ]]; then
echo "❌ ERROR: Expected '$expected', got '$cache_key'"
exit 1
fi
echo "✓ Cache key with prefix works"
- name: Test OS-specific keys
run: |
for os in "Linux" "macOS" "Windows"; do
CACHE_TYPE="test"
cache_key="$os-$CACHE_TYPE"
if [[ ! "$cache_key" =~ ^(Linux|macOS|Windows)-test$ ]]; then
echo "❌ ERROR: Invalid key for OS $os: $cache_key"
exit 1
fi
echo "✓ OS-specific key for $os: $cache_key"
done
test-common-cache-file-hashing:
name: Test File Hashing
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create test files
run: |
mkdir -p test-cache
cd test-cache
echo "content1" > file1.txt
echo "content2" > file2.txt
echo "content3" > file3.txt
- name: Test single file hash
run: |
cd test-cache
file_hash=$(cat file1.txt | sha256sum | cut -d' ' -f1)
if [[ ! "$file_hash" =~ ^[a-f0-9]{64}$ ]]; then
echo "❌ ERROR: Invalid hash format: $file_hash"
exit 1
fi
echo "✓ Single file hash: $file_hash"
- name: Test multiple file hash
run: |
cd test-cache
multi_hash=$(cat file1.txt file2.txt file3.txt | sha256sum | cut -d' ' -f1)
if [[ ! "$multi_hash" =~ ^[a-f0-9]{64}$ ]]; then
echo "❌ ERROR: Invalid hash format: $multi_hash"
exit 1
fi
echo "✓ Multiple file hash: $multi_hash"
- name: Test hash changes with content
run: |
cd test-cache
# Get initial hash
hash1=$(cat file1.txt | sha256sum | cut -d' ' -f1)
# Modify file
echo "modified" > file1.txt
# Get new hash
hash2=$(cat file1.txt | sha256sum | cut -d' ' -f1)
if [[ "$hash1" == "$hash2" ]]; then
echo "❌ ERROR: Hash should change when content changes"
exit 1
fi
echo "✓ Hash changes with content modification"
- name: Test comma-separated file list processing
run: |
cd test-cache
KEY_FILES="file1.txt,file2.txt,file3.txt"
IFS=',' read -ra FILES <<< "$KEY_FILES"
existing_files=()
for file in "${FILES[@]}"; do
file=$(echo "$file" | xargs)
if [ -f "$file" ]; then
existing_files+=("$file")
fi
done
if [ ${#existing_files[@]} -ne 3 ]; then
echo "❌ ERROR: Should find 3 files, found ${#existing_files[@]}"
exit 1
fi
echo "✓ Comma-separated file list processing works"
- name: Test missing file handling
run: |
cd test-cache
KEY_FILES="file1.txt,missing.txt,file2.txt"
IFS=',' read -ra FILES <<< "$KEY_FILES"
existing_files=()
for file in "${FILES[@]}"; do
file=$(echo "$file" | xargs)
if [ -f "$file" ]; then
existing_files+=("$file")
fi
done
if [ ${#existing_files[@]} -ne 2 ]; then
echo "❌ ERROR: Should find 2 files, found ${#existing_files[@]}"
exit 1
fi
echo "✓ Missing files correctly skipped"
test-common-cache-env-vars:
name: Test Environment Variables
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test single env var inclusion
run: |
export NODE_VERSION="20.9.0"
ENV_VARS="NODE_VERSION"
IFS=',' read -ra VARS <<< "$ENV_VARS"
env_hash=""
for var in "${VARS[@]}"; do
if [ -n "${!var}" ]; then
env_hash="${env_hash}-${var}-${!var}"
fi
done
expected="-NODE_VERSION-20.9.0"
if [[ "$env_hash" != "$expected" ]]; then
echo "❌ ERROR: Expected '$expected', got '$env_hash'"
exit 1
fi
echo "✓ Single env var inclusion works"
- name: Test multiple env vars
run: |
export NODE_VERSION="20.9.0"
export PACKAGE_MANAGER="npm"
ENV_VARS="NODE_VERSION,PACKAGE_MANAGER"
IFS=',' read -ra VARS <<< "$ENV_VARS"
env_hash=""
for var in "${VARS[@]}"; do
if [ -n "${!var}" ]; then
env_hash="${env_hash}-${var}-${!var}"
fi
done
expected="-NODE_VERSION-20.9.0-PACKAGE_MANAGER-npm"
if [[ "$env_hash" != "$expected" ]]; then
echo "❌ ERROR: Expected '$expected', got '$env_hash'"
exit 1
fi
echo "✓ Multiple env vars inclusion works"
- name: Test undefined env var skipping
run: |
export NODE_VERSION="20.9.0"
ENV_VARS="NODE_VERSION,UNDEFINED_VAR"
IFS=',' read -ra VARS <<< "$ENV_VARS"
env_hash=""
for var in "${VARS[@]}"; do
if [ -n "${!var}" ]; then
env_hash="${env_hash}-${var}-${!var}"
fi
done
# Should only include NODE_VERSION
expected="-NODE_VERSION-20.9.0"
if [[ "$env_hash" != "$expected" ]]; then
echo "❌ ERROR: Expected '$expected', got '$env_hash'"
exit 1
fi
echo "✓ Undefined env vars correctly skipped"
test-common-cache-path-processing:
name: Test Path Processing
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test single path
run: |
CACHE_PATHS="~/.npm"
IFS=',' read -ra PATHS <<< "$CACHE_PATHS"
if [ ${#PATHS[@]} -ne 1 ]; then
echo "❌ ERROR: Should have 1 path, got ${#PATHS[@]}"
exit 1
fi
echo "✓ Single path processing works"
- name: Test multiple paths
run: |
CACHE_PATHS="~/.npm,~/.yarn/cache,node_modules"
IFS=',' read -ra PATHS <<< "$CACHE_PATHS"
if [ ${#PATHS[@]} -ne 3 ]; then
echo "❌ ERROR: Should have 3 paths, got ${#PATHS[@]}"
exit 1
fi
echo "✓ Multiple paths processing works"
- name: Test path with spaces (trimming)
run: |
CACHE_PATHS=" ~/.npm , ~/.yarn/cache , node_modules "
IFS=',' read -ra PATHS <<< "$CACHE_PATHS"
trimmed_paths=()
for path in "${PATHS[@]}"; do
trimmed=$(echo "$path" | xargs)
trimmed_paths+=("$trimmed")
done
# Check first path is trimmed
if [[ "${trimmed_paths[0]}" != "~/.npm" ]]; then
echo "❌ ERROR: Path not trimmed: '${trimmed_paths[0]}'"
exit 1
fi
echo "✓ Path trimming works"
test-common-cache-complete-key-generation:
name: Test Complete Key Generation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create test files
run: |
mkdir -p test-complete
cd test-complete
echo "package-lock content" > package-lock.json
- name: Test complete cache key with all components
run: |
cd test-complete
RUNNER_OS="Linux"
CACHE_TYPE="npm"
KEY_PREFIX="node-20"
# Generate file hash
files_hash=$(cat package-lock.json | sha256sum | cut -d' ' -f1)
# Generate env hash
export NODE_VERSION="20.9.0"
env_hash="-NODE_VERSION-20.9.0"
# Generate final key
cache_key="$RUNNER_OS"
[ -n "$KEY_PREFIX" ] && cache_key="${cache_key}-${KEY_PREFIX}"
[ -n "$CACHE_TYPE" ] && cache_key="${cache_key}-${CACHE_TYPE}"
[ -n "$files_hash" ] && cache_key="${cache_key}-${files_hash}"
[ -n "$env_hash" ] && cache_key="${cache_key}${env_hash}"
echo "Generated cache key: $cache_key"
# Verify structure
if [[ ! "$cache_key" =~ ^Linux-node-20-npm-[a-f0-9]{64}-NODE_VERSION-20\.9\.0$ ]]; then
echo "❌ ERROR: Invalid cache key structure: $cache_key"
exit 1
fi
echo "✓ Complete cache key generation works"
test-common-cache-restore-keys:
name: Test Restore Keys
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test single restore key
run: |
RESTORE_KEYS="Linux-npm-"
if [[ -z "$RESTORE_KEYS" ]]; then
echo "❌ ERROR: Restore keys should not be empty"
exit 1
fi
echo "✓ Single restore key: $RESTORE_KEYS"
- name: Test multiple restore keys
run: |
RESTORE_KEYS="Linux-node-20-npm-,Linux-node-npm-,Linux-npm-"
IFS=',' read -ra KEYS <<< "$RESTORE_KEYS"
if [ ${#KEYS[@]} -ne 3 ]; then
echo "❌ ERROR: Should have 3 restore keys, got ${#KEYS[@]}"
exit 1
fi
echo "✓ Multiple restore keys work"
test-common-cache-type-specific-scenarios:
name: Test Type-Specific Scenarios
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test NPM cache key
run: |
TYPE="npm"
FILES="package-lock.json"
PATHS="~/.npm,node_modules"
echo "✓ NPM cache configuration valid"
echo " Type: $TYPE"
echo " Key files: $FILES"
echo " Paths: $PATHS"
- name: Test Composer cache key
run: |
TYPE="composer"
FILES="composer.lock"
PATHS="~/.composer/cache,vendor"
echo "✓ Composer cache configuration valid"
echo " Type: $TYPE"
echo " Key files: $FILES"
echo " Paths: $PATHS"
- name: Test Go cache key
run: |
TYPE="go"
FILES="go.sum"
PATHS="~/go/pkg/mod,~/.cache/go-build"
echo "✓ Go cache configuration valid"
echo " Type: $TYPE"
echo " Key files: $FILES"
echo " Paths: $PATHS"
- name: Test Pip cache key
run: |
TYPE="pip"
FILES="requirements.txt"
PATHS="~/.cache/pip"
echo "✓ Pip cache configuration valid"
echo " Type: $TYPE"
echo " Key files: $FILES"
echo " Paths: $PATHS"
test-common-cache-edge-cases:
name: Test Edge Cases
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test empty prefix
run: |
KEY_PREFIX=""
cache_key="Linux"
[ -n "$KEY_PREFIX" ] && cache_key="${cache_key}-${KEY_PREFIX}"
if [[ "$cache_key" != "Linux" ]]; then
echo "❌ ERROR: Empty prefix should not modify key"
exit 1
fi
echo "✓ Empty prefix handling works"
- name: Test no key files
run: |
KEY_FILES=""
files_hash=""
if [ -n "$KEY_FILES" ]; then
echo "❌ ERROR: Should detect empty key files"
exit 1
fi
echo "✓ No key files handling works"
- name: Test no env vars
run: |
ENV_VARS=""
env_hash=""
if [ -n "$ENV_VARS" ]; then
echo "❌ ERROR: Should detect empty env vars"
exit 1
fi
echo "✓ No env vars handling works"
integration-test-summary:
name: Integration Test Summary
runs-on: ubuntu-latest
needs:
- test-common-cache-key-generation
- test-common-cache-file-hashing
- test-common-cache-env-vars
- test-common-cache-path-processing
- test-common-cache-complete-key-generation
- test-common-cache-restore-keys
- test-common-cache-type-specific-scenarios
- test-common-cache-edge-cases
steps:
- name: Summary
run: |
echo "=========================================="
echo "Common Cache Integration Tests - PASSED"
echo "=========================================="
echo ""
echo "✓ Cache key generation tests"
echo "✓ File hashing tests"
echo "✓ Environment variable tests"
echo "✓ Path processing tests"
echo "✓ Complete key generation tests"
echo "✓ Restore keys tests"
echo "✓ Type-specific scenario tests"
echo "✓ Edge case tests"
echo ""
echo "All common-cache integration tests completed successfully!"

View File

@@ -0,0 +1,186 @@
---
name: Test Docker Build & Publish Integration
on:
workflow_dispatch:
push:
paths:
- 'docker-build/**'
- 'docker-publish/**'
- 'docker-publish-gh/**'
- 'docker-publish-hub/**'
- '_tests/integration/workflows/docker-build-publish-test.yml'
jobs:
test-docker-build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create test Dockerfile
run: |
cat > Dockerfile <<EOF
FROM alpine:3.19
RUN apk add --no-cache bash
COPY test.sh /test.sh
RUN chmod +x /test.sh
CMD ["/test.sh"]
EOF
cat > test.sh <<EOF
#!/bin/bash
echo "Test container is running"
EOF
- name: Test docker-build action
id: build
uses: ./docker-build
with:
image-name: 'test-image'
tag: 'test-tag'
dockerfile: './Dockerfile'
context: '.'
platforms: 'linux/amd64'
push: 'false'
scan-image: 'false'
- name: Validate build outputs
run: |
echo "Build outputs:"
echo " Image Digest: ${{ steps.build.outputs.image-digest }}"
echo " Build Time: ${{ steps.build.outputs.build-time }}"
echo " Platforms: ${{ steps.build.outputs.platforms }}"
# Validate that we got a digest
if [[ -z "${{ steps.build.outputs.image-digest }}" ]]; then
echo "❌ ERROR: No image digest output"
exit 1
fi
# Validate digest format (sha256:...)
if ! echo "${{ steps.build.outputs.image-digest }}" | grep -E '^sha256:[a-f0-9]{64}'; then
echo "❌ ERROR: Invalid digest format: ${{ steps.build.outputs.image-digest }}"
exit 1
fi
echo "✅ Docker build validation passed"
test-docker-inputs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create test Dockerfile
run: |
cat > Dockerfile <<EOF
FROM alpine:3.19
CMD ["echo", "test"]
EOF
- name: Test with build-args
id: build-with-args
uses: ./docker-build
with:
image-name: 'test-build-args'
tag: 'latest'
dockerfile: './Dockerfile'
context: '.'
build-args: |
ARG1=value1
ARG2=value2
platforms: 'linux/amd64'
push: 'false'
scan-image: 'false'
- name: Validate build-args handling
run: |
if [[ -z "${{ steps.build-with-args.outputs.image-digest }}" ]]; then
echo "❌ ERROR: Build with build-args failed"
exit 1
fi
echo "✅ Build-args handling validated"
test-platform-detection:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create test Dockerfile
run: |
cat > Dockerfile <<EOF
FROM alpine:3.19
CMD ["echo", "multi-platform test"]
EOF
- name: Test multi-platform build
id: multi-platform
uses: ./docker-build
with:
image-name: 'test-multiplatform'
tag: 'latest'
dockerfile: './Dockerfile'
context: '.'
platforms: 'linux/amd64,linux/arm64'
push: 'false'
scan-image: 'false'
- name: Validate platform matrix output
run: |
echo "Platform Matrix: ${{ steps.multi-platform.outputs.platform-matrix }}"
# Check that we got platform results
if [[ -z "${{ steps.multi-platform.outputs.platform-matrix }}" ]]; then
echo "⚠️ WARNING: No platform matrix output (may be expected for local builds)"
else
echo "✅ Platform matrix generated"
fi
echo "✅ Multi-platform build validated"
test-input-validation:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test invalid tag format
id: invalid-tag
uses: ./docker-build
with:
image-name: 'test-image'
tag: 'INVALID TAG WITH SPACES'
dockerfile: './Dockerfile'
context: '.'
platforms: 'linux/amd64'
push: 'false'
continue-on-error: true
- name: Validate tag validation
run: |
if [ "${{ steps.invalid-tag.outcome }}" != "failure" ]; then
echo "❌ ERROR: Invalid tag should have failed validation"
exit 1
fi
echo "✅ Tag validation works correctly"
- name: Test invalid image name
id: invalid-image
uses: ./docker-build
with:
image-name: 'UPPERCASE_NOT_ALLOWED'
tag: 'latest'
dockerfile: './Dockerfile'
context: '.'
platforms: 'linux/amd64'
push: 'false'
continue-on-error: true
- name: Validate image name validation
run: |
if [ "${{ steps.invalid-image.outcome }}" != "failure" ]; then
echo "❌ ERROR: Invalid image name should have failed validation"
exit 1
fi
echo "✅ Image name validation works correctly"

View File

@@ -0,0 +1,440 @@
---
name: Integration Test - GitHub Release
on:
workflow_dispatch:
push:
paths:
- 'github-release/**'
- '_tests/integration/workflows/github-release-test.yml'
jobs:
test-github-release-validation:
name: Test Input Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test invalid version format
run: |
VERSION='not.a.version'
if [[ "$VERSION" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
echo "❌ ERROR: Invalid version format should have failed"
exit 1
fi
echo "✓ Invalid version format correctly rejected"
- name: Test version with alphabetic characters
run: |
VERSION='abc.def.ghi'
if [[ "$VERSION" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
echo "❌ ERROR: Alphabetic version should have failed"
exit 1
fi
echo "✓ Alphabetic version correctly rejected"
- name: Test valid version formats
run: |
for version in "1.2.3" "v1.2.3" "1.0.0-alpha" "2.0.0+build"; do
if ! [[ "$version" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
echo "❌ ERROR: Valid version '$version' should have passed"
exit 1
fi
echo "✓ Valid version '$version' accepted"
done
test-github-release-version-formats:
name: Test Version Format Support
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test basic SemVer (dry run)
run: |
echo "Testing basic SemVer format: 1.2.3"
VERSION="1.2.3"
if ! [[ "$VERSION" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
echo "❌ ERROR: Valid version rejected"
exit 1
fi
echo "✓ Basic SemVer format accepted"
- name: Test SemVer with v prefix
run: |
echo "Testing SemVer with v prefix: v1.2.3"
VERSION="v1.2.3"
if ! [[ "$VERSION" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
echo "❌ ERROR: Valid version rejected"
exit 1
fi
echo "✓ SemVer with v prefix accepted"
- name: Test prerelease version
run: |
echo "Testing prerelease version: 1.0.0-alpha.1"
VERSION="1.0.0-alpha.1"
if ! [[ "$VERSION" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
echo "❌ ERROR: Valid prerelease version rejected"
exit 1
fi
echo "✓ Prerelease version accepted"
- name: Test version with build metadata
run: |
echo "Testing version with build metadata: 1.0.0+build.123"
VERSION="1.0.0+build.123"
if ! [[ "$VERSION" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
echo "❌ ERROR: Valid build metadata version rejected"
exit 1
fi
echo "✓ Version with build metadata accepted"
- name: Test complex version
run: |
echo "Testing complex version: v2.1.0-rc.1+build.456"
VERSION="v2.1.0-rc.1+build.456"
if ! [[ "$VERSION" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
echo "❌ ERROR: Valid complex version rejected"
exit 1
fi
echo "✓ Complex version accepted"
test-github-release-tool-availability:
name: Test Tool Availability Checks
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test gh CLI detection logic
run: |
# Test the logic for checking gh availability
# In actual action, this would fail if gh is not available
if command -v gh >/dev/null 2>&1; then
echo "✓ gh CLI is available in this environment"
gh --version
else
echo "⚠️ gh CLI not available in test environment (would fail in actual action)"
echo "✓ Tool detection logic works correctly"
fi
- name: Test jq detection logic
run: |
# Test the logic for checking jq availability
# In actual action, this would fail if jq is not available
if command -v jq >/dev/null 2>&1; then
echo "✓ jq is available in this environment"
jq --version
else
echo "⚠️ jq not available in test environment (would fail in actual action)"
echo "✓ Tool detection logic works correctly"
fi
- name: Test tool requirement validation
run: |
# Verify the action correctly checks for required tools
REQUIRED_TOOLS=("gh" "jq")
echo "Testing tool requirement checks..."
for tool in "${REQUIRED_TOOLS[@]}"; do
if command -v "$tool" >/dev/null 2>&1; then
echo " ✓ $tool: available"
else
echo " ⚠️ $tool: not available (action would fail at this check)"
fi
done
echo "✓ Tool requirement validation logic verified"
- name: Test gh authentication logic
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Test authentication detection logic
if [[ -n "$GITHUB_TOKEN" ]]; then
echo "✓ GITHUB_TOKEN environment variable is set"
else
echo "⚠️ GITHUB_TOKEN not set in test environment"
fi
# Test gh auth status check (without requiring it to pass)
if command -v gh >/dev/null 2>&1; then
if gh auth status >/dev/null 2>&1; then
echo "✓ gh authentication successful"
else
echo "⚠️ gh auth check failed (expected without proper setup)"
fi
else
echo "⚠️ gh not available, skipping auth check"
fi
echo "✓ Authentication detection logic verified"
test-github-release-changelog-validation:
name: Test Changelog Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test empty changelog (should trigger autogenerated notes)
run: |
echo "Testing empty changelog handling..."
CHANGELOG=""
if [[ -n "$CHANGELOG" ]]; then
echo "❌ ERROR: Empty string should be empty"
exit 1
fi
echo "✓ Empty changelog correctly detected"
- name: Test normal changelog
run: |
echo "Testing normal changelog..."
CHANGELOG="## Features
- Added new feature
- Improved performance"
if [[ -z "$CHANGELOG" ]]; then
echo "❌ ERROR: Changelog should not be empty"
exit 1
fi
if [[ ${#CHANGELOG} -gt 10000 ]]; then
echo "⚠️ Changelog is very long"
fi
echo "✓ Normal changelog processed correctly"
- name: Test very long changelog warning
run: |
echo "Testing very long changelog..."
# Create a changelog with >10000 characters
CHANGELOG=$(printf 'A%.0s' {1..10001})
if [[ ${#CHANGELOG} -le 10000 ]]; then
echo "❌ ERROR: Test changelog should be >10000 chars"
exit 1
fi
echo "✓ Long changelog warning would trigger (${#CHANGELOG} characters)"
test-github-release-changelog-types:
name: Test Changelog Content Types
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test multiline changelog
run: |
echo "Testing multiline changelog..."
CHANGELOG="## Version 1.2.3
### Features
- Feature A
- Feature B
### Bug Fixes
- Fix #123
- Fix #456"
echo "✓ Multiline changelog supported"
- name: Test changelog with special characters
run: |
echo "Testing changelog with special characters..."
CHANGELOG='## Release Notes
Special chars: $, `, \, ", '\'', !, @, #, %, &, *, (, )'
echo "✓ Special characters in changelog supported"
- name: Test changelog with markdown
run: |
echo "Testing changelog with markdown..."
CHANGELOG="## Changes
**Bold** and *italic* text
- [x] Task completed
- [ ] Task pending
\`\`\`bash
echo 'code block'
\`\`\`
| Table | Header |
|-------|--------|
| Cell | Data |"
echo "✓ Markdown in changelog supported"
test-github-release-output-format:
name: Test Output Format
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Verify output structure (mock test)
run: |
echo "Testing output structure..."
# Check if jq is available for this test
if ! command -v jq >/dev/null 2>&1; then
echo "⚠️ jq not available, skipping JSON parsing test"
echo "✓ Output format validation logic verified (jq would be required in actual action)"
exit 0
fi
# Mock release info JSON (similar to gh release view output)
RELEASE_INFO='{
"url": "https://github.com/owner/repo/releases/tag/v1.0.0",
"id": "RE_12345",
"uploadUrl": "https://uploads.github.com/repos/owner/repo/releases/12345/assets{?name,label}"
}'
# Extract outputs
release_url=$(echo "$RELEASE_INFO" | jq -r '.url')
release_id=$(echo "$RELEASE_INFO" | jq -r '.id')
upload_url=$(echo "$RELEASE_INFO" | jq -r '.uploadUrl')
echo "Release URL: $release_url"
echo "Release ID: $release_id"
echo "Upload URL: $upload_url"
# Verify output format
if [[ ! "$release_url" =~ ^https://github\.com/.*/releases/tag/.* ]]; then
echo "❌ ERROR: Invalid release URL format"
exit 1
fi
if [[ ! "$release_id" =~ ^RE_.* ]]; then
echo "❌ ERROR: Invalid release ID format"
exit 1
fi
if [[ ! "$upload_url" =~ ^https://uploads\.github\.com/.* ]]; then
echo "❌ ERROR: Invalid upload URL format"
exit 1
fi
echo "✓ Output format validation passed"
test-github-release-integration-scenarios:
name: Test Integration Scenarios
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test release workflow without actual creation
run: |
echo "Simulating release workflow..."
# Validate version
VERSION="v1.2.3-test"
if ! [[ "$VERSION" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
echo "❌ ERROR: Version validation failed"
exit 1
fi
echo "✓ Version validation passed"
# Check tool availability (non-fatal for test environment)
gh_available=false
jq_available=false
if command -v gh >/dev/null 2>&1; then
echo "✓ gh CLI is available"
gh_available=true
else
echo "⚠️ gh not available (would fail in actual action)"
fi
if command -v jq >/dev/null 2>&1; then
echo "✓ jq is available"
jq_available=true
else
echo "⚠️ jq not available (would fail in actual action)"
fi
# Create mock changelog
CHANGELOG="Test release notes"
NOTES_FILE="$(mktemp)"
printf '%s' "$CHANGELOG" > "$NOTES_FILE"
# Verify changelog file
if [[ ! -f "$NOTES_FILE" ]]; then
echo "❌ ERROR: Changelog file not created"
exit 1
fi
CONTENT=$(cat "$NOTES_FILE")
if [[ "$CONTENT" != "$CHANGELOG" ]]; then
echo "❌ ERROR: Changelog content mismatch"
exit 1
fi
rm -f "$NOTES_FILE"
echo "✓ Release workflow simulation passed"
- name: Test autogenerated changelog scenario
run: |
echo "Testing autogenerated changelog scenario..."
VERSION="v2.0.0"
CHANGELOG=""
if [[ -z "$CHANGELOG" ]]; then
echo "✓ Would use --generate-notes flag"
else
echo "✓ Would use custom changelog"
fi
- name: Test custom changelog scenario
run: |
echo "Testing custom changelog scenario..."
VERSION="v2.1.0"
CHANGELOG="## Custom Release Notes
This release includes:
- Feature X
- Bug fix Y"
if [[ -n "$CHANGELOG" ]]; then
echo "✓ Would use --notes-file with custom changelog"
else
echo "✓ Would use --generate-notes"
fi
integration-test-summary:
name: Integration Test Summary
runs-on: ubuntu-latest
needs:
- test-github-release-validation
- test-github-release-version-formats
- test-github-release-tool-availability
- test-github-release-changelog-validation
- test-github-release-changelog-types
- test-github-release-output-format
- test-github-release-integration-scenarios
steps:
- name: Summary
run: |
echo "=========================================="
echo "GitHub Release Integration Tests - PASSED"
echo "=========================================="
echo ""
echo "✓ Input validation tests"
echo "✓ Version format tests"
echo "✓ Tool availability tests"
echo "✓ Changelog validation tests"
echo "✓ Changelog content tests"
echo "✓ Output format tests"
echo "✓ Integration scenario tests"
echo ""
echo "All github-release integration tests completed successfully!"

View File

@@ -0,0 +1,316 @@
---
name: Test Lint & Fix Action Chains
on:
workflow_dispatch:
push:
paths:
- 'eslint-check/**'
- 'eslint-fix/**'
- 'prettier-check/**'
- 'prettier-fix/**'
- 'node-setup/**'
- 'common-cache/**'
- '_tests/integration/workflows/lint-fix-chain-test.yml'
jobs:
test-eslint-chain:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create test JavaScript files
run: |
mkdir -p test-project/src
# Create package.json
cat > test-project/package.json <<EOF
{
"name": "test-project",
"version": "1.0.0",
"devDependencies": {
"eslint": "^8.0.0"
}
}
EOF
# Create .eslintrc.json
cat > test-project/.eslintrc.json <<EOF
{
"env": {
"node": true,
"es2021": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 12
},
"rules": {
"semi": ["error", "always"],
"quotes": ["error", "single"]
}
}
EOF
# Create test file with linting issues
cat > test-project/src/test.js <<EOF
const x = "double quotes"
console.log(x)
EOF
- name: Setup Node.js
uses: ./node-setup
with:
node-version: '18'
working-directory: './test-project'
- name: Test eslint-check (should find errors)
id: eslint-check
uses: ./eslint-check
with:
working-directory: './test-project'
continue-on-error: true
- name: Validate eslint-check found issues
run: |
echo "ESLint check outcome: ${{ steps.eslint-check.outcome }}"
echo "Error count: ${{ steps.eslint-check.outputs.error-count }}"
echo "Warning count: ${{ steps.eslint-check.outputs.warning-count }}"
# Check should fail or find issues
if [[ "${{ steps.eslint-check.outcome }}" == "success" ]]; then
if [[ "${{ steps.eslint-check.outputs.error-count }}" == "0" ]]; then
echo "⚠️ WARNING: Expected to find linting errors but found none"
fi
fi
echo "✅ ESLint check validated"
- name: Test eslint-fix (should fix issues)
id: eslint-fix
uses: ./eslint-fix
with:
working-directory: './test-project'
token: ${{ github.token }}
email: 'test@example.com'
username: 'test-user'
- name: Validate eslint-fix ran
run: |
echo "Fixed count: ${{ steps.eslint-fix.outputs.fixed-count }}"
echo "Files fixed: ${{ steps.eslint-fix.outputs.files-fixed }}"
# Check that fixes were attempted
if [[ -n "${{ steps.eslint-fix.outputs.fixed-count }}" ]]; then
echo "✅ ESLint fixed ${{ steps.eslint-fix.outputs.fixed-count }} issues"
else
echo "⚠️ No fix count reported (may be expected if no fixable issues)"
fi
echo "✅ ESLint fix validated"
test-prettier-chain:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create test files for Prettier
run: |
mkdir -p test-prettier
# Create package.json
cat > test-prettier/package.json <<EOF
{
"name": "test-prettier",
"version": "1.0.0",
"devDependencies": {
"prettier": "^3.0.0"
}
}
EOF
# Create .prettierrc
cat > test-prettier/.prettierrc <<EOF
{
"semi": true,
"singleQuote": true,
"printWidth": 80
}
EOF
# Create badly formatted file
cat > test-prettier/test.js <<EOF
const x={"key":"value","another":"data"}
console.log(x)
EOF
# Create badly formatted JSON
cat > test-prettier/test.json <<EOF
{"key":"value","nested":{"data":"here"}}
EOF
- name: Setup Node.js for Prettier
uses: ./node-setup
with:
node-version: '18'
working-directory: './test-prettier'
- name: Test prettier-check (should find issues)
id: prettier-check
uses: ./prettier-check
with:
working-directory: './test-prettier'
continue-on-error: true
- name: Validate prettier-check found issues
run: |
echo "Prettier check outcome: ${{ steps.prettier-check.outcome }}"
# Check should find formatting issues
if [[ "${{ steps.prettier-check.outcome }}" == "failure" ]]; then
echo "✅ Prettier correctly found formatting issues"
else
echo "⚠️ WARNING: Expected Prettier to find formatting issues"
fi
- name: Test prettier-fix (should fix issues)
id: prettier-fix
uses: ./prettier-fix
with:
working-directory: './test-prettier'
token: ${{ github.token }}
email: 'test@example.com'
username: 'test-user'
- name: Validate prettier-fix ran
run: |
echo "Prettier fix completed"
# Check that files exist and have been processed
if [[ -f "test-prettier/test.js" ]]; then
echo "✅ Test file exists after Prettier fix"
else
echo "❌ ERROR: Test file missing after Prettier fix"
exit 1
fi
echo "✅ Prettier fix validated"
test-action-chain-integration:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create comprehensive test project
run: |
mkdir -p test-chain/src
# Create package.json with both ESLint and Prettier
cat > test-chain/package.json <<EOF
{
"name": "test-chain",
"version": "1.0.0",
"devDependencies": {
"eslint": "^8.0.0",
"prettier": "^3.0.0"
}
}
EOF
# Create .eslintrc.json
cat > test-chain/.eslintrc.json <<EOF
{
"env": {
"node": true,
"es2021": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 12
},
"rules": {
"semi": ["error", "always"],
"quotes": ["error", "single"]
}
}
EOF
# Create .prettierrc
cat > test-chain/.prettierrc <<EOF
{
"semi": true,
"singleQuote": true,
"printWidth": 80
}
EOF
# Create test file with both linting and formatting issues
cat > test-chain/src/app.js <<EOF
const message="hello world"
function greet(){console.log(message)}
greet()
EOF
- name: Setup Node.js
uses: ./node-setup
with:
node-version: '18'
working-directory: './test-chain'
- name: Run ESLint check
id: lint-check
uses: ./eslint-check
with:
working-directory: './test-chain'
continue-on-error: true
- name: Run Prettier check
id: format-check
uses: ./prettier-check
with:
working-directory: './test-chain'
continue-on-error: true
- name: Run ESLint fix
id: lint-fix
uses: ./eslint-fix
with:
working-directory: './test-chain'
token: ${{ github.token }}
email: 'test@example.com'
username: 'test-user'
- name: Run Prettier fix
id: format-fix
uses: ./prettier-fix
with:
working-directory: './test-chain'
token: ${{ github.token }}
email: 'test@example.com'
username: 'test-user'
- name: Validate complete chain
run: |
echo "=== Action Chain Results ==="
echo "Lint Check: ${{ steps.lint-check.outcome }}"
echo "Format Check: ${{ steps.format-check.outcome }}"
echo "Lint Fix: ${{ steps.lint-fix.outcome }}"
echo "Format Fix: ${{ steps.format-fix.outcome }}"
# Validate that all steps ran
steps_run=0
[[ "${{ steps.lint-check.outcome }}" != "skipped" ]] && ((steps_run++))
[[ "${{ steps.format-check.outcome }}" != "skipped" ]] && ((steps_run++))
[[ "${{ steps.lint-fix.outcome }}" != "skipped" ]] && ((steps_run++))
[[ "${{ steps.format-fix.outcome }}" != "skipped" ]] && ((steps_run++))
if [[ $steps_run -eq 4 ]]; then
echo "✅ Complete action chain executed successfully"
else
echo "❌ ERROR: Not all steps in chain executed (ran: $steps_run/4)"
exit 1
fi
echo "✅ Action chain integration validated"

View File

@@ -0,0 +1,513 @@
---
name: Integration Test - Node Setup
on:
workflow_dispatch:
push:
paths:
- 'node-setup/**'
- 'version-file-parser/**'
- 'common-cache/**'
- 'common-retry/**'
- '_tests/integration/workflows/node-setup-test.yml'
jobs:
test-node-setup-version-validation:
name: Test Version Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test invalid default version format (alphabetic)
run: |
VERSION="abc"
if [[ "$VERSION" =~ ^[0-9]+(\.[0-9]+(\.[0-9]+)?)?$ ]]; then
echo "❌ ERROR: Should reject alphabetic version"
exit 1
fi
echo "✓ Alphabetic version correctly rejected"
- name: Test invalid default version (too low)
run: |
VERSION="10"
major=$(echo "$VERSION" | cut -d'.' -f1)
if [ "$major" -lt 14 ] || [ "$major" -gt 30 ]; then
echo "✓ Version $VERSION correctly rejected (major < 14)"
else
echo "❌ ERROR: Should reject Node.js $VERSION"
exit 1
fi
- name: Test invalid default version (too high)
run: |
VERSION="50"
major=$(echo "$VERSION" | cut -d'.' -f1)
if [ "$major" -lt 14 ] || [ "$major" -gt 30 ]; then
echo "✓ Version $VERSION correctly rejected (major > 30)"
else
echo "❌ ERROR: Should reject Node.js $VERSION"
exit 1
fi
- name: Test valid version formats
run: |
for version in "20" "20.9" "20.9.0" "18" "22.1.0"; do
if [[ "$version" =~ ^[0-9]+(\.[0-9]+(\.[0-9]+)?)?$ ]]; then
major=$(echo "$version" | cut -d'.' -f1)
if [ "$major" -ge 14 ] && [ "$major" -le 30 ]; then
echo "✓ Version $version accepted"
else
echo "❌ ERROR: Version $version should be accepted"
exit 1
fi
else
echo "❌ ERROR: Version $version format validation failed"
exit 1
fi
done
test-node-setup-package-manager-validation:
name: Test Package Manager Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test valid package managers
run: |
for pm in "npm" "yarn" "pnpm" "bun" "auto"; do
case "$pm" in
"npm"|"yarn"|"pnpm"|"bun"|"auto")
echo "✓ Package manager $pm accepted"
;;
*)
echo "❌ ERROR: Valid package manager $pm rejected"
exit 1
;;
esac
done
- name: Test invalid package manager
run: |
PM="invalid-pm"
case "$PM" in
"npm"|"yarn"|"pnpm"|"bun"|"auto")
echo "❌ ERROR: Invalid package manager should be rejected"
exit 1
;;
*)
echo "✓ Invalid package manager correctly rejected"
;;
esac
test-node-setup-url-validation:
name: Test URL Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test valid registry URLs
run: |
for url in "https://registry.npmjs.org" "http://localhost:4873" "https://npm.custom.com/"; do
if [[ "$url" == "https://"* ]] || [[ "$url" == "http://"* ]]; then
echo "✓ Registry URL $url accepted"
else
echo "❌ ERROR: Valid URL $url rejected"
exit 1
fi
done
- name: Test invalid registry URLs
run: |
for url in "ftp://registry.com" "not-a-url" "registry.com"; do
if [[ "$url" == "https://"* ]] || [[ "$url" == "http://"* ]]; then
echo "❌ ERROR: Invalid URL $url should be rejected"
exit 1
else
echo "✓ Invalid URL $url correctly rejected"
fi
done
test-node-setup-retries-validation:
name: Test Retries Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test valid retry counts
run: |
for retries in "1" "3" "5" "10"; do
if [[ "$retries" =~ ^[0-9]+$ ]] && [ "$retries" -gt 0 ] && [ "$retries" -le 10 ]; then
echo "✓ Max retries $retries accepted"
else
echo "❌ ERROR: Valid retry count $retries rejected"
exit 1
fi
done
- name: Test invalid retry counts
run: |
for retries in "0" "11" "abc" "-1"; do
if [[ "$retries" =~ ^[0-9]+$ ]] && [ "$retries" -gt 0 ] && [ "$retries" -le 10 ]; then
echo "❌ ERROR: Invalid retry count $retries should be rejected"
exit 1
else
echo "✓ Invalid retry count $retries correctly rejected"
fi
done
test-node-setup-boolean-validation:
name: Test Boolean Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test valid boolean values
run: |
for value in "true" "false"; do
if [[ "$value" == "true" ]] || [[ "$value" == "false" ]]; then
echo "✓ Boolean value $value accepted"
else
echo "❌ ERROR: Valid boolean $value rejected"
exit 1
fi
done
- name: Test invalid boolean values
run: |
for value in "yes" "no" "1" "0" "True" "FALSE" ""; do
if [[ "$value" != "true" ]] && [[ "$value" != "false" ]]; then
echo "✓ Invalid boolean value '$value' correctly rejected"
else
echo "❌ ERROR: Invalid boolean $value should be rejected"
exit 1
fi
done
test-node-setup-token-validation:
name: Test Auth Token Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test injection pattern detection
run: |
for token in "token;malicious" "token&&command" "token|pipe"; do
if [[ "$token" == *";"* ]] || [[ "$token" == *"&&"* ]] || [[ "$token" == *"|"* ]]; then
echo "✓ Injection pattern in token correctly detected"
else
echo "❌ ERROR: Should detect injection pattern in: $token"
exit 1
fi
done
- name: Test valid tokens
run: |
for token in "npm_AbCdEf1234567890" "github_pat_12345abcdef" "simple-token"; do
if [[ "$token" == *";"* ]] || [[ "$token" == *"&&"* ]] || [[ "$token" == *"|"* ]]; then
echo "❌ ERROR: Valid token should not be rejected: $token"
exit 1
else
echo "✓ Valid token accepted"
fi
done
test-node-setup-package-manager-resolution:
name: Test Package Manager Resolution
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test auto detection with detected PM
run: |
INPUT_PM="auto"
DETECTED_PM="pnpm"
if [ "$INPUT_PM" = "auto" ]; then
if [ -n "$DETECTED_PM" ]; then
FINAL_PM="$DETECTED_PM"
else
FINAL_PM="npm"
fi
else
FINAL_PM="$INPUT_PM"
fi
if [[ "$FINAL_PM" != "pnpm" ]]; then
echo "❌ ERROR: Should use detected PM (pnpm)"
exit 1
fi
echo "✓ Auto-detected package manager correctly resolved"
- name: Test auto detection without detected PM
run: |
INPUT_PM="auto"
DETECTED_PM=""
if [ "$INPUT_PM" = "auto" ]; then
if [ -n "$DETECTED_PM" ]; then
FINAL_PM="$DETECTED_PM"
else
FINAL_PM="npm"
fi
else
FINAL_PM="$INPUT_PM"
fi
if [[ "$FINAL_PM" != "npm" ]]; then
echo "❌ ERROR: Should default to npm"
exit 1
fi
echo "✓ Defaults to npm when no detection"
- name: Test explicit package manager
run: |
INPUT_PM="yarn"
DETECTED_PM="pnpm"
if [ "$INPUT_PM" = "auto" ]; then
if [ -n "$DETECTED_PM" ]; then
FINAL_PM="$DETECTED_PM"
else
FINAL_PM="npm"
fi
else
FINAL_PM="$INPUT_PM"
fi
if [[ "$FINAL_PM" != "yarn" ]]; then
echo "❌ ERROR: Should use explicit PM (yarn)"
exit 1
fi
echo "✓ Explicit package manager correctly used"
test-node-setup-feature-detection:
name: Test Feature Detection
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create test package.json with ESM
run: |
mkdir -p test-esm
cd test-esm
cat > package.json <<'EOF'
{
"name": "test-esm",
"version": "1.0.0",
"type": "module"
}
EOF
- name: Test ESM detection
run: |
cd test-esm
if command -v jq >/dev/null 2>&1; then
pkg_type=$(jq -r '.type // "commonjs"' package.json 2>/dev/null)
if [[ "$pkg_type" == "module" ]]; then
echo "✓ ESM support correctly detected"
else
echo "❌ ERROR: Should detect ESM support"
exit 1
fi
else
echo "⚠️ jq not available, skipping ESM detection test"
echo "✓ ESM detection logic verified (jq would be required in actual action)"
fi
- name: Create test with TypeScript
run: |
mkdir -p test-ts
cd test-ts
touch tsconfig.json
cat > package.json <<'EOF'
{
"name": "test-ts",
"devDependencies": {
"typescript": "^5.0.0"
}
}
EOF
- name: Test TypeScript detection
run: |
cd test-ts
typescript_support="false"
if [ -f tsconfig.json ]; then
typescript_support="true"
fi
if [[ "$typescript_support" != "true" ]]; then
echo "❌ ERROR: Should detect TypeScript"
exit 1
fi
echo "✓ TypeScript support correctly detected"
- name: Create test with frameworks
run: |
mkdir -p test-frameworks
cd test-frameworks
cat > package.json <<'EOF'
{
"name": "test-frameworks",
"dependencies": {
"react": "^18.0.0",
"next": "^14.0.0"
}
}
EOF
- name: Test framework detection
run: |
cd test-frameworks
if command -v jq >/dev/null 2>&1; then
has_next=$(jq -e '.dependencies.next or .devDependencies.next' package.json >/dev/null 2>&1 && echo "yes" || echo "no")
has_react=$(jq -e '.dependencies.react or .devDependencies.react' package.json >/dev/null 2>&1 && echo "yes" || echo "no")
if [[ "$has_next" == "yes" ]] && [[ "$has_react" == "yes" ]]; then
echo "✓ Frameworks (Next.js, React) correctly detected"
else
echo "❌ ERROR: Should detect Next.js and React"
exit 1
fi
else
echo "⚠️ jq not available, skipping framework detection test"
echo "✓ Framework detection logic verified (jq would be required in actual action)"
fi
test-node-setup-security:
name: Test Security Measures
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test token sanitization
run: |
TOKEN="test-token
with-newline"
# Should remove newlines
sanitized=$(echo "$TOKEN" | tr -d '\n\r')
if [[ "$sanitized" == *$'\n'* ]] || [[ "$sanitized" == *$'\r'* ]]; then
echo "❌ ERROR: Newlines not removed"
exit 1
fi
echo "✓ Token sanitization works correctly"
- name: Test package manager sanitization
run: |
PM="npm
with-newline"
# Should remove newlines
sanitized=$(echo "$PM" | tr -d '\n\r')
if [[ "$sanitized" == *$'\n'* ]] || [[ "$sanitized" == *$'\r'* ]]; then
echo "❌ ERROR: Newlines not removed from PM"
exit 1
fi
echo "✓ Package manager sanitization works correctly"
test-node-setup-integration-workflow:
name: Test Integration Workflow
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Simulate complete workflow
run: |
echo "=== Simulating Node Setup Workflow ==="
# 1. Validation
echo "Step 1: Validate inputs"
DEFAULT_VERSION="20"
PACKAGE_MANAGER="npm"
REGISTRY_URL="https://registry.npmjs.org"
CACHE="true"
INSTALL="true"
MAX_RETRIES="3"
echo "✓ Inputs validated"
# 2. Version parsing
echo "Step 2: Parse Node.js version"
NODE_VERSION="20.9.0"
echo "✓ Version parsed: $NODE_VERSION"
# 3. Package manager resolution
echo "Step 3: Resolve package manager"
if [ "$PACKAGE_MANAGER" = "auto" ]; then
FINAL_PM="npm"
else
FINAL_PM="$PACKAGE_MANAGER"
fi
echo "✓ Package manager resolved: $FINAL_PM"
# 4. Setup Node.js
echo "Step 4: Setup Node.js $NODE_VERSION"
if command -v node >/dev/null 2>&1; then
echo "✓ Node.js available: $(node --version)"
fi
# 5. Enable Corepack
echo "Step 5: Enable Corepack"
if command -v corepack >/dev/null 2>&1; then
echo "✓ Corepack available"
else
echo "⚠️ Corepack not available in test environment"
fi
# 6. Cache dependencies
if [[ "$CACHE" == "true" ]]; then
echo "Step 6: Cache dependencies"
echo "✓ Would use common-cache action"
fi
# 7. Install dependencies
if [[ "$INSTALL" == "true" ]]; then
echo "Step 7: Install dependencies"
echo "✓ Would run: $FINAL_PM install"
fi
echo "=== Workflow simulation completed ==="
integration-test-summary:
name: Integration Test Summary
runs-on: ubuntu-latest
needs:
- test-node-setup-version-validation
- test-node-setup-package-manager-validation
- test-node-setup-url-validation
- test-node-setup-retries-validation
- test-node-setup-boolean-validation
- test-node-setup-token-validation
- test-node-setup-package-manager-resolution
- test-node-setup-feature-detection
- test-node-setup-security
- test-node-setup-integration-workflow
steps:
- name: Summary
run: |
echo "=========================================="
echo "Node Setup Integration Tests - PASSED"
echo "=========================================="
echo ""
echo "✓ Version validation tests"
echo "✓ Package manager validation tests"
echo "✓ URL validation tests"
echo "✓ Retries validation tests"
echo "✓ Boolean validation tests"
echo "✓ Token validation tests"
echo "✓ Package manager resolution tests"
echo "✓ Feature detection tests"
echo "✓ Security measure tests"
echo "✓ Integration workflow tests"
echo ""
echo "All node-setup integration tests completed successfully!"

View File

@@ -0,0 +1,353 @@
---
name: Integration Test - NPM Publish
on:
workflow_dispatch:
push:
paths:
- 'npm-publish/**'
- 'node-setup/**'
- '_tests/integration/workflows/npm-publish-test.yml'
jobs:
test-npm-publish-validation:
name: Test Input Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create test package.json
run: |
mkdir -p test-package
cd test-package
cat > package.json <<'EOF'
{
"name": "@test/integration-test",
"version": "1.0.0",
"description": "Test package for npm-publish integration",
"main": "index.js"
}
EOF
echo "module.exports = { test: true };" > index.js
- name: Test valid inputs (should succeed validation)
id: valid-test
uses: ./npm-publish
continue-on-error: true
with:
registry-url: 'https://registry.npmjs.org/'
scope: '@test'
package-version: '1.0.0'
npm_token: 'test-token-12345678'
env:
GITHUB_WORKSPACE: ${{ github.workspace }}/test-package
- name: Validate success (validation only)
run: |
# This will fail at publish step but validation should pass
echo "✓ Input validation passed for valid inputs"
- name: Test invalid registry URL
id: invalid-registry
uses: ./npm-publish
continue-on-error: true
with:
registry-url: 'not-a-url'
scope: '@test'
package-version: '1.0.0'
npm_token: 'test-token'
env:
GITHUB_WORKSPACE: ${{ github.workspace }}/test-package
- name: Verify invalid registry URL failed
run: |
if [[ "${{ steps.invalid-registry.outcome }}" == "success" ]]; then
echo "❌ ERROR: Invalid registry URL should have failed"
exit 1
fi
echo "✓ Invalid registry URL correctly rejected"
- name: Test invalid version format
id: invalid-version
uses: ./npm-publish
continue-on-error: true
with:
registry-url: 'https://registry.npmjs.org/'
scope: '@test'
package-version: 'not.a.version'
npm_token: 'test-token'
env:
GITHUB_WORKSPACE: ${{ github.workspace }}/test-package
- name: Verify invalid version failed
run: |
if [[ "${{ steps.invalid-version.outcome }}" == "success" ]]; then
echo "❌ ERROR: Invalid version should have failed"
exit 1
fi
echo "✓ Invalid version format correctly rejected"
- name: Test invalid scope format
id: invalid-scope
uses: ./npm-publish
continue-on-error: true
with:
registry-url: 'https://registry.npmjs.org/'
scope: 'invalid-scope'
package-version: '1.0.0'
npm_token: 'test-token'
env:
GITHUB_WORKSPACE: ${{ github.workspace }}/test-package
- name: Verify invalid scope failed
run: |
if [[ "${{ steps.invalid-scope.outcome }}" == "success" ]]; then
echo "❌ ERROR: Invalid scope format should have failed"
exit 1
fi
echo "✓ Invalid scope format correctly rejected"
- name: Test missing npm token
id: missing-token
uses: ./npm-publish
continue-on-error: true
with:
registry-url: 'https://registry.npmjs.org/'
scope: '@test'
package-version: '1.0.0'
npm_token: ''
env:
GITHUB_WORKSPACE: ${{ github.workspace }}/test-package
- name: Verify missing token failed
run: |
if [[ "${{ steps.missing-token.outcome }}" == "success" ]]; then
echo "❌ ERROR: Missing token should have failed"
exit 1
fi
echo "✓ Missing NPM token correctly rejected"
test-npm-publish-package-validation:
name: Test Package Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test missing package.json
id: missing-package
uses: ./npm-publish
continue-on-error: true
with:
registry-url: 'https://registry.npmjs.org/'
scope: '@test'
package-version: '1.0.0'
npm_token: 'test-token'
- name: Verify missing package.json failed
run: |
if [[ "${{ steps.missing-package.outcome }}" == "success" ]]; then
echo "❌ ERROR: Missing package.json should have failed"
exit 1
fi
echo "✓ Missing package.json correctly detected"
- name: Create test package with version mismatch
run: |
mkdir -p test-mismatch
cd test-mismatch
cat > package.json <<'EOF'
{
"name": "@test/mismatch-test",
"version": "2.0.0",
"description": "Test version mismatch"
}
EOF
- name: Test version mismatch detection
id: version-mismatch
uses: ./npm-publish
continue-on-error: true
with:
registry-url: 'https://registry.npmjs.org/'
scope: '@test'
package-version: '1.0.0'
npm_token: 'test-token'
env:
GITHUB_WORKSPACE: ${{ github.workspace }}/test-mismatch
- name: Verify version mismatch failed
run: |
if [[ "${{ steps.version-mismatch.outcome }}" == "success" ]]; then
echo "❌ ERROR: Version mismatch should have been detected"
exit 1
fi
echo "✓ Version mismatch correctly detected"
test-npm-publish-version-formats:
name: Test Version Format Support
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test SemVer with v prefix
run: |
mkdir -p test-v-prefix
cd test-v-prefix
cat > package.json <<'EOF'
{
"name": "@test/v-prefix",
"version": "1.2.3",
"description": "Test v prefix"
}
EOF
# Should accept v1.2.3 and strip to 1.2.3
echo "Testing v prefix version..."
- name: Test prerelease versions
run: |
mkdir -p test-prerelease
cd test-prerelease
cat > package.json <<'EOF'
{
"name": "@test/prerelease",
"version": "1.0.0-alpha.1",
"description": "Test prerelease"
}
EOF
echo "Testing prerelease version format..."
- name: Test build metadata
run: |
mkdir -p test-build
cd test-build
cat > package.json <<'EOF'
{
"name": "@test/build-meta",
"version": "1.0.0+build.123",
"description": "Test build metadata"
}
EOF
echo "Testing build metadata format..."
test-npm-publish-outputs:
name: Test Output Values
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create test package
run: |
mkdir -p test-outputs
cd test-outputs
cat > package.json <<'EOF'
{
"name": "@test/outputs-test",
"version": "1.5.0",
"description": "Test outputs"
}
EOF
- name: Run npm-publish (validation only)
id: publish-outputs
uses: ./npm-publish
continue-on-error: true
with:
registry-url: 'https://npm.custom.com/'
scope: '@custom-scope'
package-version: '1.5.0'
npm_token: 'test-token-outputs'
env:
GITHUB_WORKSPACE: ${{ github.workspace }}/test-outputs
- name: Verify outputs
run: |
registry="${{ steps.publish-outputs.outputs.registry-url }}"
scope="${{ steps.publish-outputs.outputs.scope }}"
version="${{ steps.publish-outputs.outputs.package-version }}"
echo "Registry URL: $registry"
echo "Scope: $scope"
echo "Version: $version"
# Verify output values match inputs
if [[ "$registry" != "https://npm.custom.com/" ]]; then
echo "❌ ERROR: Registry URL output mismatch"
exit 1
fi
if [[ "$scope" != "@custom-scope" ]]; then
echo "❌ ERROR: Scope output mismatch"
exit 1
fi
if [[ "$version" != "1.5.0" ]]; then
echo "❌ ERROR: Version output mismatch"
exit 1
fi
echo "✓ All outputs match expected values"
test-npm-publish-secret-masking:
name: Test Secret Masking
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create test package
run: |
mkdir -p test-secrets
cd test-secrets
cat > package.json <<'EOF'
{
"name": "@test/secrets-test",
"version": "1.0.0"
}
EOF
- name: Test that token gets masked
id: test-masking
uses: ./npm-publish
continue-on-error: true
with:
registry-url: 'https://registry.npmjs.org/'
scope: '@test'
package-version: '1.0.0'
npm_token: 'super-secret-token-12345'
env:
GITHUB_WORKSPACE: ${{ github.workspace }}/test-secrets
- name: Verify token is not in logs
run: |
echo "✓ Token should be masked in GitHub Actions logs"
echo "✓ Secret masking test completed"
integration-test-summary:
name: Integration Test Summary
runs-on: ubuntu-latest
needs:
- test-npm-publish-validation
- test-npm-publish-package-validation
- test-npm-publish-version-formats
- test-npm-publish-outputs
- test-npm-publish-secret-masking
steps:
- name: Summary
run: |
echo "=========================================="
echo "NPM Publish Integration Tests - PASSED"
echo "=========================================="
echo ""
echo "✓ Input validation tests"
echo "✓ Package validation tests"
echo "✓ Version format tests"
echo "✓ Output verification tests"
echo "✓ Secret masking tests"
echo ""
echo "All npm-publish integration tests completed successfully!"

View File

@@ -0,0 +1,435 @@
---
name: Integration Test - Pre-commit
on:
workflow_dispatch:
push:
paths:
- 'pre-commit/**'
- 'set-git-config/**'
- 'validate-inputs/**'
- '_tests/integration/workflows/pre-commit-test.yml'
jobs:
test-pre-commit-validation:
name: Test Input Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test with default inputs (should pass validation)
id: default-inputs
uses: ./pre-commit
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Verify validation passed
run: |
echo "✓ Default inputs validation completed"
- name: Test with custom config file
id: custom-config
uses: ./pre-commit
continue-on-error: true
with:
pre-commit-config: '.pre-commit-config.yaml'
token: ${{ secrets.GITHUB_TOKEN }}
- name: Verify custom config accepted
run: |
echo "✓ Custom config file accepted"
- name: Test with base branch
id: with-base-branch
uses: ./pre-commit
continue-on-error: true
with:
base-branch: 'main'
token: ${{ secrets.GITHUB_TOKEN }}
- name: Verify base branch accepted
run: |
echo "✓ Base branch parameter accepted"
test-pre-commit-git-config:
name: Test Git Configuration
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test custom git user
run: |
# Simulate set-git-config step
git config user.name "Test User"
git config user.email "test@example.com"
# Verify configuration
user_name=$(git config user.name)
user_email=$(git config user.email)
if [[ "$user_name" != "Test User" ]]; then
echo "❌ ERROR: Git user name not set correctly"
exit 1
fi
if [[ "$user_email" != "test@example.com" ]]; then
echo "❌ ERROR: Git user email not set correctly"
exit 1
fi
echo "✓ Git configuration works correctly"
- name: Test default git user
run: |
# Simulate default configuration
git config user.name "GitHub Actions"
git config user.email "github-actions@github.com"
# Verify default configuration
user_name=$(git config user.name)
user_email=$(git config user.email)
if [[ "$user_name" != "GitHub Actions" ]]; then
echo "❌ ERROR: Default git user name not set correctly"
exit 1
fi
if [[ "$user_email" != "github-actions@github.com" ]]; then
echo "❌ ERROR: Default git user email not set correctly"
exit 1
fi
echo "✓ Default git configuration works correctly"
test-pre-commit-option-generation:
name: Test Option Generation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test all-files option (no base branch)
run: |
BASE_BRANCH=""
if [ -z "$BASE_BRANCH" ]; then
option="--all-files"
else
option="--from-ref $BASE_BRANCH --to-ref HEAD"
fi
if [[ "$option" != "--all-files" ]]; then
echo "❌ ERROR: Should use --all-files when no base branch"
exit 1
fi
echo "✓ Correctly generates --all-files option"
- name: Test diff option (with base branch)
run: |
BASE_BRANCH="main"
if [ -z "$BASE_BRANCH" ]; then
option="--all-files"
else
option="--from-ref $BASE_BRANCH --to-ref HEAD"
fi
expected="--from-ref main --to-ref HEAD"
if [[ "$option" != "$expected" ]]; then
echo "❌ ERROR: Option mismatch. Expected: $expected, Got: $option"
exit 1
fi
echo "✓ Correctly generates diff option with base branch"
test-pre-commit-config-file-detection:
name: Test Config File Detection
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Verify default config exists
run: |
if [[ -f ".pre-commit-config.yaml" ]]; then
echo "✓ Default .pre-commit-config.yaml found"
else
echo "⚠️ Default config not found (may use repo default)"
fi
- name: Test custom config path validation
run: |
CONFIG_FILE="custom-pre-commit-config.yaml"
# In real action, this would be validated
if [[ ! -f "$CONFIG_FILE" ]]; then
echo "✓ Custom config file validation would fail (expected)"
else
echo "✓ Custom config file exists"
fi
test-pre-commit-hook-execution:
name: Test Hook Execution Scenarios
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test pre-commit installed
run: |
if command -v pre-commit >/dev/null 2>&1; then
echo "✓ pre-commit is installed"
pre-commit --version
else
echo "⚠️ pre-commit not installed (would be installed by action)"
fi
- name: Create test file with issues
run: |
mkdir -p test-pre-commit
cd test-pre-commit
# Create a file with trailing whitespace
echo "Line with trailing spaces " > test.txt
echo "Line without issues" >> test.txt
# Create a minimal .pre-commit-config.yaml
cat > .pre-commit-config.yaml <<'EOF'
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
EOF
echo "✓ Test environment created"
- name: Test hook detection of issues
run: |
cd test-pre-commit
# Check if trailing whitespace exists
if grep -q " $" test.txt; then
echo "✓ Test file has trailing whitespace (as expected)"
else
echo "❌ ERROR: Test file should have trailing whitespace"
exit 1
fi
test-pre-commit-outputs:
name: Test Output Values
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test hooks_passed output
run: |
# Simulate successful hooks
HOOKS_OUTCOME="success"
if [[ "$HOOKS_OUTCOME" == "success" ]]; then
hooks_passed="true"
else
hooks_passed="false"
fi
if [[ "$hooks_passed" != "true" ]]; then
echo "❌ ERROR: hooks_passed should be true for success"
exit 1
fi
echo "✓ hooks_passed output correct for success"
- name: Test hooks_passed output on failure
run: |
# Simulate failed hooks
HOOKS_OUTCOME="failure"
if [[ "$HOOKS_OUTCOME" == "success" ]]; then
hooks_passed="true"
else
hooks_passed="false"
fi
if [[ "$hooks_passed" != "false" ]]; then
echo "❌ ERROR: hooks_passed should be false for failure"
exit 1
fi
echo "✓ hooks_passed output correct for failure"
- name: Test files_changed output
run: |
# Simulate git status check
echo "test.txt" > /tmp/test-changes.txt
if [[ -s /tmp/test-changes.txt ]]; then
files_changed="true"
else
files_changed="false"
fi
if [[ "$files_changed" != "true" ]]; then
echo "❌ ERROR: files_changed should be true when files exist"
exit 1
fi
echo "✓ files_changed output correct"
test-pre-commit-uv-integration:
name: Test UV Integration
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test PRE_COMMIT_USE_UV environment variable
run: |
PRE_COMMIT_USE_UV='1'
if [[ "$PRE_COMMIT_USE_UV" != "1" ]]; then
echo "❌ ERROR: PRE_COMMIT_USE_UV should be set to 1"
exit 1
fi
echo "✓ PRE_COMMIT_USE_UV correctly set"
echo "✓ pre-commit will use UV for faster installations"
test-pre-commit-workflow-scenarios:
name: Test Workflow Scenarios
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test full workflow (all files)
run: |
echo "Simulating full workflow with --all-files..."
# 1. Validate inputs
CONFIG_FILE=".pre-commit-config.yaml"
echo "✓ Step 1: Validate inputs"
# 2. Set git config
git config user.name "Test User"
git config user.email "test@example.com"
echo "✓ Step 2: Set git config"
# 3. Determine option
BASE_BRANCH=""
if [ -z "$BASE_BRANCH" ]; then
OPTION="--all-files"
else
OPTION="--from-ref $BASE_BRANCH --to-ref HEAD"
fi
echo "✓ Step 3: Option set to: $OPTION"
# 4. Run pre-commit (simulated)
echo "✓ Step 4: Would run: pre-commit run $OPTION"
# 5. Check for changes
echo "✓ Step 5: Check for changes to commit"
echo "✓ Full workflow simulation completed"
- name: Test diff workflow (with base branch)
run: |
echo "Simulating diff workflow with base branch..."
# 1. Validate inputs
CONFIG_FILE=".pre-commit-config.yaml"
BASE_BRANCH="main"
echo "✓ Step 1: Validate inputs (base-branch: $BASE_BRANCH)"
# 2. Set git config
git config user.name "GitHub Actions"
git config user.email "github-actions@github.com"
echo "✓ Step 2: Set git config"
# 3. Determine option
if [ -z "$BASE_BRANCH" ]; then
OPTION="--all-files"
else
OPTION="--from-ref $BASE_BRANCH --to-ref HEAD"
fi
echo "✓ Step 3: Option set to: $OPTION"
# 4. Run pre-commit (simulated)
echo "✓ Step 4: Would run: pre-commit run $OPTION"
# 5. Check for changes
echo "✓ Step 5: Check for changes to commit"
echo "✓ Diff workflow simulation completed"
test-pre-commit-autofix-behavior:
name: Test Autofix Behavior
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test autofix commit message
run: |
COMMIT_MESSAGE="style(pre-commit): autofix"
if [[ "$COMMIT_MESSAGE" != "style(pre-commit): autofix" ]]; then
echo "❌ ERROR: Incorrect commit message"
exit 1
fi
echo "✓ Autofix commit message correct"
- name: Test git add options
run: |
ADD_OPTIONS="-u"
if [[ "$ADD_OPTIONS" != "-u" ]]; then
echo "❌ ERROR: Incorrect add options"
exit 1
fi
echo "✓ Git add options correct (-u for tracked files)"
- name: Test autofix always runs
run: |
# Simulate pre-commit failure
PRECOMMIT_FAILED=true
# Autofix should still run (if: always())
echo "✓ Autofix runs even when pre-commit fails"
integration-test-summary:
name: Integration Test Summary
runs-on: ubuntu-latest
needs:
- test-pre-commit-validation
- test-pre-commit-git-config
- test-pre-commit-option-generation
- test-pre-commit-config-file-detection
- test-pre-commit-hook-execution
- test-pre-commit-outputs
- test-pre-commit-uv-integration
- test-pre-commit-workflow-scenarios
- test-pre-commit-autofix-behavior
steps:
- name: Summary
run: |
echo "=========================================="
echo "Pre-commit Integration Tests - PASSED"
echo "=========================================="
echo ""
echo "✓ Input validation tests"
echo "✓ Git configuration tests"
echo "✓ Option generation tests"
echo "✓ Config file detection tests"
echo "✓ Hook execution tests"
echo "✓ Output verification tests"
echo "✓ UV integration tests"
echo "✓ Workflow scenario tests"
echo "✓ Autofix behavior tests"
echo ""
echo "All pre-commit integration tests completed successfully!"

View File

@@ -0,0 +1,414 @@
---
name: Integration Test - Version Validator
on:
workflow_dispatch:
push:
paths:
- 'version-validator/**'
- '_tests/integration/workflows/version-validator-test.yml'
jobs:
test-version-validator-input-validation:
name: Test Input Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test empty version (should fail)
run: |
VERSION=""
if [[ -z "$VERSION" ]]; then
echo "✓ Empty version correctly rejected"
else
echo "❌ ERROR: Empty version should be rejected"
exit 1
fi
- name: Test dangerous characters in version
run: |
for version in "1.2.3;rm -rf /" "1.0&&echo" "1.0|cat" '1.0`cmd`' "1.0\$variable"; do
if [[ "$version" == *";"* ]] || [[ "$version" == *"&&"* ]] || \
[[ "$version" == *"|"* ]] || [[ "$version" == *"\`"* ]] || [[ "$version" == *"\$"* ]]; then
echo "✓ Dangerous version '$version' correctly detected"
else
echo "❌ ERROR: Should detect dangerous characters in: $version"
exit 1
fi
done
- name: Test valid version strings
run: |
for version in "1.2.3" "v1.0.0" "2.0.0-alpha" "1.0.0+build"; do
if [[ "$version" == *";"* ]] || [[ "$version" == *"&&"* ]] || \
[[ "$version" == *"|"* ]] || [[ "$version" == *"\`"* ]] || [[ "$version" == *"\$"* ]]; then
echo "❌ ERROR: Valid version should not be rejected: $version"
exit 1
else
echo "✓ Valid version '$version' accepted"
fi
done
test-version-validator-regex-validation:
name: Test Regex Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test empty regex (should fail)
run: |
REGEX=""
if [[ -z "$REGEX" ]]; then
echo "✓ Empty regex correctly rejected"
else
echo "❌ ERROR: Empty regex should be rejected"
exit 1
fi
- name: Test potential ReDoS patterns
run: |
for regex in ".*.*" ".+.+"; do
if [[ "$regex" == *".*.*"* ]] || [[ "$regex" == *".+.+"* ]]; then
echo "✓ ReDoS pattern '$regex' detected (would show warning)"
else
echo "❌ ERROR: Should detect ReDoS pattern: $regex"
exit 1
fi
done
- name: Test safe regex patterns
run: |
for regex in "^[0-9]+\.[0-9]+$" "^v?[0-9]+"; do
if [[ "$regex" == *".*.*"* ]] || [[ "$regex" == *".+.+"* ]]; then
echo "❌ ERROR: Safe regex should not be flagged: $regex"
exit 1
else
echo "✓ Safe regex '$regex' accepted"
fi
done
test-version-validator-language-validation:
name: Test Language Parameter Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test dangerous characters in language
run: |
for lang in "node;rm" "python&&cmd" "ruby|cat"; do
if [[ "$lang" == *";"* ]] || [[ "$lang" == *"&&"* ]] || [[ "$lang" == *"|"* ]]; then
echo "✓ Dangerous language parameter '$lang' correctly detected"
else
echo "❌ ERROR: Should detect dangerous characters in: $lang"
exit 1
fi
done
- name: Test valid language parameters
run: |
for lang in "node" "python" "ruby" "go" "java"; do
if [[ "$lang" == *";"* ]] || [[ "$lang" == *"&&"* ]] || [[ "$lang" == *"|"* ]]; then
echo "❌ ERROR: Valid language should not be rejected: $lang"
exit 1
else
echo "✓ Valid language '$lang' accepted"
fi
done
test-version-validator-version-cleaning:
name: Test Version Cleaning
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test v prefix removal
run: |
for input in "v1.2.3" "V2.0.0"; do
cleaned=$(echo "$input" | sed -e 's/^[vV]//')
if [[ "$cleaned" == "1.2.3" ]] || [[ "$cleaned" == "2.0.0" ]]; then
echo "✓ v prefix removed from '$input' -> '$cleaned'"
else
echo "❌ ERROR: Failed to clean '$input', got '$cleaned'"
exit 1
fi
done
- name: Test whitespace removal
run: |
input=" 1.2.3 "
cleaned=$(echo "$input" | tr -d ' ')
if [[ "$cleaned" == "1.2.3" ]]; then
echo "✓ Whitespace removed: '$input' -> '$cleaned'"
else
echo "❌ ERROR: Failed to remove whitespace"
exit 1
fi
- name: Test newline removal
run: |
input=$'1.2.3\n'
cleaned=$(echo "$input" | tr -d '\n' | tr -d '\r')
if [[ "$cleaned" == "1.2.3" ]]; then
echo "✓ Newlines removed"
else
echo "❌ ERROR: Failed to remove newlines"
exit 1
fi
test-version-validator-regex-matching:
name: Test Regex Matching
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test default SemVer regex
run: |
REGEX='^[0-9]+\.[0-9]+(\.[0-9]+)?(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$'
for version in "1.0.0" "1.2" "1.0.0-alpha" "1.0.0+build" "2.1.0-rc.1+build.123"; do
if [[ $version =~ $REGEX ]]; then
echo "✓ Version '$version' matches SemVer regex"
else
echo "❌ ERROR: Version '$version' should match SemVer"
exit 1
fi
done
- name: Test invalid versions against SemVer regex
run: |
REGEX='^[0-9]+\.[0-9]+(\.[0-9]+)?(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$'
for version in "abc" "1.a.b" "not.a.version"; do
if [[ $version =~ $REGEX ]]; then
echo "❌ ERROR: Invalid version '$version' should not match"
exit 1
else
echo "✓ Invalid version '$version' correctly rejected"
fi
done
- name: Test custom strict regex
run: |
REGEX='^[0-9]+\.[0-9]+\.[0-9]+$'
# Should match
for version in "1.0.0" "2.5.10"; do
if [[ $version =~ $REGEX ]]; then
echo "✓ Version '$version' matches strict regex"
else
echo "❌ ERROR: Version '$version' should match strict regex"
exit 1
fi
done
# Should not match
for version in "1.0" "1.0.0-alpha"; do
if [[ $version =~ $REGEX ]]; then
echo "❌ ERROR: Version '$version' should not match strict regex"
exit 1
else
echo "✓ Version '$version' correctly rejected by strict regex"
fi
done
test-version-validator-outputs:
name: Test Output Generation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test valid version outputs (simulation)
run: |
VERSION="v1.2.3"
REGEX='^[0-9]+\.[0-9]+\.[0-9]+$'
# Clean version
cleaned=$(echo "$VERSION" | sed -e 's/^[vV]//' | tr -d ' ' | tr -d '\n' | tr -d '\r')
# Validate
if [[ $cleaned =~ $REGEX ]]; then
is_valid="true"
validated_version="$cleaned"
error_message=""
echo "is_valid=$is_valid"
echo "validated_version=$validated_version"
echo "error_message=$error_message"
if [[ "$is_valid" != "true" ]]; then
echo "❌ ERROR: Should be valid"
exit 1
fi
if [[ "$validated_version" != "1.2.3" ]]; then
echo "❌ ERROR: Wrong validated version"
exit 1
fi
echo "✓ Valid version outputs correct"
fi
- name: Test invalid version outputs (simulation)
run: |
VERSION="not.a.version"
REGEX='^[0-9]+\.[0-9]+\.[0-9]+$'
LANGUAGE="test"
# Clean version
cleaned=$(echo "$VERSION" | sed -e 's/^[vV]//' | tr -d ' ' | tr -d '\n' | tr -d '\r')
# Validate
if [[ $cleaned =~ $REGEX ]]; then
is_valid="true"
else
is_valid="false"
validated_version=""
error_msg="Invalid $LANGUAGE version format: '$VERSION' (cleaned: '$cleaned'). Expected pattern: $REGEX"
error_message=$(echo "$error_msg" | tr -d '\n\r')
echo "is_valid=$is_valid"
echo "validated_version=$validated_version"
echo "error_message=$error_message"
if [[ "$is_valid" != "false" ]]; then
echo "❌ ERROR: Should be invalid"
exit 1
fi
if [[ -n "$validated_version" ]]; then
echo "❌ ERROR: Validated version should be empty"
exit 1
fi
if [[ -z "$error_message" ]]; then
echo "❌ ERROR: Error message should not be empty"
exit 1
fi
echo "✓ Invalid version outputs correct"
fi
test-version-validator-sanitization:
name: Test Output Sanitization
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test error message sanitization
run: |
error_msg=$'Error message\nwith newlines'
sanitized=$(echo "$error_msg" | tr -d '\n\r')
if [[ "$sanitized" == *$'\n'* ]] || [[ "$sanitized" == *$'\r'* ]]; then
echo "❌ ERROR: Newlines not removed from error message"
exit 1
fi
echo "✓ Error message sanitization works"
- name: Test validated version sanitization
run: |
VERSION=$'1.2.3\n'
cleaned=$(echo "$VERSION" | sed -e 's/^[vV]//' | tr -d ' ' | tr -d '\n' | tr -d '\r')
if [[ "$cleaned" == *$'\n'* ]] || [[ "$cleaned" == *$'\r'* ]]; then
echo "❌ ERROR: Newlines not removed from validated version"
exit 1
fi
echo "✓ Validated version sanitization works"
test-version-validator-real-world-scenarios:
name: Test Real World Scenarios
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test Node.js version validation
run: |
REGEX='^[0-9]+(\.[0-9]+(\.[0-9]+)?)?$'
for version in "20" "20.9" "20.9.0" "18.17.1"; do
cleaned=$(echo "$version" | sed -e 's/^[vV]//')
if [[ $cleaned =~ $REGEX ]]; then
echo "✓ Node.js version '$version' valid"
else
echo "❌ ERROR: Node.js version should be valid"
exit 1
fi
done
- name: Test Python version validation
run: |
REGEX='^[0-9]+\.[0-9]+(\.[0-9]+)?$'
for version in "3.11" "3.11.5" "3.12.0"; do
cleaned=$(echo "$version" | sed -e 's/^[vV]//')
if [[ $cleaned =~ $REGEX ]]; then
echo "✓ Python version '$version' valid"
else
echo "❌ ERROR: Python version should be valid"
exit 1
fi
done
- name: Test CalVer validation
run: |
REGEX='^[0-9]{4}\.[0-9]{1,2}(\.[0-9]+)?$'
for version in "2024.3" "2024.3.15" "2024.10.1"; do
cleaned=$(echo "$version" | sed -e 's/^[vV]//')
if [[ $cleaned =~ $REGEX ]]; then
echo "✓ CalVer version '$version' valid"
else
echo "❌ ERROR: CalVer version should be valid"
exit 1
fi
done
- name: Test Docker tag validation
run: |
REGEX='^[a-z0-9][a-z0-9._-]*$'
for tag in "latest" "v1.2.3" "stable-alpine" "2024.10.15"; do
cleaned=$(echo "$tag" | sed -e 's/^[vV]//')
# Note: Docker tags are case-insensitive, so convert to lowercase
cleaned=$(echo "$cleaned" | tr '[:upper:]' '[:lower:]')
if [[ $cleaned =~ $REGEX ]]; then
echo "✓ Docker tag '$tag' valid"
else
echo "❌ ERROR: Docker tag should be valid: $tag"
exit 1
fi
done
integration-test-summary:
name: Integration Test Summary
runs-on: ubuntu-latest
needs:
- test-version-validator-input-validation
- test-version-validator-regex-validation
- test-version-validator-language-validation
- test-version-validator-version-cleaning
- test-version-validator-regex-matching
- test-version-validator-outputs
- test-version-validator-sanitization
- test-version-validator-real-world-scenarios
steps:
- name: Summary
run: |
echo "=========================================="
echo "Version Validator Integration Tests - PASSED"
echo "=========================================="
echo ""
echo "✓ Input validation tests"
echo "✓ Regex validation tests"
echo "✓ Language validation tests"
echo "✓ Version cleaning tests"
echo "✓ Regex matching tests"
echo "✓ Output generation tests"
echo "✓ Sanitization tests"
echo "✓ Real world scenario tests"
echo ""
echo "All version-validator integration tests completed successfully!"

View File

@@ -10,7 +10,7 @@ Lints and fixes Ansible playbooks, commits changes, and uploads SARIF report.
| name | description | required | default |
|---------------|--------------------------------------------------------------------|----------|-----------------------------|
| `token` | <p>GitHub token for authentication</p> | `false` | `${{ github.token }}` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
| `username` | <p>GitHub username for commits</p> | `false` | `github-actions` |
| `email` | <p>GitHub email for commits</p> | `false` | `github-actions@github.com` |
| `max-retries` | <p>Maximum number of retry attempts for pip install operations</p> | `false` | `3` |
@@ -36,7 +36,7 @@ This action is a `composite` action.
# GitHub token for authentication
#
# Required: false
# Default: ${{ github.token }}
# Default: ""
username:
# GitHub username for commits

View File

@@ -15,7 +15,7 @@ inputs:
token:
description: 'GitHub token for authentication'
required: false
default: ${{ github.token }}
default: ''
username:
description: 'GitHub username for commits'
required: false
@@ -104,6 +104,11 @@ runs:
echo "No Ansible files found. Skipping lint and fix."
fi
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Cache Python Dependencies
if: steps.check-files.outputs.files_found == 'true'
id: cache-pip
@@ -177,6 +182,6 @@ runs:
- name: Upload SARIF Report
if: steps.check-files.outputs.files_found == 'true'
uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
with:
sarif_file: ansible-lint.sarif

View File

@@ -233,6 +233,6 @@ runs:
- name: Upload Biome Results
if: always()
uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
with:
sarif_file: biome-report.sarif

View File

@@ -189,7 +189,7 @@ runs:
echo "Using build mode: $build_mode"
- name: Initialize CodeQL
uses: github/codeql-action/init@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/init@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
with:
languages: ${{ inputs.language }}
queries: ${{ inputs.queries }}
@@ -202,12 +202,12 @@ runs:
threads: ${{ inputs.threads }}
- name: Autobuild
uses: github/codeql-action/autobuild@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/autobuild@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
if: ${{ steps.set-build-mode.outputs.build-mode == 'autobuild' }}
- name: Perform CodeQL Analysis
id: analysis
uses: github/codeql-action/analyze@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/analyze@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
with:
category: ${{ steps.set-category.outputs.category }}
upload: ${{ inputs.upload-results }}

View File

@@ -12,6 +12,7 @@ Builds and tests C# projects.
|------------------|-----------------------------------------------------------------------|----------|---------|
| `dotnet-version` | <p>Version of .NET SDK to use.</p> | `false` | `""` |
| `max-retries` | <p>Maximum number of retry attempts for dotnet restore operations</p> | `false` | `3` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
@@ -43,4 +44,10 @@ This action is a `composite` action.
#
# Required: false
# Default: 3
token:
# GitHub token for authentication
#
# Required: false
# Default: ""
```

View File

@@ -18,6 +18,10 @@ inputs:
description: 'Maximum number of retry attempts for dotnet restore operations'
required: false
default: '3'
token:
description: 'GitHub token for authentication'
required: false
default: ''
outputs:
build_status:
@@ -39,6 +43,11 @@ outputs:
runs:
using: composite
steps:
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Detect .NET SDK Version
id: detect-dotnet-version
uses: ./dotnet-version-detect

View File

@@ -2,7 +2,7 @@
# Validation rules for csharp-build action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
# Coverage: 100% (2/2 inputs)
# Coverage: 100% (3/3 inputs)
#
# This file defines validation rules for the csharp-build GitHub Action.
# Rules are automatically applied by validate-inputs action when this
@@ -17,13 +17,15 @@ required_inputs: []
optional_inputs:
- dotnet-version
- max-retries
- token
conventions:
dotnet-version: dotnet_version
max-retries: numeric_range_1_10
token: github_token
overrides: {}
statistics:
total_inputs: 2
validated_inputs: 2
total_inputs: 3
validated_inputs: 3
skipped_inputs: 0
coverage_percentage: 100
validation_coverage: 100
@@ -31,7 +33,7 @@ auto_detected: true
manual_review_required: false
quality_indicators:
has_required_inputs: false
has_token_validation: false
has_token_validation: true
has_version_validation: true
has_file_validation: false
has_security_validation: false
has_security_validation: true

View File

@@ -8,9 +8,10 @@ Runs linters like StyleCop or dotnet-format for C# code style checks.
### Inputs
| name | description | required | default |
|------------------|------------------------------------|----------|---------|
| `dotnet-version` | <p>Version of .NET SDK to use.</p> | `false` | `""` |
| name | description | required | default |
|------------------|----------------------------------------|----------|---------|
| `dotnet-version` | <p>Version of .NET SDK to use.</p> | `false` | `""` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
@@ -34,4 +35,10 @@ This action is a `composite` action.
#
# Required: false
# Default: ""
token:
# GitHub token for authentication
#
# Required: false
# Default: ""
```

View File

@@ -15,6 +15,10 @@ inputs:
dotnet-version:
description: 'Version of .NET SDK to use.'
required: false
token:
description: 'GitHub token for authentication'
required: false
default: ''
outputs:
lint_status:
@@ -55,6 +59,11 @@ runs:
echo "Input validation completed successfully"
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Detect .NET SDK Version
id: detect-dotnet-version
uses: ./dotnet-version-detect
@@ -102,6 +111,6 @@ runs:
fi
- name: Upload SARIF Report
uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
with:
sarif_file: dotnet-format.sarif

View File

@@ -2,7 +2,7 @@
# Validation rules for csharp-lint-check action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
# Coverage: 100% (1/1 inputs)
# Coverage: 100% (2/2 inputs)
#
# This file defines validation rules for the csharp-lint-check GitHub Action.
# Rules are automatically applied by validate-inputs action when this
@@ -16,12 +16,14 @@ generator_version: 1.0.0
required_inputs: []
optional_inputs:
- dotnet-version
- token
conventions:
dotnet-version: dotnet_version
token: github_token
overrides: {}
statistics:
total_inputs: 1
validated_inputs: 1
total_inputs: 2
validated_inputs: 2
skipped_inputs: 0
coverage_percentage: 100
validation_coverage: 100
@@ -29,7 +31,7 @@ auto_detected: true
manual_review_required: false
quality_indicators:
has_required_inputs: false
has_token_validation: false
has_token_validation: true
has_version_validation: true
has_file_validation: false
has_security_validation: false
has_security_validation: true

View File

@@ -44,6 +44,11 @@ runs:
run: |
echo "::add-mask::$API_KEY"
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Validate Inputs
id: validate
uses: ./validate-inputs

View File

@@ -140,6 +140,11 @@ outputs:
runs:
using: composite
steps:
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Validate Inputs
id: validate
uses: ./validate-inputs
@@ -523,7 +528,7 @@ runs:
- name: Install Cosign
if: inputs.sign-image == 'true' && inputs.push == 'true' && inputs.dry-run != 'true'
uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
- name: Sign Image
id: sign

View File

@@ -213,7 +213,7 @@ runs:
- name: Set up Cosign
if: inputs.provenance == 'true' || inputs.sign-image == 'true'
uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
- name: Detect Available Platforms
id: detect-platforms

View File

@@ -213,7 +213,7 @@ runs:
- name: Set up Cosign
if: inputs.provenance == 'true'
uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
- name: Update Docker Hub Description
if: inputs.repository-description != '' || inputs.readme-file != ''
@@ -409,7 +409,7 @@ runs:
- name: Install Cosign
if: inputs.sign-image == 'true'
uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
- name: Sign Published Image
id: sign

View File

@@ -21,6 +21,7 @@ Publish a Docker image to GitHub Packages and Docker Hub.
| `verbose` | <p>Enable verbose logging</p> | `false` | `false` |
| `dockerhub-username` | <p>Docker Hub username for authentication</p> | `false` | `""` |
| `dockerhub-password` | <p>Docker Hub password or access token for authentication</p> | `false` | `""` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
@@ -109,4 +110,10 @@ This action is a `composite` action.
#
# Required: false
# Default: ""
token:
# GitHub token for authentication
#
# Required: false
# Default: ""
```

View File

@@ -54,6 +54,10 @@ inputs:
dockerhub-password:
description: 'Docker Hub password or access token for authentication'
required: false
token:
description: 'GitHub token for authentication'
required: false
default: ''
outputs:
registry:
@@ -84,6 +88,18 @@ outputs:
runs:
using: composite
steps:
- name: Mask Sensitive Inputs
shell: bash
env:
DOCKERHUB_PASSWORD: ${{ inputs.dockerhub-password }}
run: |
set -euo pipefail
# Mask Docker Hub credentials to prevent exposure in logs
if [[ -n "${DOCKERHUB_PASSWORD}" ]]; then
echo "::add-mask::${DOCKERHUB_PASSWORD}"
fi
- name: Validate Inputs
id: validate
shell: bash
@@ -147,6 +163,11 @@ runs:
echo "Publishing to: $REGISTRY"
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Build Multi-Arch Docker Image
id: build
uses: ./docker-build

View File

@@ -2,7 +2,7 @@
# Validation rules for docker-publish action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
# Coverage: 100% (11/11 inputs)
# Coverage: 100% (12/12 inputs)
#
# This file defines validation rules for the docker-publish GitHub Action.
# Rules are automatically applied by validate-inputs action when this
@@ -25,6 +25,7 @@ optional_inputs:
- platforms
- scan-image
- sign-image
- token
- verbose
conventions:
auto-detect-platforms: docker_architectures
@@ -37,14 +38,15 @@ conventions:
registry: registry
scan-image: boolean
sign-image: boolean
token: github_token
verbose: boolean
overrides:
cache-mode: cache_mode
platforms: null
registry: registry_enum
statistics:
total_inputs: 11
validated_inputs: 11
total_inputs: 12
validated_inputs: 12
skipped_inputs: 1
coverage_percentage: 100
validation_coverage: 100
@@ -52,7 +54,7 @@ auto_detected: true
manual_review_required: false
quality_indicators:
has_required_inputs: true
has_token_validation: false
has_token_validation: true
has_version_validation: true
has_file_validation: false
has_security_validation: true

View File

@@ -11,6 +11,7 @@ Detects .NET SDK version from global.json or defaults to a specified version.
| name | description | required | default |
|-------------------|---------------------------------------------------------------------|----------|---------|
| `default-version` | <p>Default .NET SDK version to use if global.json is not found.</p> | `true` | `7.0` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
@@ -32,4 +33,10 @@ This action is a `composite` action.
#
# Required: true
# Default: 7.0
token:
# GitHub token for authentication
#
# Required: false
# Default: ""
```

View File

@@ -15,6 +15,10 @@ inputs:
description: 'Default .NET SDK version to use if global.json is not found.'
required: true
default: '7.0'
token:
description: 'GitHub token for authentication'
required: false
default: ''
outputs:
dotnet-version:
@@ -47,6 +51,11 @@ runs:
echo "Input validation completed successfully"
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Parse .NET Version
id: parse-version
uses: ./version-file-parser

View File

@@ -2,7 +2,7 @@
# Validation rules for dotnet-version-detect action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
# Coverage: 100% (1/1 inputs)
# Coverage: 100% (2/2 inputs)
#
# This file defines validation rules for the dotnet-version-detect GitHub Action.
# Rules are automatically applied by validate-inputs action when this
@@ -15,14 +15,16 @@ description: Detects .NET SDK version from global.json or defaults to a specifie
generator_version: 1.0.0
required_inputs:
- default-version
optional_inputs: []
optional_inputs:
- token
conventions:
default-version: semantic_version
token: github_token
overrides:
default-version: dotnet_version
statistics:
total_inputs: 1
validated_inputs: 1
total_inputs: 2
validated_inputs: 2
skipped_inputs: 0
coverage_percentage: 100
validation_coverage: 100
@@ -30,7 +32,7 @@ auto_detected: true
manual_review_required: false
quality_indicators:
has_required_inputs: true
has_token_validation: false
has_token_validation: true
has_version_validation: true
has_file_validation: false
has_security_validation: false
has_security_validation: true

View File

@@ -20,6 +20,7 @@ Run ESLint check on the repository with advanced configuration and reporting
| `fail-on-error` | <p>Fail workflow if issues are found</p> | `false` | `true` |
| `report-format` | <p>Output format (stylish, json, sarif)</p> | `false` | `sarif` |
| `max-retries` | <p>Maximum number of retry attempts</p> | `false` | `3` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
@@ -98,4 +99,10 @@ This action is a `composite` action.
#
# Required: false
# Default: 3
token:
# GitHub token for authentication
#
# Required: false
# Default: ""
```

View File

@@ -52,6 +52,10 @@ inputs:
description: 'Maximum number of retry attempts'
required: false
default: '3'
token:
description: 'GitHub token for authentication'
required: false
default: ''
outputs:
error-count:
@@ -165,6 +169,11 @@ runs:
exit 1
fi
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Setup Node.js
id: node-setup
uses: ./node-setup
@@ -405,7 +414,7 @@ runs:
- name: Upload ESLint Results
if: always() && inputs.report-format == 'sarif'
uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
with:
sarif_file: ${{ inputs.working-directory }}/reports/eslint.sarif
category: eslint

View File

@@ -2,7 +2,7 @@
# Validation rules for eslint-check action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
# Coverage: 100% (10/10 inputs)
# Coverage: 100% (11/11 inputs)
#
# This file defines validation rules for the eslint-check GitHub Action.
# Rules are automatically applied by validate-inputs action when this
@@ -24,6 +24,7 @@ optional_inputs:
- max-retries
- max-warnings
- report-format
- token
- working-directory
conventions:
cache: boolean
@@ -35,11 +36,12 @@ conventions:
max-retries: numeric_range_1_10
max-warnings: numeric_range_0_10000
report-format: report_format
token: github_token
working-directory: file_path
overrides: {}
statistics:
total_inputs: 10
validated_inputs: 10
total_inputs: 11
validated_inputs: 11
skipped_inputs: 0
coverage_percentage: 100
validation_coverage: 100
@@ -47,7 +49,7 @@ auto_detected: true
manual_review_required: false
quality_indicators:
has_required_inputs: false
has_token_validation: false
has_token_validation: true
has_version_validation: true
has_file_validation: true
has_security_validation: false
has_security_validation: true

View File

@@ -13,6 +13,7 @@ Builds the Go project.
| `go-version` | <p>Go version to use.</p> | `false` | `""` |
| `destination` | <p>Build destination directory.</p> | `false` | `./bin` |
| `max-retries` | <p>Maximum number of retry attempts for go mod download operations</p> | `false` | `3` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
@@ -50,4 +51,10 @@ This action is a `composite` action.
#
# Required: false
# Default: 3
token:
# GitHub token for authentication
#
# Required: false
# Default: ""
```

View File

@@ -22,6 +22,10 @@ inputs:
description: 'Maximum number of retry attempts for go mod download operations'
required: false
default: '3'
token:
description: 'GitHub token for authentication'
required: false
default: ''
outputs:
build_status:
@@ -43,6 +47,11 @@ outputs:
runs:
using: composite
steps:
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Detect Go Version
id: detect-go-version
uses: ./go-version-detect

View File

@@ -2,7 +2,7 @@
# Validation rules for go-build action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
# Coverage: 100% (3/3 inputs)
# Coverage: 100% (4/4 inputs)
#
# This file defines validation rules for the go-build GitHub Action.
# Rules are automatically applied by validate-inputs action when this
@@ -18,14 +18,16 @@ optional_inputs:
- destination
- go-version
- max-retries
- token
conventions:
destination: file_path
go-version: semantic_version
max-retries: numeric_range_1_10
token: github_token
overrides: {}
statistics:
total_inputs: 3
validated_inputs: 3
total_inputs: 4
validated_inputs: 4
skipped_inputs: 0
coverage_percentage: 100
validation_coverage: 100
@@ -33,7 +35,7 @@ auto_detected: true
manual_review_required: false
quality_indicators:
has_required_inputs: false
has_token_validation: false
has_token_validation: true
has_version_validation: true
has_file_validation: true
has_security_validation: false
has_security_validation: true

View File

@@ -23,6 +23,7 @@ Run golangci-lint with advanced configuration, caching, and reporting
| `disable-all` | <p>Disable all linters (useful with --enable-\*)</p> | `false` | `false` |
| `enable-linters` | <p>Comma-separated list of linters to enable</p> | `false` | `""` |
| `disable-linters` | <p>Comma-separated list of linters to disable</p> | `false` | `""` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
@@ -119,4 +120,10 @@ This action is a `composite` action.
#
# Required: false
# Default: ""
token:
# GitHub token for authentication
#
# Required: false
# Default: ""
```

View File

@@ -62,6 +62,10 @@ inputs:
disable-linters:
description: 'Comma-separated list of linters to disable'
required: false
token:
description: 'GitHub token for authentication'
required: false
default: ''
outputs:
error-count:
@@ -199,6 +203,11 @@ runs:
go-version: ${{ inputs.go-version }}
cache: true
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Set up Cache
id: cache
if: inputs.cache == 'true'
@@ -394,7 +403,7 @@ runs:
- name: Upload Lint Results
if: always() && inputs.report-format == 'sarif'
uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
with:
sarif_file: ${{ inputs.working-directory }}/reports/golangci-lint.sarif
category: golangci-lint

View File

@@ -2,7 +2,7 @@
# Validation rules for go-lint action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
# Coverage: 100% (13/13 inputs)
# Coverage: 100% (14/14 inputs)
#
# This file defines validation rules for the go-lint GitHub Action.
# Rules are automatically applied by validate-inputs action when this
@@ -27,6 +27,7 @@ optional_inputs:
- only-new-issues
- report-format
- timeout
- token
- working-directory
conventions:
cache: boolean
@@ -41,14 +42,15 @@ conventions:
only-new-issues: branch_name
report-format: report_format
timeout: numeric_range_1_3600
token: github_token
working-directory: file_path
overrides:
go-version: go_version
only-new-issues: boolean
timeout: timeout_with_unit
statistics:
total_inputs: 13
validated_inputs: 13
total_inputs: 14
validated_inputs: 14
skipped_inputs: 0
coverage_percentage: 100
validation_coverage: 100
@@ -56,7 +58,7 @@ auto_detected: true
manual_review_required: false
quality_indicators:
has_required_inputs: false
has_token_validation: false
has_token_validation: true
has_version_validation: true
has_file_validation: true
has_security_validation: false
has_security_validation: true

View File

@@ -11,6 +11,7 @@ Detects the Go version from the project's go.mod file or defaults to a specified
| name | description | required | default |
|-------------------|----------------------------------------------------------|----------|---------|
| `default-version` | <p>Default Go version to use if go.mod is not found.</p> | `false` | `1.25` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
@@ -32,4 +33,10 @@ This action is a `composite` action.
#
# Required: false
# Default: 1.25
token:
# GitHub token for authentication
#
# Required: false
# Default: ""
```

View File

@@ -15,6 +15,10 @@ inputs:
description: 'Default Go version to use if go.mod is not found.'
required: false
default: '1.25'
token:
description: 'GitHub token for authentication'
required: false
default: ''
outputs:
go-version:
@@ -54,6 +58,11 @@ runs:
echo "Input validation completed successfully"
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Parse Go Version
id: parse-version
uses: ./version-file-parser

View File

@@ -2,7 +2,7 @@
# Validation rules for go-version-detect action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
# Coverage: 100% (1/1 inputs)
# Coverage: 100% (2/2 inputs)
#
# This file defines validation rules for the go-version-detect GitHub Action.
# Rules are automatically applied by validate-inputs action when this
@@ -16,13 +16,15 @@ generator_version: 1.0.0
required_inputs: []
optional_inputs:
- default-version
- token
conventions:
default-version: semantic_version
token: github_token
overrides:
default-version: go_version
statistics:
total_inputs: 1
validated_inputs: 1
total_inputs: 2
validated_inputs: 2
skipped_inputs: 0
coverage_percentage: 100
validation_coverage: 100
@@ -30,7 +32,7 @@ auto_detected: true
manual_review_required: false
quality_indicators:
has_required_inputs: false
has_token_validation: false
has_token_validation: true
has_version_validation: true
has_file_validation: false
has_security_validation: false
has_security_validation: true

View File

@@ -169,6 +169,11 @@ runs:
echo "Input validation completed successfully"
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Parse Node.js Version
id: version
uses: ./version-file-parser

View File

@@ -8,12 +8,13 @@ Publishes the package to the NPM registry with configurable scope and registry U
### Inputs
| name | description | required | default |
|-------------------|-------------------------------------|----------|----------------------------------------|
| `registry-url` | <p>Registry URL for publishing.</p> | `false` | `https://registry.npmjs.org/` |
| `scope` | <p>Package scope to use.</p> | `false` | `@ivuorinen` |
| `package-version` | <p>The version to publish.</p> | `false` | `${{ github.event.release.tag_name }}` |
| `npm_token` | <p>NPM token.</p> | `true` | `""` |
| name | description | required | default |
|-------------------|----------------------------------------|----------|----------------------------------------|
| `registry-url` | <p>Registry URL for publishing.</p> | `false` | `https://registry.npmjs.org/` |
| `scope` | <p>Package scope to use.</p> | `false` | `@ivuorinen` |
| `package-version` | <p>The version to publish.</p> | `false` | `${{ github.event.release.tag_name }}` |
| `npm_token` | <p>NPM token.</p> | `true` | `""` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
@@ -55,4 +56,10 @@ This action is a `composite` action.
#
# Required: true
# Default: ""
token:
# GitHub token for authentication
#
# Required: false
# Default: ""
```

View File

@@ -28,6 +28,10 @@ inputs:
description: 'NPM token.'
required: true
default: ''
token:
description: 'GitHub token for authentication'
required: false
default: ''
outputs:
registry-url:
@@ -91,6 +95,11 @@ runs:
exit 1
fi
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Setup Node.js
uses: ./node-setup

View File

@@ -2,7 +2,7 @@
# Validation rules for npm-publish action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
# Coverage: 100% (4/4 inputs)
# Coverage: 100% (5/5 inputs)
#
# This file defines validation rules for the npm-publish GitHub Action.
# Rules are automatically applied by validate-inputs action when this
@@ -19,16 +19,18 @@ optional_inputs:
- package-version
- registry-url
- scope
- token
conventions:
npm_token: github_token
package-version: semantic_version
registry-url: url
scope: scope
token: github_token
overrides:
package-version: strict_semantic_version
statistics:
total_inputs: 4
validated_inputs: 4
total_inputs: 5
validated_inputs: 5
skipped_inputs: 0
coverage_percentage: 100
validation_coverage: 100
@@ -36,7 +38,7 @@ auto_detected: true
manual_review_required: false
quality_indicators:
has_required_inputs: true
has_token_validation: false
has_token_validation: true
has_version_validation: true
has_file_validation: false
has_security_validation: true

View File

@@ -17,7 +17,7 @@ Runs Composer install on a repository with advanced caching and configuration.
| `composer-version` | <p>Composer version to use (1 or 2)</p> | `false` | `2` |
| `stability` | <p>Minimum stability (stable, RC, beta, alpha, dev)</p> | `false` | `stable` |
| `cache-directories` | <p>Additional directories to cache (comma-separated)</p> | `false` | `""` |
| `token` | <p>GitHub token for private repository access</p> | `false` | `${{ github.token }}` |
| `token` | <p>GitHub token for private repository access</p> | `false` | `""` |
| `max-retries` | <p>Maximum number of retry attempts for Composer commands</p> | `false` | `3` |
### Outputs
@@ -84,7 +84,7 @@ This action is a `composite` action.
# GitHub token for private repository access
#
# Required: false
# Default: ${{ github.token }}
# Default: ""
max-retries:
# Maximum number of retry attempts for Composer commands

View File

@@ -42,7 +42,7 @@ inputs:
token:
description: 'GitHub token for private repository access'
required: false
default: ${{ github.token }}
default: ''
max-retries:
description: 'Maximum number of retry attempts for Composer commands'
required: false
@@ -68,10 +68,15 @@ runs:
- name: Mask Secrets
shell: bash
env:
GITHUB_TOKEN: ${{ inputs.token }}
GITHUB_TOKEN: ${{ inputs.token || github.token }}
run: |
echo "::add-mask::$GITHUB_TOKEN"
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Validate Inputs
id: validate
uses: ./validate-inputs
@@ -129,7 +134,7 @@ runs:
id: composer
shell: bash
env:
GITHUB_TOKEN: ${{ inputs.token }}
GITHUB_TOKEN: ${{ inputs.token || github.token }}
STABILITY: ${{ inputs.stability }}
COMPOSER_VERSION: ${{ inputs.composer-version }}
run: |

View File

@@ -80,6 +80,11 @@ runs:
echo "Input validation completed successfully"
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Set Git Config
uses: ./set-git-config
with:

View File

@@ -11,6 +11,7 @@ Detects the PHP version from the project's composer.json, phpunit.xml, or other
| name | description | required | default |
|-------------------|--------------------------------------------------------------|----------|---------|
| `default-version` | <p>Default PHP version to use if no version is detected.</p> | `false` | `8.2` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
@@ -32,4 +33,10 @@ This action is a `composite` action.
#
# Required: false
# Default: 8.2
token:
# GitHub token for authentication
#
# Required: false
# Default: ""
```

View File

@@ -15,6 +15,10 @@ inputs:
description: 'Default PHP version to use if no version is detected.'
required: false
default: '8.2'
token:
description: 'GitHub token for authentication'
required: false
default: ''
outputs:
php-version:
@@ -56,6 +60,11 @@ runs:
echo "Input validation completed successfully"
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Parse PHP Version
id: parse-version
uses: ./version-file-parser

View File

@@ -2,7 +2,7 @@
# Validation rules for php-version-detect action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
# Coverage: 100% (1/1 inputs)
# Coverage: 100% (2/2 inputs)
#
# This file defines validation rules for the php-version-detect GitHub Action.
# Rules are automatically applied by validate-inputs action when this
@@ -16,13 +16,15 @@ generator_version: 1.0.0
required_inputs: []
optional_inputs:
- default-version
- token
conventions:
default-version: semantic_version
token: github_token
overrides:
default-version: php_version
statistics:
total_inputs: 1
validated_inputs: 1
total_inputs: 2
validated_inputs: 2
skipped_inputs: 0
coverage_percentage: 100
validation_coverage: 100
@@ -30,7 +32,7 @@ auto_detected: true
manual_review_required: false
quality_indicators:
has_required_inputs: false
has_token_validation: false
has_token_validation: true
has_version_validation: true
has_file_validation: false
has_security_validation: false
has_security_validation: true

View File

@@ -10,7 +10,7 @@ Runs MegaLinter against pull requests
| name | description | required | default |
|------------|----------------------------------------|----------|-----------------------------|
| `token` | <p>GitHub token for authentication</p> | `false` | `${{ github.token }}` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
| `username` | <p>GitHub username for commits</p> | `false` | `github-actions` |
| `email` | <p>GitHub email for commits</p> | `false` | `github-actions@github.com` |
@@ -34,7 +34,7 @@ This action is a `composite` action.
# GitHub token for authentication
#
# Required: false
# Default: ${{ github.token }}
# Default: ""
username:
# GitHub username for commits

View File

@@ -17,7 +17,7 @@ inputs:
token:
description: 'GitHub token for authentication'
required: false
default: ${{ github.token }}
default: ''
username:
description: 'GitHub username for commits'
required: false
@@ -53,7 +53,7 @@ runs:
- name: Checkout Code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token }}
token: ${{ inputs.token || github.token }}
# If you use VALIDATE_ALL_CODEBASE = true, you can remove this line to
# improve performance

View File

@@ -12,7 +12,7 @@ Runs pre-commit on the repository and pushes the fixes back to the repository
|---------------------|----------------------------------------|----------|-----------------------------|
| `pre-commit-config` | <p>pre-commit configuration file</p> | `false` | `.pre-commit-config.yaml` |
| `base-branch` | <p>Base branch to compare against</p> | `false` | `""` |
| `token` | <p>GitHub token for authentication</p> | `false` | `${{ github.token }}` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
| `commit_user` | <p>Commit user</p> | `false` | `GitHub Actions` |
| `commit_email` | <p>Commit email</p> | `false` | `github-actions@github.com` |
@@ -48,7 +48,7 @@ This action is a `composite` action.
# GitHub token for authentication
#
# Required: false
# Default: ${{ github.token }}
# Default: ""
commit_user:
# Commit user

View File

@@ -21,7 +21,7 @@ inputs:
token:
description: 'GitHub token for authentication'
required: false
default: ${{ github.token }}
default: ''
commit_user:
description: 'Commit user'
required: false
@@ -42,6 +42,11 @@ outputs:
runs:
using: composite
steps:
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Validate Inputs
id: validate
uses: ./validate-inputs

View File

@@ -21,6 +21,7 @@ Run Prettier check on the repository with advanced configuration and reporting
| `max-retries` | <p>Maximum number of retry attempts</p> | `false` | `3` |
| `plugins` | <p>Comma-separated list of Prettier plugins to install</p> | `false` | `""` |
| `check-only` | <p>Only check for formatting issues without fixing</p> | `false` | `true` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
@@ -105,4 +106,10 @@ This action is a `composite` action.
#
# Required: false
# Default: true
token:
# GitHub token for authentication
#
# Required: false
# Default: ""
```

View File

@@ -56,6 +56,10 @@ inputs:
description: 'Only check for formatting issues without fixing'
required: false
default: 'true'
token:
description: 'GitHub token for authentication'
required: false
default: ''
outputs:
files-checked:
@@ -191,6 +195,11 @@ runs:
fi
fi
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Setup Node.js
id: node-setup
uses: ./node-setup
@@ -423,7 +432,7 @@ runs:
- name: Upload Prettier Results
if: always() && inputs.report-format == 'sarif'
uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
with:
sarif_file: ${{ inputs.working-directory }}/reports/prettier.sarif
category: prettier

View File

@@ -2,7 +2,7 @@
# Validation rules for prettier-check action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
# Coverage: 100% (11/11 inputs)
# Coverage: 100% (12/12 inputs)
#
# This file defines validation rules for the prettier-check GitHub Action.
# Rules are automatically applied by validate-inputs action when this
@@ -25,6 +25,7 @@ optional_inputs:
- plugins
- prettier-version
- report-format
- token
- working-directory
conventions:
cache: boolean
@@ -37,11 +38,12 @@ conventions:
plugins: plugin_list
prettier-version: semantic_version
report-format: report_format
token: github_token
working-directory: file_path
overrides: {}
statistics:
total_inputs: 11
validated_inputs: 11
total_inputs: 12
validated_inputs: 12
skipped_inputs: 0
coverage_percentage: 100
validation_coverage: 100
@@ -49,7 +51,7 @@ auto_detected: true
manual_review_required: false
quality_indicators:
has_required_inputs: false
has_token_validation: false
has_token_validation: true
has_version_validation: true
has_file_validation: true
has_security_validation: false
has_security_validation: true

View File

@@ -147,6 +147,12 @@ runs:
echo "::warning::GitHub token format may be invalid. Expected format: gh*_36characters"
fi
fi
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Detect Python Version
id: python-version
uses: ./python-version-detect
@@ -364,7 +370,7 @@ runs:
- name: Upload SARIF Report
if: steps.check-files.outputs.result == 'found'
uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
with:
sarif_file: ${{ inputs.working-directory }}/reports/flake8.sarif
category: 'python-lint'

View File

@@ -11,6 +11,7 @@ Detects Python version from project configuration files using enhanced detection
| name | description | required | default |
|-------------------|-----------------------------------------------------------------|----------|---------|
| `default-version` | <p>Default Python version to use if no version is detected.</p> | `false` | `3.12` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
@@ -33,4 +34,10 @@ This action is a `composite` action.
#
# Required: false
# Default: 3.12
token:
# GitHub token for authentication
#
# Required: false
# Default: ""
```

View File

@@ -15,6 +15,10 @@ inputs:
description: 'Default Python version to use if no version is detected.'
required: false
default: '3.12'
token:
description: 'GitHub token for authentication'
required: false
default: ''
outputs:
python-version:
@@ -57,6 +61,11 @@ runs:
echo "Input validation completed successfully"
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Parse Python Version
id: parse-version
uses: ./version-file-parser

View File

@@ -2,7 +2,7 @@
# Validation rules for python-version-detect-v2 action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
# Coverage: 100% (1/1 inputs)
# Coverage: 100% (2/2 inputs)
#
# This file defines validation rules for the python-version-detect-v2 GitHub Action.
# Rules are automatically applied by validate-inputs action when this
@@ -16,13 +16,15 @@ generator_version: 1.0.0
required_inputs: []
optional_inputs:
- default-version
- token
conventions:
default-version: semantic_version
token: github_token
overrides:
default-version: python_version
statistics:
total_inputs: 1
validated_inputs: 1
total_inputs: 2
validated_inputs: 2
skipped_inputs: 0
coverage_percentage: 100
validation_coverage: 100
@@ -30,7 +32,7 @@ auto_detected: true
manual_review_required: false
quality_indicators:
has_required_inputs: false
has_token_validation: false
has_token_validation: true
has_version_validation: true
has_file_validation: false
has_security_validation: false
has_security_validation: true

View File

@@ -11,6 +11,7 @@ Detects Python version from project configuration files or defaults to a specifi
| name | description | required | default |
|-------------------|-----------------------------------------------------------------|----------|---------|
| `default-version` | <p>Default Python version to use if no version is detected.</p> | `false` | `3.12` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
@@ -32,4 +33,10 @@ This action is a `composite` action.
#
# Required: false
# Default: 3.12
token:
# GitHub token for authentication
#
# Required: false
# Default: ""
```

View File

@@ -15,6 +15,10 @@ inputs:
description: 'Default Python version to use if no version is detected.'
required: false
default: '3.12'
token:
description: 'GitHub token for authentication'
required: false
default: ''
outputs:
python-version:
@@ -54,6 +58,11 @@ runs:
echo "Input validation completed successfully"
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Parse Python Version
id: parse-version
uses: ./version-file-parser

View File

@@ -2,7 +2,7 @@
# Validation rules for python-version-detect action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
# Coverage: 100% (1/1 inputs)
# Coverage: 100% (2/2 inputs)
#
# This file defines validation rules for the python-version-detect GitHub Action.
# Rules are automatically applied by validate-inputs action when this
@@ -16,13 +16,15 @@ generator_version: 1.0.0
required_inputs: []
optional_inputs:
- default-version
- token
conventions:
default-version: semantic_version
token: github_token
overrides:
default-version: python_version
statistics:
total_inputs: 1
validated_inputs: 1
total_inputs: 2
validated_inputs: 2
skipped_inputs: 0
coverage_percentage: 100
validation_coverage: 100
@@ -30,7 +32,7 @@ auto_detected: true
manual_review_required: false
quality_indicators:
has_required_inputs: false
has_token_validation: false
has_token_validation: true
has_version_validation: true
has_file_validation: false
has_security_validation: false
has_security_validation: true

View File

@@ -8,11 +8,11 @@ A GitHub Action to close stale issues and pull requests.
### Inputs
| name | description | required | default |
|---------------------|------------------------------------------------------------------------|----------|-----------------------|
| `token` | <p>GitHub token for authentication</p> | `false` | `${{ github.token }}` |
| `days-before-stale` | <p>Number of days of inactivity before an issue is marked as stale</p> | `false` | `30` |
| `days-before-close` | <p>Number of days of inactivity before a stale issue is closed</p> | `false` | `7` |
| name | description | required | default |
|---------------------|------------------------------------------------------------------------|----------|---------|
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
| `days-before-stale` | <p>Number of days of inactivity before an issue is marked as stale</p> | `false` | `30` |
| `days-before-close` | <p>Number of days of inactivity before a stale issue is closed</p> | `false` | `7` |
### Outputs
@@ -34,7 +34,7 @@ This action is a `composite` action.
# GitHub token for authentication
#
# Required: false
# Default: ${{ github.token }}
# Default: ""
days-before-stale:
# Number of days of inactivity before an issue is marked as stale

View File

@@ -15,7 +15,7 @@ inputs:
token:
description: 'GitHub token for authentication'
required: false
default: ${{ github.token }}
default: ''
days-before-stale:
description: 'Number of days of inactivity before an issue is marked as stale'
required: false
@@ -36,12 +36,17 @@ outputs:
runs:
using: composite
steps:
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Validate Inputs
id: validate
uses: ./validate-inputs
with:
action: 'stale'
token: ${{ inputs.token }}
token: ${{ inputs.token || github.token }}
days-before-stale: ${{ inputs.days-before-stale }}
days-before-close: ${{ inputs.days-before-close }}
@@ -49,7 +54,7 @@ runs:
id: stale
uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10.1.0
with:
repo-token: ${{ inputs.token }}
repo-token: ${{ inputs.token || github.token }}
days-before-stale: ${{ inputs.days-before-stale }}
days-before-close: ${{ inputs.days-before-close }}
remove-stale-when-updated: true

View File

@@ -18,7 +18,7 @@ Lints and fixes Terraform files with advanced validation and security checks.
| `auto-fix` | <p>Automatically fix issues when possible</p> | `false` | `true` |
| `max-retries` | <p>Maximum number of retry attempts</p> | `false` | `3` |
| `format` | <p>Output format (compact, json, checkstyle, junit, sarif)</p> | `false` | `sarif` |
| `token` | <p>GitHub token for authentication</p> | `false` | `${{ github.token }}` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
| `username` | <p>GitHub username for commits</p> | `false` | `github-actions` |
| `email` | <p>GitHub email for commits</p> | `false` | `github-actions@github.com` |
@@ -91,7 +91,7 @@ This action is a `composite` action.
# GitHub token for authentication
#
# Required: false
# Default: ${{ github.token }}
# Default: ""
username:
# GitHub username for commits

View File

@@ -47,7 +47,7 @@ inputs:
token:
description: 'GitHub token for authentication'
required: false
default: ${{ github.token }}
default: ''
username:
description: 'GitHub username for commits'
required: false
@@ -71,12 +71,17 @@ outputs:
runs:
using: composite
steps:
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ inputs.token || github.token }}
- name: Validate Inputs
id: validate
uses: ./validate-inputs
with:
action-type: 'terraform-lint-fix'
token: ${{ inputs.token }}
token: ${{ inputs.token || github.token }}
email: ${{ inputs.email }}
username: ${{ inputs.username }}
terraform-version: ${{ inputs.terraform-version }}
@@ -267,7 +272,7 @@ runs:
if: ${{ fromJSON(steps.fix.outputs.fixed_count) > 0 }}
uses: ./set-git-config
with:
token: ${{ inputs.token }}
token: ${{ inputs.token || github.token }}
username: ${{ inputs.username }}
email: ${{ inputs.email }}
@@ -297,7 +302,7 @@ runs:
- name: Upload SARIF Report
if: steps.check-files.outputs.found == 'true' && inputs.format == 'sarif'
uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
with:
sarif_file: ${{ env.VALIDATED_WORKING_DIR }}/reports/tflint.sarif
category: terraform-lint

View File

@@ -4,9 +4,9 @@
from __future__ import annotations
from pathlib import Path
import re
import sys
from pathlib import Path
# Add validate-inputs directory to path to import validators
validate_inputs_path = Path(__file__).parent

View File

@@ -200,10 +200,10 @@ class CustomValidator(BaseValidator):
return False
return True
def get_validation_rules(self) -> dict:
"""Get validation rules."""
rules_path = Path(__file__).parent / "rules.yml"
return self.load_rules(rules_path)
def get_validation_rules(self) -> dict:
"""Get validation rules."""
rules_path = Path(__file__).parent / "rules.yml"
return self.load_rules(rules_path)
```
1. **Test your validator** (optional but recommended):

View File

@@ -5,7 +5,7 @@ A comprehensive, modular validation system for GitHub Actions inputs with automa
## Features
- 🔍 **Automatic Validation** - Convention-based input detection
- 🧩 **Modular Architecture** - 11+ specialized validators
- 🧩 **Modular Architecture** - 9 specialized validators
- 🛡️ **Security First** - Injection and traversal protection
- 🎯 **Custom Validators** - Action-specific validation logic
- 🧪 **Test Generation** - Automatic test scaffolding
@@ -332,8 +332,8 @@ class CustomValidator(BaseValidator):
## Quality Metrics
- **Test Coverage**: 100% (303 tests)
- **Validators**: 11 core + unlimited custom
- **Test Coverage**: 100% (769 tests)
- **Validators**: 9 specialized + unlimited custom
- **Performance**: < 10ms typical validation time
- **Zero Dependencies**: Uses only Python stdlib + PyYAML
- **Production Ready**: Zero defects policy

View File

@@ -9,8 +9,8 @@ from __future__ import annotations
import logging
import os
from pathlib import Path
import sys
from pathlib import Path
# Add validators module to path
sys.path.insert(0, str(Path(__file__).parent))

View File

@@ -0,0 +1,131 @@
[project]
name = "github-actions-validate-inputs"
version = "1.0.0"
description = "Modular input validation system for GitHub Actions with automatic convention-based detection"
readme = "README.md"
requires-python = ">=3.8"
authors = [
{name = "Ismo Vuorinen", email = "ismo@ivuorinen.net"}
]
license = {text = "MIT"}
keywords = [
"github-actions",
"validation",
"input-validation",
"security",
"ci-cd"
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Software Development :: Quality Assurance",
"Topic :: Software Development :: Testing",
]
dependencies = [
"pyyaml>=6.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"pytest-cov>=4.0.0",
"ruff>=0.1.0",
]
[project.urls]
Homepage = "https://github.com/ivuorinen/actions"
Repository = "https://github.com/ivuorinen/actions.git"
Issues = "https://github.com/ivuorinen/actions/issues"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["validators", "tests"]
[tool.pytest.ini_options]
minversion = "7.0"
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"-ra",
"--strict-markers",
"--strict-config",
"--showlocals",
]
markers = [
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
"integration: marks tests as integration tests",
]
[tool.coverage.run]
source = ["validators"]
omit = [
"*/tests/*",
"*/test_*.py",
"*/__pycache__/*",
]
[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
"if TYPE_CHECKING:",
"@abstractmethod",
]
show_missing = true
precision = 2
[tool.ruff]
target-version = "py38"
line-length = 100
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"UP", # pyupgrade
"ARG", # flake8-unused-arguments
"SIM", # flake8-simplify
]
ignore = [
"E402", # module level import not at top of file (intentional for sys.path manipulation)
"E501", # line too long (handled by formatter)
"B008", # do not perform function calls in argument defaults
"W191", # indentation contains tabs
]
[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = [
"ARG", # Unused function arguments
"S101", # Use of assert
"SIM117", # Nested with statements (stylistic preference in tests)
]
[tool.ruff.lint.isort]
known-first-party = ["validators"]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "lf"

View File

@@ -8,10 +8,10 @@ from __future__ import annotations
import argparse
import json
from pathlib import Path
import statistics
import sys
import time
from pathlib import Path
from typing import Any
# Add parent directory to path for imports
@@ -171,8 +171,8 @@ class ValidatorBenchmark:
inputs: Dictionary of inputs to validate
"""
import cProfile
from io import StringIO
import pstats
from io import StringIO
print(f"\nProfiling {action_type} validator...")
print("-" * 70)

View File

@@ -13,8 +13,8 @@ from __future__ import annotations
import argparse
import json
import logging
from pathlib import Path
import sys
from pathlib import Path
from typing import TYPE_CHECKING
# Add parent directory to path for imports

View File

@@ -10,9 +10,9 @@ from __future__ import annotations
import argparse
import logging
from pathlib import Path
import re
import sys
from pathlib import Path
import yaml # pylint: disable=import-error

View File

@@ -12,9 +12,9 @@ Usage:
from __future__ import annotations
import argparse
from pathlib import Path
import re
import sys
from pathlib import Path
from typing import Any
import yaml # pylint: disable=import-error

View File

@@ -2,9 +2,9 @@
from __future__ import annotations
from pathlib import Path
import sys
import unittest
from pathlib import Path
from unittest.mock import patch
# Add parent directory to path

View File

@@ -1,16 +1,15 @@
"""Tests for the BooleanValidator module."""
from pathlib import Path
import sys
from pathlib import Path
import pytest # pylint: disable=import-error
# Add the parent directory to the path
sys.path.insert(0, str(Path(__file__).parent.parent))
from validators.boolean import BooleanValidator
from tests.fixtures.version_test_data import BOOLEAN_INVALID, BOOLEAN_VALID
from validators.boolean import BooleanValidator
class TestBooleanValidator:

View File

@@ -4,8 +4,8 @@ Generated by generate-tests.py - Do not edit manually.
"""
# pylint: disable=invalid-name # Test file name matches action name
from pathlib import Path
import sys
from pathlib import Path
# Add action directory to path to import custom validator
action_path = Path(__file__).parent.parent.parent / "codeql-analysis"

Some files were not shown because too many files have changed in this diff Show More