diff --git a/.github/workflows/check_db_migration_confict.yml b/.github/workflows/check_db_migration_confict.yml new file mode 100644 index 000000000..756ab87d4 --- /dev/null +++ b/.github/workflows/check_db_migration_confict.yml @@ -0,0 +1,59 @@ +name: Check DB migration conflict +on: + push: + paths: + - "superset/migrations/**" + +jobs: + check_db_migration_conflict: + name: Check DB migration conflict + runs-on: ubuntu-20.04 + steps: + - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" + uses: actions/checkout@v2 + - name: Check and notify + uses: actions/github-script@v3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + // API reference: https://octokit.github.io/rest.js + const currentBranch = context.ref.replace('refs/heads/', ''); + + // Find all pull requests to current branch + const opts = github.pulls.list.endpoint.merge({ + owner: context.repo.owner, + repo: context.repo.repo, + base: context.ref, + state: 'open', + sort: 'updated', + per_page: 100, + }); + const pulls = await github.paginate(opts); + if (pulls.length > 0) { + console.log(`Found ${pulls.length} open PRs for base branch "${currentBranch}"`) + } + + for (const pull of pulls) { + const listFilesOpts = await github.pulls.listFiles.endpoint.merge({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pull.number, + }); + const files = await github.paginate(listFilesOpts); + if ( + files.some(x => x.contents_url.includes('/contents/superset/migrations')) + ) { + console.log(`PR #${pull.number} "${pull.title}" also added db migration`) + await github.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pull.number, + body: + `⚠️ @${pull.user.login} Your base branch \`${currentBranch}\` has just ` + + 'also updated `superset/migrations`.\n' + + '\n' + + '❗ **Please consider rebasing your branch to avoid db migration conflicts.**', + }); + } + } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b6c517706..8231755e4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1026,7 +1026,7 @@ Submissions will be considered for submission (or removal) on a case-by-case bas When two DB migrations collide, you'll get an error message like this one: -``` +```text alembic.util.exc.CommandError: Multiple head revisions are present for given argument 'head'; please specify a specific target revision, '@head' to narrow to a specific head, @@ -1041,15 +1041,46 @@ To fix it: superset db heads ``` - This should list two or more migration hashes. + This should list two or more migration hashes. E.g. -1. Create a new merge migration + ```bash + 1412ec1e5a7b (head) + 67da9ef1ef9c (head) + ``` + +2. Pick one of them as the parent revision, open the script for the other revision + and update `Revises` and `down_revision` to the new parent revision. E.g.: + + ```diff + --- a/67da9ef1ef9c_add_hide_left_bar_to_tabstate.py + +++ b/67da9ef1ef9c_add_hide_left_bar_to_tabstate.py + @@ -17,14 +17,14 @@ + """add hide_left_bar to tabstate + + Revision ID: 67da9ef1ef9c + -Revises: c501b7c653a3 + +Revises: 1412ec1e5a7b + Create Date: 2021-02-22 11:22:10.156942 + + """ + + # revision identifiers, used by Alembic. + revision = "67da9ef1ef9c" + -down_revision = "c501b7c653a3" + +down_revision = "1412ec1e5a7b" + + import sqlalchemy as sa + from alembic import op + ``` + + Alternatively you may also run `superset db merge` to create a migration script + just for merging the heads. ```bash superset db merge {HASH1} {HASH2} ``` -1. Upgrade the DB to the new checkpoint +3. Upgrade the DB to the new checkpoint ```bash superset db upgrade