Browse Source

ci: add integration test workflow with live PostgreSQL and MySQL

Two jobs - one per db - each spinning up a service container:

    1. diesel migration run --migration-dir migrations/<db>
       Verifies every migration applies cleanly to a fresh instance.
       This is the primary gap: a broken migration would otherwise only
       surface on production deployment.

    2. cargo test --features <db> with DATABASE_URL set
       Builds and runs the test suite against the live engine. Existing
       tests are unit-level (no DB access), but DATABASE_URL is wired in
       so any future integration tests work without further infrastructure
       changes.

    Service containers: postgres:16, mysql:8.4 (utf8mb4).
    diesel CLI binary is cached keyed on Cargo.lock hash to avoid
    recompiling it on every run.
    Triggers on the same path set as build.yml (src/**, migrations/**,
    Cargo.*, rust-toolchain.toml).
pull/6998/head
TriplEight 2 weeks ago
parent
commit
68fc32fda0
No known key found for this signature in database GPG Key ID: 9E9B1BBD89CE29A1
  1. 167
      .github/workflows/integration-test.yml
  2. 2
      migrations/mysql/2022-07-27-110000_add_group_support/up.sql
  3. 7
      migrations/mysql/2026-03-22-100000_add_primary_keys_to_group_tables/down.sql
  4. 10
      migrations/mysql/2026-03-22-100000_add_primary_keys_to_group_tables/up.sql

167
.github/workflows/integration-test.yml

@ -0,0 +1,167 @@
name: Integration Tests
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
on:
push:
paths:
- ".github/workflows/integration-test.yml"
- "src/**"
- "migrations/**"
- "Cargo.*"
- "build.rs"
- "rust-toolchain.toml"
pull_request:
paths:
- ".github/workflows/integration-test.yml"
- "src/**"
- "migrations/**"
- "Cargo.*"
- "build.rs"
- "rust-toolchain.toml"
defaults:
run:
shell: bash
env:
RUSTFLAGS: "-Dwarnings"
jobs:
# ============================================================
# PostgreSQL integration test
# ============================================================
postgresql:
name: Integration test (PostgreSQL)
runs-on: ubuntu-24.04
timeout-minutes: 60
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: vaultwarden
POSTGRES_PASSWORD: vaultwarden
POSTGRES_DB: vaultwarden
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U vaultwarden"
--health-interval 5s
--health-timeout 5s
--health-retries 15
env:
DATABASE_URL: "postgresql://vaultwarden:vaultwarden@localhost:5432/vaultwarden"
steps:
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends libpq-dev pkg-config
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Rust cache
uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with:
prefix-key: "v2025.09-rust-integration-pg"
# Cache the diesel CLI binary to avoid recompiling it on every run.
# Key includes the Cargo.lock hash so it is invalidated when diesel is upgraded.
- name: Cache diesel CLI (postgresql)
id: cache-diesel-pg
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.2
with:
path: ~/.cargo/bin/diesel
key: diesel-cli-postgres-${{ runner.os }}-${{ hashFiles('Cargo.lock') }}
- name: Install diesel CLI (postgresql)
if: steps.cache-diesel-pg.outputs.cache-hit != 'true'
run: cargo install diesel_cli --no-default-features --features postgres
# Verify that all PostgreSQL migrations apply cleanly to a fresh database.
# This catches broken SQL before it reaches a production deployment.
# DIESEL_CONFIG_FILE=/dev/null disables the [print_schema] setting from
# diesel.toml so that schema.rs is not overwritten during the check.
- name: Run PostgreSQL migrations
env:
DIESEL_CONFIG_FILE: /dev/null
run: diesel migration run --migration-dir migrations/postgresql
# Run the test suite with a live PostgreSQL instance available.
# Existing tests are unit tests (no DB access), but DATABASE_URL is set
# so any future integration tests can connect without further setup.
- name: Run tests (postgresql)
run: cargo test --profile ci --features postgresql
# ============================================================
# MySQL integration test
# ============================================================
mysql:
name: Integration test (MySQL)
runs-on: ubuntu-24.04
timeout-minutes: 60
services:
mysql:
image: mysql:8.4
env:
MYSQL_USER: vaultwarden
MYSQL_PASSWORD: vaultwarden
MYSQL_DATABASE: vaultwarden
MYSQL_ROOT_PASSWORD: root
MYSQL_CHARACTER_SET_SERVER: utf8mb4
MYSQL_COLLATION_SERVER: utf8mb4_unicode_ci
ports:
- 3306:3306
options: >-
--health-cmd "mysqladmin ping -h localhost -uvaultwarden -pvaultwarden --silent"
--health-interval 5s
--health-timeout 5s
--health-retries 15
env:
DATABASE_URL: "mysql://vaultwarden:vaultwarden@127.0.0.1:3306/vaultwarden"
steps:
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends libmariadb-dev-compat pkg-config
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Rust cache
uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with:
prefix-key: "v2025.09-rust-integration-mysql"
# Cache the diesel CLI binary to avoid recompiling it on every run.
- name: Cache diesel CLI (mysql)
id: cache-diesel-mysql
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.2
with:
path: ~/.cargo/bin/diesel
key: diesel-cli-mysql-${{ runner.os }}-${{ hashFiles('Cargo.lock') }}
- name: Install diesel CLI (mysql)
if: steps.cache-diesel-mysql.outputs.cache-hit != 'true'
run: cargo install diesel_cli --no-default-features --features mysql
# Verify that all MySQL migrations apply cleanly to a fresh database.
# DIESEL_CONFIG_FILE=/dev/null for the same reason as the PostgreSQL job.
- name: Run MySQL migrations
env:
DIESEL_CONFIG_FILE: /dev/null
run: diesel migration run --migration-dir migrations/mysql
# Run the test suite with a live MySQL instance available.
- name: Run tests (mysql)
run: cargo test --profile ci --features mysql

2
migrations/mysql/2022-07-27-110000_add_group_support/up.sql

@ -20,4 +20,4 @@ CREATE TABLE collections_groups (
read_only BOOLEAN NOT NULL,
hide_passwords BOOLEAN NOT NULL,
UNIQUE (collections_uuid, groups_uuid)
);
);

7
migrations/mysql/2026-03-22-100000_add_primary_keys_to_group_tables/down.sql

@ -0,0 +1,7 @@
ALTER TABLE groups_users
DROP PRIMARY KEY,
ADD UNIQUE (groups_uuid, users_organizations_uuid);
ALTER TABLE collections_groups
DROP PRIMARY KEY,
ADD UNIQUE (collections_uuid, groups_uuid);

10
migrations/mysql/2026-03-22-100000_add_primary_keys_to_group_tables/up.sql

@ -0,0 +1,10 @@
-- groups_users and collections_groups were created with UNIQUE instead of
-- PRIMARY KEY. Diesel requires primary keys on all tables for schema
-- introspection. Drop the auto-named unique index and add the primary key.
ALTER TABLE groups_users
DROP INDEX groups_uuid,
ADD PRIMARY KEY (groups_uuid, users_organizations_uuid);
ALTER TABLE collections_groups
DROP INDEX collections_uuid,
ADD PRIMARY KEY (collections_uuid, groups_uuid);
Loading…
Cancel
Save