diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 851e04c8e..96d259425 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -159,6 +159,20 @@ jobs: done - run: ./.github/workflows/validate-translations.sh -v + migrations-lint: + name: Validate migrations + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Fetch master branch + run: git fetch origin master + + - name: Validate migration timestamps + run: ./.github/workflows/validate-migrations.sh check-push-enabled: name: Check Docker configuration @@ -172,7 +186,8 @@ jobs: build: name: Build - needs: [js, go, go-lint, i18n-lint, git-version, check-push-enabled] + needs: [js, go, go-lint, i18n-lint, migrations-lint, git-version, check-push-enabled] + if: ${{ !failure() && !cancelled() }} strategy: matrix: platform: [ linux/amd64, linux/arm64, linux/arm/v5, linux/arm/v6, linux/arm/v7, linux/386, darwin/amd64, darwin/arm64, windows/amd64, windows/386 ] diff --git a/.github/workflows/validate-migrations.sh b/.github/workflows/validate-migrations.sh new file mode 100755 index 000000000..cea7cc469 --- /dev/null +++ b/.github/workflows/validate-migrations.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# Validates that new migrations in a PR have timestamps greater than +# the latest migration timestamp on the master branch. +# +# This prevents migration ordering conflicts when multiple PRs add migrations. + +set -e + +# Get the latest migration timestamp from master branch +# Filter for files matching the pattern: 14-digit timestamp followed by _ and ending in .sql or .go +MASTER_MIGRATIONS=$(git ls-tree --name-only origin/master -- db/migrations/ | grep -E '^db/migrations/[0-9]{14}_.*\.(sql|go)$' || true) + +if [ -z "$MASTER_MIGRATIONS" ]; then + echo "No migrations found on master branch" + exit 0 +fi + +MASTER_LATEST=$(echo "$MASTER_MIGRATIONS" | sed 's|db/migrations/||' | cut -c1-14 | sort -n | tail -1) + +# Get migrations added/modified in this PR compared to master +CHANGED_MIGRATIONS=$(git diff --name-only origin/master -- db/migrations/ | grep -E '^db/migrations/[0-9]{14}_.*\.(sql|go)$' || true) + +if [ -z "$CHANGED_MIGRATIONS" ]; then + echo "No new migrations found in this PR" + exit 0 +fi + +echo "Latest migration on master: $MASTER_LATEST" +echo "New/modified migrations in this PR:" + +HAS_ERRORS=false +for migration in $CHANGED_MIGRATIONS; do + TIMESTAMP=$(basename "$migration" | cut -c1-14) + echo " - $migration (timestamp: $TIMESTAMP)" + + if [ "$TIMESTAMP" -le "$MASTER_LATEST" ]; then + echo "::error file=$migration::Migration timestamp $TIMESTAMP must be greater than latest master timestamp $MASTER_LATEST" + HAS_ERRORS=true + fi +done + +if [ "$HAS_ERRORS" = "true" ]; then + echo "" + echo "ERROR: One or more migrations have timestamps that are not after the latest migration on master." + echo "Please regenerate the migration with a newer timestamp using:" + echo " make migration-sql name=your_migration_name" + echo " make migration-go name=your_migration_name" + exit 1 +fi + +echo "All migration timestamps are valid!"