name: sql-forge CI
on:
pull_request:
paths-ignore:
- 'README.md'
- '.gitignore'
push:
branches: [main]
tags: ['v*']
paths-ignore:
- 'README.md'
- '.gitignore'
env:
CARGO_TERM_COLOR: always
SQLX_OFFLINE: "false"
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
db-type: [mysql, postgres, sqlite]
services:
mysql:
image: ${{ matrix.db-type == 'mysql' && 'mysql:8.0.45' || '' }}
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: sql_forge_test
ports:
- 3306:3306
postgres:
image: ${{ matrix.db-type == 'postgres' && 'postgres:18.4' || '' }}
env:
POSTGRES_PASSWORD: root
POSTGRES_DB: sql_forge_test
ports:
- 5432:5432
env:
ENV_DB_TYPE: ${{ matrix.db-type }}
DATABASE_URL: ${{ matrix.db-type == 'mysql' && 'mysql://root:root@127.0.0.1:3306/sql_forge_test' || matrix.db-type == 'postgres' && 'postgres://postgres:root@127.0.0.1:5432/sql_forge_test' || format('sqlite:{0}/sql_forge_test.db', github.workspace) }}
SQL_FORGE_DB_TYPE: ${{ matrix.db-type == 'mysql' && 'sqlx::MySql' || matrix.db-type == 'postgres' && 'sqlx::Postgres' || 'sqlx::Sqlite' }}
SQLX_ENV_DIR: tests/${{ matrix.db-type }}/.sqlx
RUSTFLAGS: ${{ matrix.db-type == 'mysql' && '--cfg sql_forge_db_mysql' || matrix.db-type == 'postgres' && '--cfg sql_forge_db_postgres' || '--cfg sql_forge_db_sqlite' }}
steps:
- uses: actions/checkout@v6
- name: Rust Cache
uses: swatinem/rust-cache@v2
with:
cache-targets: "false"
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
default-libmysqlclient-dev \
libpq-dev \
mysql-client \
pkg-config \
postgresql-client
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: 1.95.0
components: rustfmt, clippy
- name: Verify README and workspace versions
run: bash tests/verify-versions.sh
- name: Wait for database and init
run: |
if [ "${{ matrix.db-type }}" = "mysql" ]; then
until mysqladmin ping -h 127.0.0.1 -uroot -proot --silent; do
echo "waiting for mysql..."
sleep 2
done
mysql -h 127.0.0.1 -uroot -proot sql_forge_test < tests/init.sql
elif [ "${{ matrix.db-type }}" = "postgres" ]; then
until pg_isready -h 127.0.0.1 -U postgres; do
echo "waiting for postgres..."
sleep 2
done
PGPASSWORD=root psql -h 127.0.0.1 -U postgres -d sql_forge_test -f tests/init-pg.sql
else
sqlite3 sql_forge_test.db < tests/init-sqlite.sql
fi
- name: Copy .sqlx metadata for this database type
run: cp -r tests/${{ matrix.db-type }}/.sqlx .sqlx
- name: Install sqlx-cli
run: cargo install sqlx-cli --no-default-features --features native-tls,mysql,postgres,sqlite
- name: Install cargo-expand
run: cargo install cargo-expand
- name: cargo expand and compare with repo copy
run: |
cargo expand --test tests > tests/${{ matrix.db-type }}/tests_expanded.ci.rs
if ! diff -q tests/${{ matrix.db-type }}/tests_expanded.rs tests/${{ matrix.db-type }}/tests_expanded.ci.rs; then
echo "ERROR: tests/${{ matrix.db-type }}/tests_expanded.rs is outdated."
echo "Regenerate it by running in the rust service from the docker-compose file: sql-forge-test"
diff tests/${{ matrix.db-type }}/tests_expanded.rs tests/${{ matrix.db-type }}/tests_expanded.ci.rs
exit 1
fi
- name: cargo check
run: cargo check --tests
- name: cargo fmt
run: cargo fmt --all -- --check
- name: cargo clippy
run: cargo clippy --tests -- -D warnings
- name: Prepare trybuild tmp-ui fixtures
run: |
TMP_UI_DIR="tests/${{ matrix.db-type }}/tmp-ui"
UI_SRC_DIR="tests/ui"
UI_COMMON_DIR="tests/${{ matrix.db-type }}/ui-common"
rm -rf "$TMP_UI_DIR"
mkdir -p "$TMP_UI_DIR"
cp -r "$UI_SRC_DIR/." "$TMP_UI_DIR/"
if [ -d "$UI_COMMON_DIR" ]; then
(
cd "$UI_COMMON_DIR"
find . -type f -name '*.stderr' -exec cp --parents {} "$GITHUB_WORKSPACE/$TMP_UI_DIR" \;
)
fi
- name: cargo test
run: cargo test
- name: Verify that .sqlx/ files are up to date
run: cargo sqlx prepare --check -- --tests
publish:
runs-on: ubuntu-latest
needs: test
if: startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v6
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Verify all crate versions match the tag
run: |
TAG_VERSION="${GITHUB_REF_NAME#v}"
WORKSPACE_VERSION=$(awk '
$0 == "[workspace.package]" { in_workspace_package = 1; next }
/^\[/ { in_workspace_package = 0 }
in_workspace_package && /^version = / {
gsub(/^version = "/, "")
gsub(/"$/, "")
print
exit
}
' Cargo.toml)
for manifest in Cargo.toml sql-forge-macro/Cargo.toml; do
if ! grep -q '^version\.workspace = true$' "$manifest"; then
echo "ERROR: $manifest must inherit the workspace version."
exit 1
fi
done
if [ "$TAG_VERSION" != "$WORKSPACE_VERSION" ]; then
echo "ERROR: Tag version ($TAG_VERSION) does not match workspace version ($WORKSPACE_VERSION)."
exit 1
fi
- name: Dry run publish sql-forge-macro
run: cargo publish -p sql-forge-macro --dry-run
- name: Publish sql-forge-macro
run: cargo publish -p sql-forge-macro
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
- name: Wait for sql-forge-macro to be indexed
run: sleep 30
- name: Dry run publish sql-forge
run: cargo publish -p sql-forge --dry-run --no-verify
- name: Publish sql-forge
run: cargo publish -p sql-forge --no-verify
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}