name: migrate cassandra on: push: branches: - canary paths: - fluxer_devops/cassandra/migrations/**/*.cql workflow_dispatch: concurrency: group: migrate-cassandra-prod cancel-in-progress: false permissions: contents: read jobs: migrate: name: Run database migrations runs-on: blacksmith-2vcpu-ubuntu-2404 timeout-minutes: 10 steps: - uses: actions/checkout@v6 - name: Set up Rust uses: dtolnay/rust-toolchain@stable - name: Cache Rust dependencies uses: actions/cache@v5 with: path: | ~/.cargo/bin/ ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ scripts/cassandra-migrate/target/ key: ${{ runner.os }}-cargo-${{ hashFiles('scripts/cassandra-migrate/Cargo.lock') }} restore-keys: | ${{ runner.os }}-cargo- - name: Build migration tool run: | set -euo pipefail cd scripts/cassandra-migrate cargo build --release - name: Validate migrations run: | set -euo pipefail ./scripts/cassandra-migrate/target/release/cassandra-migrate check - name: Set up SSH agent uses: webfactory/ssh-agent@v0.9.1 with: ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }} - name: Add server to known hosts run: | set -euo pipefail mkdir -p ~/.ssh ssh-keyscan -H ${{ secrets.SERVER_IP }} >> ~/.ssh/known_hosts - name: Set up SSH tunnel for Cassandra run: | set -euo pipefail nohup ssh -N -o ConnectTimeout=30 -o ServerAliveInterval=10 -o ServerAliveCountMax=30 -o ExitOnForwardFailure=yes -L 9042:localhost:9042 ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }} > /tmp/ssh-tunnel.log 2>&1 & SSH_TUNNEL_PID=$! printf 'SSH_TUNNEL_PID=%s\n' "$SSH_TUNNEL_PID" >> "$GITHUB_ENV" for i in {1..30}; do if timeout 1 bash -c "echo > /dev/tcp/localhost/9042" 2>/dev/null; then echo "SSH tunnel established" break elif command -v ss >/dev/null 2>&1 && ss -tln | grep -q ":9042 "; then echo "SSH tunnel established" break elif command -v netstat >/dev/null 2>&1 && netstat -tln | grep -q ":9042 "; then echo "SSH tunnel established" break fi if [ $i -eq 30 ]; then cat /tmp/ssh-tunnel.log || true exit 1 fi sleep 1 done ps -p $SSH_TUNNEL_PID > /dev/null || exit 1 - name: Test Cassandra connection env: CASSANDRA_USERNAME: ${{ secrets.CASSANDRA_USERNAME }} CASSANDRA_PASSWORD: ${{ secrets.CASSANDRA_PASSWORD }} run: | set -euo pipefail ./scripts/cassandra-migrate/target/release/cassandra-migrate \ --host localhost \ --port 9042 \ --username "${CASSANDRA_USERNAME}" \ --password "${CASSANDRA_PASSWORD}" \ test - name: Run migrations env: CASSANDRA_USERNAME: ${{ secrets.CASSANDRA_USERNAME }} CASSANDRA_PASSWORD: ${{ secrets.CASSANDRA_PASSWORD }} run: | set -euo pipefail ./scripts/cassandra-migrate/target/release/cassandra-migrate \ --host localhost \ --port 9042 \ --username "${CASSANDRA_USERNAME}" \ --password "${CASSANDRA_PASSWORD}" \ up - name: Close SSH tunnel if: always() run: | set -euo pipefail if [ -n "${SSH_TUNNEL_PID:-}" ]; then kill "$SSH_TUNNEL_PID" 2>/dev/null || true fi pkill -f "ssh.*9042:localhost:9042" || true rm -f /tmp/ssh-tunnel.log || true