Skip to content

Commit a2dbfa0

Browse files
authored
decompose CI (#200)
1 parent f63d3fd commit a2dbfa0

File tree

3 files changed

+309
-44
lines changed

3 files changed

+309
-44
lines changed

.github/workflows/build_and_test.yml renamed to .github/workflows/pipeline.yml

Lines changed: 121 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Build and Test
1+
name: CI Pipeline
22

33
on:
44
push:
@@ -15,7 +15,27 @@ env:
1515
AWS_REGION: us-west-2
1616

1717
jobs:
18+
lint:
19+
name: Lint Code
20+
runs-on: ubuntu-latest
21+
timeout-minutes: 5
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v3
25+
26+
- name: Install uv
27+
uses: astral-sh/setup-uv@v5
28+
with:
29+
version: "0.7.3"
30+
31+
- name: Run linters
32+
uses: astral-sh/ruff-action@v3
33+
with:
34+
version: ">=0.11.5"
35+
args: check .
36+
1837
build-template:
38+
name: Build Template
1939
runs-on: ubuntu-latest
2040
timeout-minutes: 10
2141
steps:
@@ -68,45 +88,33 @@ jobs:
6888
exit 1
6989
fi
7090
71-
build-and-test-codegen:
72-
runs-on: ubuntu-latest
73-
timeout-minutes: 30
74-
75-
permissions:
76-
contents: read
91+
- name: Clean up Docker Compose services
92+
working-directory: ./agent/trpc_agent/template/
93+
if: always()
94+
run: |
95+
echo "Stopping and removing Docker Compose services..."
96+
docker compose down -v --remove-orphans
97+
echo "Cleanup complete."
7798
99+
# not really unit for now, but should be at some point!
100+
unit-tests:
101+
name: Run Other Tests
102+
runs-on: ubuntu-latest
103+
timeout-minutes: 15
78104
steps:
79105
- name: Checkout repository
80106
uses: actions/checkout@v3
81-
with:
82-
fetch-depth: 2
83107

84108
- name: Install uv
85109
uses: astral-sh/setup-uv@v5
86110
with:
87111
version: "0.7.3"
88112

89-
- name: Run linters
90-
uses: astral-sh/ruff-action@v3
91-
with:
92-
version: ">=0.11.5"
93-
args: check .
94-
95-
- name: Set up Docker Buildx
96-
uses: docker/setup-buildx-action@v2
97-
98-
- name: Set up Docker Compose
99-
uses: docker/setup-compose-action@v1
100-
101-
- name: Start Docker Compose services
102-
working-directory: ./agent/
103-
run: docker compose up -d --build
104-
105113
- name: Run tests
106114
working-directory: ./agent/
107115
run: |
108116
echo "Running tests..."
109-
uv run test --verbose
117+
uv run test --verbose --exclude e2e
110118
exit_code=$?
111119
if [ $exit_code -ne 0 ]; then
112120
echo "Tests failed with exit code $exit_code"
@@ -115,8 +123,27 @@ jobs:
115123
echo "Tests passed successfully!"
116124
fi
117125
126+
health-check:
127+
name: Container Health Check
128+
runs-on: ubuntu-latest
129+
timeout-minutes: 10
130+
steps:
131+
- name: Checkout repository
132+
uses: actions/checkout@v3
133+
134+
- name: Set up Docker Buildx
135+
uses: docker/setup-buildx-action@v2
136+
137+
- name: Set up Docker Compose
138+
uses: docker/setup-compose-action@v1
139+
140+
- name: Start Docker Compose services
141+
working-directory: ./agent/
142+
run: docker compose up -d --build
143+
118144
- name: Check Container Health
119145
run: |
146+
sleep 30
120147
echo "Checking health of container: ${{ env.CONTAINER_NAME }}"
121148
status=$(docker inspect --format='{{.State.Health.Status}}' ${{ env.CONTAINER_NAME }})
122149
@@ -130,15 +157,83 @@ jobs:
130157
exit 1
131158
fi
132159
160+
# Cleanup even if the job fails
161+
- name: Clean up Docker Compose services
162+
working-directory: ./agent/
163+
if: always()
164+
run: |
165+
echo "Stopping and removing Docker Compose services..."
166+
docker compose down -v --remove-orphans
167+
echo "Cleanup complete."
168+
169+
e2e-tests:
170+
name: Run E2E Tests
171+
runs-on: ubuntu-latest
172+
timeout-minutes: 20
173+
steps:
174+
- name: Checkout repository
175+
uses: actions/checkout@v3
176+
177+
- name: Install uv
178+
uses: astral-sh/setup-uv@v5
179+
with:
180+
version: "0.7.3"
181+
182+
- name: Set up Docker Buildx
183+
uses: docker/setup-buildx-action@v2
184+
185+
- name: Set up Docker Compose
186+
uses: docker/setup-compose-action@v1
187+
188+
- name: Start Docker Compose services
189+
working-directory: ./agent/
190+
run: docker compose up -d --build
191+
192+
- name: Run E2E tests
193+
working-directory: ./agent/
194+
run: |
195+
echo "Running E2E tests..."
196+
uv run test_e2e
197+
exit_code=$?
198+
if [ $exit_code -ne 0 ]; then
199+
echo "E2E tests failed with exit code $exit_code"
200+
exit $exit_code
201+
else
202+
echo "E2E tests passed successfully!"
203+
fi
204+
205+
# Cleanup even if the job fails
206+
- name: Clean up Docker Compose services
207+
working-directory: ./agent/
208+
if: always()
209+
run: |
210+
echo "Stopping and removing Docker Compose services..."
211+
docker compose down -v --remove-orphans
212+
echo "Cleanup complete."
213+
214+
# 6. Build and push to ECR (only runs if previous jobs succeed)
215+
build-and-push:
216+
name: Build and Push Docker Image
217+
runs-on: ubuntu-latest
218+
timeout-minutes: 20
219+
needs: [build-template, unit-tests, health-check, e2e-tests, lint]
220+
steps:
221+
- name: Checkout repository
222+
uses: actions/checkout@v3
223+
with:
224+
fetch-depth: 2
225+
133226
- name: Determine if Release Build is Needed
134227
id: check_release
135228
run: |
136229
is_release="false"
137230
# we check two commits because the first commit is the merge commit
138231
if git log -2 --pretty=%s | tail -n 1 | grep -q "release"; then
139232
is_release="true"
233+
echo "Release build detected based on commit message."
140234
elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == "refs/heads/main" ]]; then
141235
is_release="true"
236+
echo "Release build detected based on push to main branch."
142237
fi
143238
144239
echo "is_release=${is_release}" >> $GITHUB_OUTPUT
@@ -187,12 +282,3 @@ jobs:
187282
--push \
188283
.
189284
echo "Docker image built and pushed successfully!"
190-
191-
# This step will run even if the health check step fails
192-
- name: Clean up Docker Compose services
193-
working-directory: ./agent/
194-
if: always() # Ensures this step runs even if previous steps fail
195-
run: |
196-
echo "Stopping and removing Docker Compose services..."
197-
docker compose down -v --remove-orphans # Stop, remove containers, networks, AND volumes (-v)
198-
echo "Cleanup complete."

