diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 882cdb0c1..46c0ca6a5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -90,3 +90,22 @@ jobs: uses: docker/build-push-action@v3 with: context: . + + main-alteration-sequence: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 2 + + - name: Setup Node and pnpm + uses: silverhand-io/actions-node-pnpm-run-steps@v2 + with: + node-version: 18 + + - name: Build + run: pnpm prepack + + - name: Check alteration sequence + run: node .scripts/check-alterations-sequence.js diff --git a/.scripts/check-alterations-sequence.js b/.scripts/check-alterations-sequence.js new file mode 100644 index 000000000..e9e19a684 --- /dev/null +++ b/.scripts/check-alterations-sequence.js @@ -0,0 +1,36 @@ +/** + * This script runs a task to check alteration files seqence: + * new files should come last + * + */ + +const { execSync } = require("child_process"); + +const alterationFilePrefix = "packages/schemas/alterations/"; + +const allAlterations = execSync("pnpm cli db alter list", { + encoding: "utf-8", +}) + .split("\n") + .filter((filename) => Boolean(filename)) + .map((filename) => filename.replace(".js", "")); + +const diffFiles = execSync("git diff --name-only HEAD HEAD~1", { + encoding: "utf-8", +}); +const committedAlterations = diffFiles + .split("\n") + .filter((filename) => filename.startsWith(alterationFilePrefix)) + .map((filename) => + filename.replace(alterationFilePrefix, "").replace(".ts", "") + ); + +for (const alteration of committedAlterations) { + const index = allAlterations.indexOf(alteration); + + if (index < allAlterations.length - committedAlterations.length) { + throw new Error( + `Wrong alteration sequence for commited file: ${alteration}\nAll timestamps of committed alteration files should be greater than the biggest one in the base branch.` + ); + } +} diff --git a/packages/cli/src/commands/database/alteration/index.ts b/packages/cli/src/commands/database/alteration/index.ts index 17a93a3b1..fbc5ed0c0 100644 --- a/packages/cli/src/commands/database/alteration/index.ts +++ b/packages/cli/src/commands/database/alteration/index.ts @@ -72,7 +72,7 @@ const alteration: CommandModule = builder: (yargs) => yargs .positional('action', { - describe: 'The action to perform, now it only accepts `deploy`', + describe: 'The action to perform, now it only accepts `deploy` and `list`', type: 'string', demandOption: true, }) @@ -81,29 +81,35 @@ const alteration: CommandModule = type: 'string', }), handler: async ({ action, target }) => { - if (action !== 'deploy') { + if (action === 'list') { + const files = await getAlterationFiles(); + + for (const file of files) { + console.log(file.filename); + } + } else if (action === 'deploy') { + const pool = await createPoolFromConfig(); + const alterations = await chooseAlterationsByVersion( + await getUndeployedAlterations(pool), + target + ); + + log.info( + `Found ${alterations.length} alteration${conditionalString( + alterations.length > 1 && 's' + )} to deploy` + ); + + // The await inside the loop is intended, alterations should run in order + for (const alteration of alterations) { + // eslint-disable-next-line no-await-in-loop + await deployAlteration(pool, alteration); + } + + await pool.end(); + } else { log.error('Unsupported action'); } - - const pool = await createPoolFromConfig(); - const alterations = await chooseAlterationsByVersion( - await getUndeployedAlterations(pool), - target - ); - - log.info( - `Found ${alterations.length} alteration${conditionalString( - alterations.length > 1 && 's' - )} to deploy` - ); - - // The await inside the loop is intended, alterations should run in order - for (const alteration of alterations) { - // eslint-disable-next-line no-await-in-loop - await deployAlteration(pool, alteration); - } - - await pool.end(); }, };