agentsclimarketplace

Managing azure sql migrations

Skill alexpizarro/azure-lean-stack-skills/skills/managing-azure-sql-migrations

Manages versioned, idempotent Azure SQL migrations that run on every deployment via sqlcmd in GitHub Actions. Provides the migration-history tracking table, the guard-clause template every migration uses, and the workflow step that installs sqlcmd on ubuntu-24.04, manages the SQL firewall with trap cleanup, and runs all files in alphabetical order. Use when adding a new SQL migration, setting up the migration system on a new project, or fixing CI failures like "sqlcmd not found", "gpg cannot open /dev/tty", or "Multiple files found matching pattern *.sql".From its SKILL.md

Install
npx -y skills add alexpizarro/azure-lean-stack-skills --skill managing-azure-sql-migrations

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

4 things to look at

  • reads credentialsReads from 1 credential source: `SQL_ADMIN_PASSWORD_*`.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
  • runs commandsInstructs the agent to run 3 commands, including `for f in $(ls infra/sql/migrations/*.sql | sort); do echo "Running: $f" sqlcmd -S localhost -d MyDb -E -i "$f" done` and 2 more.
  • fetches URLsInstructs the agent to fetch 1 URL, including https://api.ipify.org.

SKILL.md

4.9 KB, ~1.1k tokens by cl100k_base, as published. Nobody here has run it

Managing Azure SQL Migrations

Idempotent, roll-forward SQL migrations run on every deploy via sqlcmd. The migration system uses a __MigrationHistory table for tracking, guard-clause migrations to make every run safe, and a workflow step that handles the operational quirks of running sqlcmd on ubuntu-24.04 in GitHub Actions.

When to invoke

  • Adding a new migration file
  • Bootstrapping the migration system on a new project
  • Fixing a CI failure related to SQL migrations

File naming

infra/sql/migrations/
├── 000_migration_history.sql       # tracking table — always runs first
├── 001_create_items_table.sql      # initial schema (pre-tracking guard ok)
├── 002_add_user_id_to_items.sql    # guarded by __MigrationHistory
├── 003_seed_demo_data.sql          # also guarded
└── ...

Pattern: {NNN}_{snake_case_description}.sql. Zero-padded, alphabetical order = execution order.

Guard clause template

Every migration from 002 onward MUST use this pattern:

IF NOT EXISTS (
    SELECT 1 FROM dbo.__MigrationHistory WHERE MigrationId = 'NNN_describe_change'
)
BEGIN
    -- DDL here (CREATE TABLE, ALTER TABLE, INSERT, MERGE, etc.)

    INSERT INTO dbo.__MigrationHistory (MigrationId) VALUES ('NNN_describe_change');
    PRINT 'Migration NNN_describe_change applied.';
END
ELSE
BEGIN
    PRINT 'Migration NNN_describe_change already applied — skipping.';
END

The exception is 001_create_items_table.sql, which uses IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Items') because Items may have been deployed before tracking existed.

The tracking table

000_migration_history.sql creates __MigrationHistory. Idempotent — safe to re-run:

IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = '__MigrationHistory')
BEGIN
    CREATE TABLE dbo.__MigrationHistory (
        MigrationId NVARCHAR(200) NOT NULL PRIMARY KEY,
        AppliedAt   DATETIME2     NOT NULL DEFAULT GETUTCDATE()
    );
END

See templates/000_migration_history.sql and templates/001_create_items_table.sql.

Rules

  1. File naming: {NNN}_{description}.sql — zero-padded, snake_case.
  2. Never edit an applied migration — add a new one instead.
  3. Seed data must be idempotent — IF NOT EXISTS or MERGE.
  4. No rollback scripts — roll forward only. Point-in-time restore is available (7-day retention on serverless).
  5. 000 always runs first — creates the tracking table.

Why not azure/sql-action

The GitHub action azure/[email protected] accepts only one file. Multi-file pushes fail with Multiple files found matching pattern *.sql. Use the sqlcmd bash step in scripts/run-migrations.sh instead.

The workflow step

The deploy workflows call scripts/install-sqlcmd.sh and scripts/run-migrations.sh. Both encode hard-won fixes:

FixWhy
gpg --batch --yes --dearmorWithout --batch, gpg tries to open /dev/tty and fails in headless CI
Pipe through sudo teeDon't use sudo gpg -o /path — permission issues
Install mssql-tools18 explicitlyNot pre-installed on ubuntu-24.04 (which ubuntu-latest now points to)
sqlcmd -C flagRequired with mssql-tools18 to trust Azure SQL TLS certificate
trap ... EXIT for firewall cleanupGuarantees the runner's temporary firewall rule is removed even if a migration fails

Local development

To run migrations against a local SQL Server or LocalDB:

for f in $(ls infra/sql/migrations/*.sql | sort); do
  echo "Running: $f"
  sqlcmd -S localhost -d MyDb -E -i "$f"     # -E uses integrated auth
done

For Azure SQL from your dev box, add your IP to the firewall first:

MY_IP=$(curl -s https://api.ipify.org)
az sql server firewall-rule create --server "$SQL_SERVER_NAME" --resource-group "$RG" \
  --name "dev-$(whoami)" --start-ip-address "$MY_IP" --end-ip-address "$MY_IP"

Composes with

What ships with it: 4 files

4.7 KB alongside SKILL.md, 2 of them executable

scripts/

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.