name: Release Dry Run on: push: branches: - main - master workflow_dispatch: jobs: release-dry-run: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Inspect release metadata shell: bash run: | missing=0 required_docs=( "README.md" "CHANGELOG.md" "SECURITY.md" "docs/release-checklist.md" ) for file in "${required_docs[@]}"; do if [ ! -f "$file" ]; then echo "Missing release document: $file" missing=1 fi done placeholder_paths=(README.md AGENTS.md .codex docs .gitea) placeholder_pattern='PROJECT_NAME|PROJECT_DESCRIPTION|REPOSITORY_OWNER|REPOSITORY_NAME|PACKAGE_NAME|ARTIFACT_NAME|ARTIFACT_OUTPUT_DIRECTORY|DOWNLOAD_URL|CI_URL|RELEASES_URL|BUILD_COMMAND|TEST_COMMAND|LINT_COMMAND|AUDIT_COMMAND|COMMIT_OR_VERSION' for path in "${placeholder_paths[@]}"; do [ -e "$path" ] || continue if grep -RInE --exclude-dir=.git --exclude=release-dry-run.yml --exclude=template-compliance.yml "$placeholder_pattern" "$path"; then echo "Unresolved template placeholders found." missing=1 fi done if [ "$missing" -eq 1 ]; then exit 1 fi - name: Detect project stack id: detect shell: bash run: | stacks="" [ -f package.json ] && stacks="${stacks} node" { [ -f pyproject.toml ] || [ -f requirements.txt ]; } && stacks="${stacks} python" [ -f Cargo.toml ] && stacks="${stacks} rust" [ -f go.mod ] && stacks="${stacks} go" echo "stacks=${stacks:-generic}" >> "$GITHUB_OUTPUT" echo "Detected stacks:${stacks:- generic}" - name: Node release checks if: contains(steps.detect.outputs.stacks, 'node') shell: bash run: | if [ -f package-lock.json ] || [ -f npm-shrinkwrap.json ]; then npm ci else npm install fi node -e "const p=require('./package.json'); if(!p.name||!p.version){throw new Error('package.json needs name and version')}; console.log(p.name+'@'+p.version)" npm run lint --if-present npm test --if-present npm run build --if-present npm run release:check --if-present - name: Python release checks if: contains(steps.detect.outputs.stacks, 'python') shell: bash run: | python -m pip install --upgrade pip if [ -f requirements.txt ]; then python -m pip install -r requirements.txt fi if [ -f pyproject.toml ]; then python -m pip install build python -m build else echo "No pyproject.toml found; skipped Python package build." fi - name: Rust release checks if: contains(steps.detect.outputs.stacks, 'rust') shell: bash run: | cargo test cargo build --release - name: Go release checks if: contains(steps.detect.outputs.stacks, 'go') shell: bash run: | go test ./... go build ./... - name: Artifact report shell: bash run: | echo "Potential release artifacts:" find . \ -path ./.git -prune -o \ -path ./node_modules -prune -o \ -path './dist/*' -type f -print -o \ -path './build/*' -type f -print -o \ -path './release/*' -type f -print -o \ -path './target/release/*' -type f -print \ | sed 's#^\./##' \ | head -200 cat <<'EOF' Release dry run completed. This workflow verifies release readiness. It does not create tags, releases, packages, or upload artifacts. EOF