agent/commands.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,27 @@
1414
def _current_dir():
1515
return os.path.dirname(os.path.abspath(__file__))
1616

17+
1718
def _n_workers():
1819
return str(min(os.cpu_count() or 1, 4))
1920

2021

21-
def _run_tests_with_cache(dest=".", n_workers=_n_workers(), verbose=False):
22+
def _run_tests_with_cache(dest=".", n_workers=_n_workers(), verbose=False, exclude: str | None = None):
2223
os.environ["LLM_VCR_CACHE_MODE"] = "replay"
2324
os.chdir(_current_dir())
2425
flag = "-vs" if verbose else "-v"
25-
code = pytest.main([flag, "-n", str(n_workers), dest])
26+
params = [flag, "-n", str(n_workers), dest]
27+
if exclude:
28+
params += ["-k", f"not {exclude}"]
29+
code = pytest.main(params)
2630
if code != 0:
2731
raise RuntimeError(f"pytest failed with code {code}")
2832

2933

3034
def run_tests_with_cache():
3135
Fire(_run_tests_with_cache)
3236

37+
3338
def update_cache(dest="."):
3439
os.environ["LLM_VCR_CACHE_MODE"] = "record"
3540
os.chdir(_current_dir())
@@ -44,23 +49,28 @@ def run_lint():
4449
if code.returncode != 0:
4550
raise RuntimeError(f"ruff failed with code {code.returncode}")
4651

52+
4753
def run_e2e_tests():
4854
coloredlogs.install(level="INFO")
4955
_run_tests_with_cache("tests/test_e2e.py", n_workers="0", verbose=True)
5056

57+
5158
def generate():
5259
os.environ["LLM_VCR_CACHE_MODE"] = "lru"
5360
return Fire(_generate)
5461

62+
5563
def _generate(prompt=DEFAULT_APP_REQUEST):
5664
coloredlogs.install(level="INFO")
5765
anyio.run(run_e2e, prompt, True)
5866

67+
5968
def interactive():
6069
coloredlogs.install(level="INFO")
6170
os.environ["LLM_VCR_CACHE_MODE"] = "lru"
6271
Fire(_run_interactive)
6372

73+
6474
def help_command():
6575
"""Displays all available custom uv run commands with examples."""
6676
if tomllib is None:
@@ -91,23 +101,21 @@ def help_command():
91101
# and has a doc string in command_docs or fallback_examples
92102
scripts = {"help": "commands:help_command"}
93103
if "help" not in command_docs and "help" not in fallback_examples:
94-
# Provide a very basic default if no doc is available anywhere
95-
command_docs["help"] = "Displays this help message. Example: uv run help"
96-
104+
# Provide a very basic default if no doc is available anywhere
105+
command_docs["help"] = "Displays this help message. Example: uv run help"
97106

98107
# Ensure help is in the list for display, especially if pyproject.toml is empty or lacks it.
99108
if "help" not in scripts:
100109
scripts["help"] = "commands:help_command"
101110

102111
all_command_names = set(scripts.keys())
103112
if not all_command_names:
104-
max_len = len("Command") + 2
113+
max_len = len("Command") + 2
105114
else:
106115
max_len = max(len(name) for name in all_command_names) + 2
107116

108-
109117
print(f"{'Command':<{max_len}} {'Description / Example'}")
110-
print(f"{'=' * max_len} {'=' * 40}") # Using '=' for a slightly different look
118+
print(f"{'=' * max_len} {'=' * 40}") # Using '=' for a slightly different look
111119

112120
for name, target in sorted(scripts.items()):
113121
# Prioritize help string from [tool.agent.command_docs]
@@ -121,7 +129,9 @@ def help_command():
121129

122130
print(f"{name:<{max_len}} {help_text}")
123131

124-
print("\nNote: Some commands might accept additional arguments. Refer to their implementations or detailed docs.")
132+
print(
133+
"\nNote: Some commands might accept additional arguments. Refer to their implementations or detailed docs."
134+
)
125135

126136
except FileNotFoundError:
127137
print(f"Error: pyproject.toml not found at expected location: {pyproject_path}")

0 commit comments

Comments
 (0)