Implement global ignores #2
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Validate Versioning and Changelog | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened] | |
| branches: | |
| - main | |
| jobs: | |
| validate: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v5 | |
| with: | |
| version: "10" | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v5 | |
| with: | |
| node-version: "22" | |
| cache: "pnpm" | |
| - name: Install semver package | |
| run: pnpm add semver | |
| - name: Check for changes in package | |
| id: check-changes | |
| run: | | |
| # Get actual list of packages | |
| PACKAGES=$(find packages -maxdepth 1 -mindepth 1 -type d -printf "%f\n") | |
| echo "All packages found: $PACKAGES" | |
| # Check for changes in package files (excluding dist, node_modules) | |
| CHANGED_PACKAGES="" | |
| for pkg in $PACKAGES; do | |
| CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD -- packages/$pkg | grep -v -E "dist|node_modules" || true) | |
| if [ -n "$CHANGED" ]; then | |
| CHANGED_PACKAGES="$CHANGED_PACKAGES $pkg" | |
| fi | |
| done | |
| if [ -z "$CHANGED_PACKAGES" ]; then | |
| echo "No packages changed" | |
| echo "has_changes=false" >> $GITHUB_OUTPUT | |
| echo "No relevant package files modified (excluding dist, node_modules)" | |
| else | |
| echo "Changed packages: $CHANGED_PACKAGES" | |
| echo "has_changes=true" >> $GITHUB_OUTPUT | |
| echo "changed_packages=$CHANGED_PACKAGES" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Skip if no packages changed | |
| if: steps.check-changes.outputs.has_changes == 'false' | |
| run: | | |
| echo "No package changes detected. Skipping version and changelog validation." | |
| exit 0 | |
| - name: Validate versioning and changelog | |
| if: steps.check-changes.outputs.has_changes == 'true' | |
| run: | | |
| set -e | |
| # Validate each changed package | |
| for PACKAGE in ${{ steps.check-changes.outputs.changed_packages }}; do | |
| PACKAGE_DIR="packages/$PACKAGE" | |
| echo "::group::Version Validation" | |
| echo "Starting validation for package: $PACKAGE_DIR" | |
| # Get current version from package.json | |
| CURRENT_VERSION=$(node -e "console.log(require('./$PACKAGE_DIR/package.json').version)") | |
| echo "Current version in package.json: $CURRENT_VERSION" | |
| # Get base version from base branch | |
| git fetch origin ${{ github.base_ref }} --depth=1 || true | |
| BASE_VERSION=$(git show origin/${{ github.base_ref }}:$PACKAGE_DIR/package.json 2>/dev/null | node -e "const fs=require('fs'); const data=fs.readFileSync(0,'utf-8'); console.log(JSON.parse(data).version)" || echo "0.0.0") | |
| echo "Base version in package.json: $BASE_VERSION" | |
| # Validate version format and check if version was increased (semantic versioning) | |
| echo "Validating version format and increment..." | |
| set +e | |
| VERSION_CHECK=$(node -e " | |
| const semver = require('semver'); | |
| const current = '$CURRENT_VERSION'; | |
| const base = '$BASE_VERSION'; | |
| // Validate current version format | |
| if (!semver.valid(current)) { console.error('INVALID_CURRENT'); process.exit(1); } | |
| // Validate base version format (if not 0.0.0) | |
| if (base !== '0.0.0' && !semver.valid(base)) { console.error('INVALID_BASE'); process.exit(1); } | |
| // Check if versions are the same | |
| if (current === base) { console.error('SAME_VERSION'); process.exit(1); } | |
| // Check if current version is greater than base version | |
| if (!semver.gt(current, base)) { console.error('VERSION_NOT_INCREASED'); process.exit(1); } | |
| // Calculate suggested versions | |
| const patch = semver.inc(base, 'patch'); | |
| const minor = semver.inc(base, 'minor'); | |
| const major = semver.inc(base, 'major'); | |
| console.log('OK'); | |
| console.log('PATCH=' + patch); | |
| console.log('MINOR=' + minor); | |
| console.log('MAJOR=' + major); | |
| " 2>&1) | |
| VERSION_CHECK_EXIT=$? | |
| set -e | |
| echo "Full version check output:" | |
| echo "$VERSION_CHECK" | |
| VERSION_CHECK_OUTPUT=$(echo "$VERSION_CHECK" | head -1 | tr -d '\r\n') | |
| echo "First line of output: '$VERSION_CHECK_OUTPUT'" | |
| echo "Exit code: $VERSION_CHECK_EXIT" | |
| if [ $VERSION_CHECK_EXIT -ne 0 ]; then | |
| echo "::error file=$PACKAGE_DIR/package.json::Version validation failed" | |
| if echo "$VERSION_CHECK" | grep -q "INVALID_CURRENT"; then | |
| echo "::error::Current version '$CURRENT_VERSION' is not a valid semantic version!" | |
| echo "Please use semantic versioning format (e.g., 1.0.0, 1.0.1, 1.1.0, 2.0.0)" | |
| exit 1 | |
| elif echo "$VERSION_CHECK" | grep -q "INVALID_BASE"; then | |
| echo "⚠️ WARNING: Base version '$BASE_VERSION' is not a valid semantic version" | |
| echo "Assuming version bump is valid (first release or manual version)" | |
| elif echo "$VERSION_CHECK" | grep -q "SAME_VERSION"; then | |
| echo "::error file=$PACKAGE_DIR/package.json::Version was not bumped!" | |
| echo "Current version: $CURRENT_VERSION" | |
| echo "Base version: $BASE_VERSION" | |
| echo "Please bump the version in package.json" | |
| exit 1 | |
| elif echo "$VERSION_CHECK" | grep -q "VERSION_NOT_INCREASED"; then | |
| PATCH_VER=$(echo "$VERSION_CHECK" | grep "PATCH=" | cut -d= -f2) | |
| MINOR_VER=$(echo "$VERSION_CHECK" | grep "MINOR=" | cut -d= -f2) | |
| MAJOR_VER=$(echo "$VERSION_CHECK" | grep "MAJOR=" | cut -d= -f2) | |
| echo "::error file=$PACKAGE_DIR/package.json::Version must be greater than base version!" | |
| echo "Current version: $CURRENT_VERSION" | |
| echo "Base version: $BASE_VERSION" | |
| echo "The new version must be higher according to semantic versioning rules." | |
| echo "Suggested versions:" | |
| echo " - Patch: $BASE_VERSION -> $PATCH_VER" | |
| echo " - Minor: $BASE_VERSION -> $MINOR_VER" | |
| echo " - Major: $BASE_VERSION -> $MAJOR_VER" | |
| exit 1 | |
| else | |
| echo "::error::Unknown version validation error" | |
| echo "Exit code: $VERSION_CHECK_EXIT" | |
| echo "Full output was:" | |
| echo "$VERSION_CHECK" | |
| exit 1 | |
| fi | |
| else | |
| echo "✅ Version was bumped from $BASE_VERSION to $CURRENT_VERSION (valid semver increment)" | |
| fi | |
| echo "::endgroup::" | |
| echo "::group::Changelog Validation" | |
| # Check if changelog has entry for this version | |
| CHANGELOG_FILE="$PACKAGE_DIR/CHANGELOG.md" | |
| echo "Checking changelog file: $CHANGELOG_FILE" | |
| echo "Looking for version: $CURRENT_VERSION" | |
| if ! grep -q "^## \\[$CURRENT_VERSION\\]" "$CHANGELOG_FILE"; then | |
| echo "::error file=$CHANGELOG_FILE::Changelog entry for version $CURRENT_VERSION not found!" | |
| echo "Please add a changelog entry in $CHANGELOG_FILE with the format:" | |
| echo "## [$CURRENT_VERSION] - YYYY-MM-DD" | |
| exit 1 | |
| fi | |
| echo "✅ Changelog entry found for version $CURRENT_VERSION" | |
| # Verify changelog entry is not empty (has content after the version header) | |
| CHANGELOG_LINE=$(grep -n "^## \\[$CURRENT_VERSION\\]" "$CHANGELOG_FILE" | cut -d: -f1) | |
| echo "Changelog entry found at line: $CHANGELOG_LINE" | |
| # Check if there's content after the version header (skip empty entries) | |
| NEXT_VERSION_LINE=$(tail -n +$((CHANGELOG_LINE + 1)) "$CHANGELOG_FILE" | grep -n "^## \\[" | head -1 | cut -d: -f1) | |
| if [ -z "$NEXT_VERSION_LINE" ]; then | |
| # This is the latest version, check if there's any content after the header | |
| LINES_AFTER_HEADER=$(tail -n +$((CHANGELOG_LINE + 1)) "$CHANGELOG_FILE" | grep -v '^$' | head -1) | |
| if [ -z "$LINES_AFTER_HEADER" ]; then | |
| echo "::error file=$CHANGELOG_FILE::Changelog entry for version $CURRENT_VERSION is empty!" | |
| echo "Please add at least one change entry (Added, Changed, Fixed, etc.)" | |
| exit 1 | |
| fi | |
| else | |
| # Check if there's content between this version and the next | |
| LINES_BETWEEN=$(sed -n "$((CHANGELOG_LINE + 1)),$((CHANGELOG_LINE + NEXT_VERSION_LINE - 1))p" "$CHANGELOG_FILE" | grep -v '^$' | head -1) | |
| if [ -z "$LINES_BETWEEN" ]; then | |
| echo "::error file=$CHANGELOG_FILE::Changelog entry for version $CURRENT_VERSION is empty!" | |
| echo "Please add at least one change entry (Added, Changed, Fixed, etc.)" | |
| exit 1 | |
| fi | |
| fi | |
| echo "✅ Changelog entry for version $CURRENT_VERSION has content" | |
| echo "::endgroup::" | |
| echo "::notice::All validations passed successfully for package $PACKAGE!" | |
| done |