Skip to content

fix(ci): seed smoke token via psql stdin #14

fix(ci): seed smoke token via psql stdin

fix(ci): seed smoke token via psql stdin #14

name: Git Protocol Smoke
# Automated regression gate for `scripts/git_protocol_smoke.sh` (protocol.md
# P0: "建立真实 Git 客户端兼容性矩阵"). The script exercises the real Git
# CLI against a running `service http` instance, covering ls-remote, clone,
# fetch, protocol v2 fetch, shallow clone, and blob:none partial clone.
#
# CI seeds a one-off Mono access token directly into the smoke database and
# runs the HTTP push/delete branch+tag matrix with Basic Auth. LFS remains
# manual because it needs git-lfs on the runner and a larger object round trip.
on:
pull_request:
paths:
- ".github/workflows/git-protocol-smoke.yml"
- "scripts/git_protocol_smoke.sh"
- "src/ceres/protocol/**"
- "src/contract/git_protocol/**"
- "src/server/http_server.rs"
- "docs/refactoring/protocol.md"
push:
branches:
- main
paths:
- ".github/workflows/git-protocol-smoke.yml"
- "scripts/git_protocol_smoke.sh"
- "src/ceres/protocol/**"
- "src/contract/git_protocol/**"
- "src/server/http_server.rs"
- "docs/refactoring/protocol.md"
jobs:
git-protocol-smoke:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout monoengine
uses: actions/checkout@v5
with:
path: monoengine
- name: Validate orbit checkout token
env:
ORBIT_CHECKOUT_TOKEN: ${{ secrets.ORBIT_CHECKOUT_TOKEN }}
run: |
if [ -z "${ORBIT_CHECKOUT_TOKEN}" ]; then
echo "::error title=Missing ORBIT_CHECKOUT_TOKEN::Git protocol smoke needs to checkout the private gitmono-dev/orbit sibling repository. Add an Actions secret named ORBIT_CHECKOUT_TOKEN with read-only contents access to gitmono-dev/orbit."
exit 1
fi
- name: Checkout orbit sibling
uses: actions/checkout@v5
with:
repository: gitmono-dev/orbit
ref: main
path: orbit
token: ${{ secrets.ORBIT_CHECKOUT_TOKEN }}
- name: Install Rust toolchain
run: |
rustup toolchain install stable --profile minimal
rustup default stable
- name: Install git
run: |
git --version
git config --global user.email "ci@example.invalid"
git config --global user.name "CI Smoke"
- name: Build monoengine binary
working-directory: monoengine
run: cargo build --release -p monoengine
- name: Mask test secrets in logs
run: |
echo "::add-mask::mono_test_password"
echo "::add-mask::smtp-test-password"
- name: Start test services (PostgreSQL, Redis)
working-directory: monoengine
run: |
docker compose -f docker-compose.test.yml up -d --wait postgres redis
docker compose -f docker-compose.test.yml ps
- name: Prepare smoke config and seed secret
working-directory: monoengine
env:
MEGA_DATABASE__DB_URL: postgres://mono:mono_test_password@127.0.0.1:15432/monoengine_smoke
MEGA_REDIS__URL: redis://127.0.0.1:16379
MEGA_BASE_DIR: ${{ runner.temp }}/monoengine-smoke/base
run: |
set -euo pipefail
smoke_dir="${RUNNER_TEMP}/monoengine-smoke"
mkdir -p "${smoke_dir}/base"
cp config/config.toml "${smoke_dir}/config.toml"
# Create a dedicated database for the smoke run.
psql "postgres://mono:mono_test_password@127.0.0.1:15432/monoengine_it" \
-c "DROP DATABASE IF EXISTS monoengine_smoke" \
-c "CREATE DATABASE monoengine_smoke"
# Seed mail.password so that service http can start (mail is enabled
# in the default config with a password_ref). MEGA_BASE_DIR must be
# set here too so the vault core key is written to the same location
# that `service http` will later read from.
printf '%s' 'smtp-test-password' \
| ./target/release/monoengine --config "${smoke_dir}/config.toml" \
config secret set mail.password \
--vault-path config/smoke/mail/password \
--field value --value-stdin
smoke_git_token="$(python3 -c 'import secrets; print(secrets.token_urlsafe(32))')"
echo "::add-mask::${smoke_git_token}"
psql "${MEGA_DATABASE__DB_URL}" \
-v ON_ERROR_STOP=1 \
-v token="${smoke_git_token}" <<'SQL'
INSERT INTO access_token (id, username, token, created_at)
VALUES ((extract(epoch from clock_timestamp()) * 1000000)::bigint, 'ci-smoke', :'token', now());
SQL
echo "SMOKE_CONFIG_PATH=${smoke_dir}/config.toml" >> "$GITHUB_ENV"
echo "SMOKE_BASE_DIR=${smoke_dir}/base" >> "$GITHUB_ENV"
echo "SMOKE_GIT_TOKEN=${smoke_git_token}" >> "$GITHUB_ENV"
- name: Start service http
working-directory: monoengine
env:
MEGA_DATABASE__DB_URL: postgres://mono:mono_test_password@127.0.0.1:15432/monoengine_smoke
MEGA_REDIS__URL: redis://127.0.0.1:16379
MEGA_DATABASE__SQLX_LOGGING: "false"
MEGA_LOG__PRINT_STD: "true"
MEGA_LOG__LEVEL: "info"
MEGA_BASE_DIR: ${{ env.SMOKE_BASE_DIR }}
run: |
set -euo pipefail
PORT=9000
echo "Starting monoengine service http on port ${PORT}..."
./target/release/monoengine --config "${SMOKE_CONFIG_PATH}" \
service http --host 127.0.0.1 -p "${PORT}" &
SERVICE_PID=$!
echo "SERVICE_PID=${SERVICE_PID}" >> "$GITHUB_ENV"
# Wait for the service to become ready (max 90 seconds).
deadline=$((SECONDS + 90))
until curl -sf "http://127.0.0.1:${PORT}/api/openapi.json" >/dev/null 2>&1; do
if [ $SECONDS -ge $deadline ]; then
echo "::error::service http did not become ready within 90 seconds"
kill $SERVICE_PID 2>/dev/null || true
exit 1
fi
sleep 1
done
echo "service http is ready"
- name: Run git protocol smoke (HTTP)
working-directory: monoengine
run: |
set -euo pipefail
# The monorepo root "/" is initialized by init_monorepo during
# service startup and has refs/heads/main. Push/delete uses the
# one-off access token seeded into the smoke database above.
MONOENGINE_HTTP_REPO_URL="http://ci-smoke:${SMOKE_GIT_TOKEN}@127.0.0.1:9000/" \
MONOENGINE_GIT_SMOKE_PUSH=1 \
bash scripts/git_protocol_smoke.sh
- name: Stop service http
if: always()
run: |
if [ -n "${SERVICE_PID:-}" ]; then
kill "${SERVICE_PID}" 2>/dev/null || true
wait "${SERVICE_PID}" 2>/dev/null || true
fi
- name: Stop test services
if: always()
working-directory: monoengine
run: docker compose -f docker-compose.test.yml down -v