Files
LangBot/.github/workflows/core-smoke.yml
T
huanghuoguoguo 5ec41f15a1 test(ci): add a 60-second core smoke gate and regression jobs (#2711)
* test(tools): add deterministic lbctl regression job

* test(tools): simulate persistent multi-group conversations

* test(tools): add finite core smoke with terminal run and file oracles

* test(tools): expand smoke coverage across execution stages

* ci: add a timed real core smoke and lightweight tool checks

* fix(ci): keep infrastructure failures visible in smoke verdicts
2026-10-23 16:24:26 +08:00

114 lines
4.0 KiB
YAML

name: Core Smoke
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
push:
branches: [master, develop]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: core-smoke-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
tools:
name: Regression tools
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: python -m pip install PyYAML==6.0.3
- name: Check regression tools
run: timeout 60s python -m unittest discover -s tools -p 'test_*.py' -v
smoke:
name: Core smoke (60s)
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- uses: astral-sh/setup-uv@v4
with:
enable-cache: true
- name: Install locked dependencies
run: uv sync --dev --frozen
- name: Read official plugin source pin
id: plugins
run: |
python - <<'PY'
import json, os
from pathlib import Path
revision = json.loads(Path('tests/fixtures/legacy_plugin_identity_sources.json').read_text())['revision']
with open(os.environ['GITHUB_OUTPUT'], 'a') as stream:
stream.write(f'revision={revision}\n')
PY
- uses: actions/checkout@v4
with:
repository: langbot-app/langbot-plugins
ref: ${{ steps.plugins.outputs.revision }}
path: .smoke-plugins
persist-credentials: false
- name: Prepare CLI and sandbox image
env:
GH_TOKEN: ${{ github.token }}
run: |
mkdir -p .smoke-bin
gh release download v0.3.0 --repo langbot-app/langbot-cli --dir .smoke-bin \
--pattern lbctl_linux_amd64 --pattern checksums.txt
cd .smoke-bin
sha256sum --check --ignore-missing checksums.txt
chmod +x lbctl_linux_amd64
docker pull python:3.12-alpine
- name: Prepare real services and run the 60-second smoke
run: |
uv run --no-sync python tools/regression_ci.py \
--lbctl .smoke-bin/lbctl_linux_amd64 --plugins .smoke-plugins --output .qa/core-smoke
- name: Publish gate result
if: always()
run: |
python - <<'PY'
import json, os
from pathlib import Path
path = Path('.qa/core-smoke/gate/gate.json')
with open(os.environ['GITHUB_STEP_SUMMARY'], 'a') as out:
if path.exists():
data = json.loads(path.read_text())
out.write(f"Core smoke: {'PASS' if data['passed'] else 'FAIL'}; "
f"{data.get('elapsed_seconds', 0):.2f}/60 seconds; {data.get('requests', 0)} requests.\n")
if data.get('infrastructure_error'):
out.write('Preparation or teardown failed; inspect service logs.\n')
out.write('Service/dependency preparation is outside the 60-second execution budget.\n')
else:
out.write('Core smoke did not produce a verdict; inspect preparation failure.\n')
PY
- name: Preserve verdicts and resource samples
if: always()
uses: actions/upload-artifact@v4
with:
name: core-smoke-${{ github.run_id }}
path: |
.qa/core-smoke/gate/gate.json
.qa/core-smoke/gate/resources.jsonl
.qa/core-smoke/gate/suite.log
.qa/core-smoke/gate/suite/cases.json
.qa/core-smoke/gate/suite/summary.json
.qa/core-smoke/gate/suite/health.json
.qa/core-smoke/gate/suite/cleanup-checks.json
.qa/core-smoke/*.log
if-no-files-found: warn
retention-days: 7