Commit d5390cc
authored
feat: container build context config + full build log preservation (#1110)
<h3>PR Summary by Qodo</h3>
Add container build context option and preserve full redacted build logs
<code>✨ Enhancement</code> <code>🐞 Bug fix</code> <code>🧪 Tests</code>
<code>⚙️ Configuration changes</code> <code>📝 Documentation</code>
<code>🕐 20-40 Minutes</code>
<img
src="https://www.qodo.ai/wp-content/uploads/2025/11/light-grey-line.svg"
height="10%" alt="Grey Divider">
<h3>Walkthroughs</h3>
<details open>
<summary>User Description</summary>
<br/>
## Summary
Two container build improvements:
### Full build log preservation (#1090)
- Log full redacted build output before truncation for debugging
- Extract `_redact_output()` helper for reusable secret redaction
- Truncation threshold uses ANSI-stripped lengths consistently
### Docker build context from non-root directory (#1065)
- Add `context` config option under `container` for non-root build
context
- Path traversal validation prevents context escaping worktree root
- Schema pattern constraint rejects obviously bad values
Closes #1090
Closes #1065
</details>
<details open>
<summary>AI Description</summary>
<br/>
<pre>
• Add <b><i>container.context</i></b> config to build images from a repo
subdirectory.
• Validate context stays within the checked-out worktree to prevent path
traversal.
• Log full redacted build output before GitHub check-run truncation for
debugging.
</pre>
</details>
<details>
<summary>Diagram</summary>
<br/>
```mermaid
graph TD
cfg["Container config"] --> loader["Config loader"] --> runner["RunnerHandler"] --> podman["Podman build"]
runner --> check["CheckRunHandler"] --> gh["GitHub Checks API"]
```
</details>
<details>
<summary>High-Level Assessment</summary>
<br/>
The following are alternative approaches to this PR:
<details>
<summary><b>1. Use commonpath/is_relative_to for context
validation</b></summary>
- ➕ Less error-prone than string prefix checks
- ➕ More readable intent: “resolved path is within worktree”
- ➖ `Path.is_relative_to` requires Python 3.9+; `commonpath` still needs
careful normalization/symlink handling
</details>
<details>
<summary><b>2. Persist full build logs as artifacts instead of debug
logs</b></summary>
- ➕ Avoids flooding debug logs while still preserving full output
- ➕ Makes large logs easier to browse/download
- ➖ Requires artifact storage/retention and plumbing (upload, linking,
cleanup)
- ➖ More moving parts than a server-side debug log
</details>
**Recommendation:** The PR’s approach is reasonable: config-driven
context selection with realpath-based containment checks, plus
pre-truncation redacted logging gated on truncation. If context
validation edge cases become a concern, consider switching to
`os.path.commonpath` (or `Path.resolve().is_relative_to()` where
supported) to express containment more directly.
</details>
<img
src="https://www.qodo.ai/wp-content/uploads/2025/11/light-grey-line.svg"
height="10%" alt="Grey Divider">
<h3>File Changes</h3>
<details>
<summary><strong>Enhancement</strong> (2)</summary>
<blockquote>
<details>
<summary><strong>github_api.py</strong> <code>Read container context
from repo config into webhook runtime</code>
<code>+1/-0</code></summary>
<br/>
>Read container context from repo config into webhook runtime
>
><pre>
>• Extends repository config ingestion to populate
'container_context' from 'container.context',
defaulting to empty string when unset.
></pre>
>
><a
href='https://github.com/myk-org/github-webhook-server/pull/1110/files#diff-7c5f6dfcadb38e75c2d0f1d418ba1a861cc9f6c0efe72905a250e9f43a6cfdcf'>webhook_server/libs/github_api.py</a>
<hr/>
</details>
</blockquote>
<blockquote>
<details>
<summary><strong>runner_handler.py</strong> <code>Support building
containers from a configured subdirectory context</code>
<code>+26/-6</code></summary>
<br/>
>Support building containers from a configured subdirectory context
>
><pre>
>• Uses 'container_context' to select the podman build context
directory while keeping the Dockerfile path rooted at the worktree. Adds
realpath-based validation to reject contexts that resolve outside the
checked-out worktree and fails the check run instead of building.
></pre>
>
><a
href='https://github.com/myk-org/github-webhook-server/pull/1110/files#diff-0cb54c95cafda12d8d169c7b03ac484738f4cf925c22f6e6b8b8c5db0730ce42'>webhook_server/libs/handlers/runner_handler.py</a>
<hr/>
</details>
</blockquote>
</details>
<details>
<summary><strong>Bug fix</strong> (1)</summary>
<blockquote>
<details>
<summary><strong>check_run_handler.py</strong> <code>Preserve full
redacted output in logs before check-run truncation</code>
<code>+38/-18</code></summary>
<br/>
>Preserve full redacted output in logs before check-run truncation
>
><pre>
>• Extracts a reusable '_redact_output()' helper and uses it
both for returned check-run text and for a new debug log that captures
the full redacted output when truncation is required. Truncation
detection is based on ANSI-stripped lengths to match what is sent to
GitHub.
></pre>
>
><a
href='https://github.com/myk-org/github-webhook-server/pull/1110/files#diff-6b505edd8695d646f7fec8e71517af3e42df16342d1409a74c8212063ab26f56'>webhook_server/libs/handlers/check_run_handler.py</a>
<hr/>
</details>
</blockquote>
</details>
<details>
<summary><strong>Tests</strong> (3)</summary>
<blockquote>
<details>
<summary><strong>test_check_run_handler.py</strong> <code>Add tests for
pre-truncation full-output logging and redaction</code>
<code>+53/-0</code></summary>
<br/>
>Add tests for pre-truncation full-output logging and redaction
>
><pre>
>• Adds coverage ensuring the full output debug log is emitted only when
truncation occurs and that secrets are redacted in the logged content.
></pre>
>
><a
href='https://github.com/myk-org/github-webhook-server/pull/1110/files#diff-ab2e5c2c544a42d78004d8aa40f768b38426f08f365090a75fdb5e4fad57a7cc'>webhook_server/tests/test_check_run_handler.py</a>
<hr/>
</details>
</blockquote>
<blockquote>
<details>
<summary><strong>test_repo_data_from_config.py</strong> <code>Test
container context config parsing and defaults</code>
<code>+27/-0</code></summary>
<br/>
>Test container context config parsing and defaults
>
><pre>
>• Asserts 'container_context' defaults to empty string and is
correctly read when supplied under the 'container' config
block.
></pre>
>
><a
href='https://github.com/myk-org/github-webhook-server/pull/1110/files#diff-4e76f4b4427b5be5ab45623aa0f35a24a51b526903e36dbf3ea347757ae1cc62'>webhook_server/tests/test_repo_data_from_config.py</a>
<hr/>
</details>
</blockquote>
<blockquote>
<details>
<summary><strong>test_runner_handler.py</strong> <code>Test build
context selection and traversal rejection in container builds</code>
<code>+96/-0</code></summary>
<br/>
>Test build context selection and traversal rejection in container
builds
>
><pre>
>• Adds tests verifying the podman command uses the configured
subdirectory as context, rejects traversal attempts that escape the
worktree, and defaults to repo root when context is empty.
></pre>
>
><a
href='https://github.com/myk-org/github-webhook-server/pull/1110/files#diff-beb446b71d75b7a427d17e48e75971c270de4820cb9786a12af9e4f988887269'>webhook_server/tests/test_runner_handler.py</a>
<hr/>
</details>
</blockquote>
</details>
<details>
<summary><strong>Documentation</strong> (1)</summary>
<blockquote>
<details>
<summary><strong>config.yaml</strong> <code>Document optional container
build context setting</code> <code>+1/-0</code></summary>
<br/>
>Document optional container build context setting
>
><pre>
>• Adds an example/commented 'context' key under
'container' to demonstrate building from a subdirectory
instead of repo root.
></pre>
>
><a
href='https://github.com/myk-org/github-webhook-server/pull/1110/files#diff-e3ac27ce128a0ddae53723bc8c3133257530a13c00f97c9edfeef152ebc3b8ce'>examples/config.yaml</a>
<hr/>
</details>
</blockquote>
</details>
<details>
<summary><strong>Other</strong> (1)</summary>
<blockquote>
<details>
<summary><strong>schema.yaml</strong> <code>Add
'container.context' to configuration schema with input
constraints</code> <code>+8/-0</code></summary>
<br/>
>Add 'container.context' to configuration schema with input
constraints
>
><pre>
>• Introduces a 'context' string option under
'container' with a conservative allowed-character pattern and
a default of empty string (repo root).
></pre>
>
><a
href='https://github.com/myk-org/github-webhook-server/pull/1110/files#diff-0eaf85d7f2a5888c61710a31c06434f63fe254f177f3df114332204780388f67'>webhook_server/config/schema.yaml</a>
<hr/>
</details>
</blockquote>
</details>
<img
src="https://www.qodo.ai/wp-content/uploads/2025/11/light-grey-line.svg"
height="10%" alt="Grey Divider">
<a href="https://www.qodo.ai"><img
src="https://www.qodo.ai/wp-content/uploads/2025/03/qodo-logo.svg"
width="80" alt="Qodo Logo"></a>1 parent 23028c4 commit d5390cc
8 files changed
Lines changed: 262 additions & 30 deletions
File tree
- examples
- webhook_server
- config
- libs
- handlers
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
175 | 175 | | |
176 | 176 | | |
177 | 177 | | |
| 178 | + | |
178 | 179 | | |
179 | 180 | | |
180 | 181 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
392 | 392 | | |
393 | 393 | | |
394 | 394 | | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
395 | 403 | | |
396 | 404 | | |
397 | 405 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
818 | 818 | | |
819 | 819 | | |
820 | 820 | | |
| 821 | + | |
821 | 822 | | |
822 | 823 | | |
823 | 824 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
| |||
202 | 203 | | |
203 | 204 | | |
204 | 205 | | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
205 | 227 | | |
206 | 228 | | |
207 | 229 | | |
208 | 230 | | |
209 | 231 | | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
210 | 236 | | |
211 | 237 | | |
212 | 238 | | |
213 | 239 | | |
214 | 240 | | |
215 | 241 | | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
216 | 257 | | |
217 | 258 | | |
218 | 259 | | |
| |||
241 | 282 | | |
242 | 283 | | |
243 | 284 | | |
244 | | - | |
245 | | - | |
246 | | - | |
247 | | - | |
248 | | - | |
249 | | - | |
250 | | - | |
251 | | - | |
252 | | - | |
253 | | - | |
254 | | - | |
255 | | - | |
256 | | - | |
257 | | - | |
258 | | - | |
259 | | - | |
260 | | - | |
261 | | - | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
262 | 288 | | |
263 | 289 | | |
264 | 290 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
395 | 395 | | |
396 | 396 | | |
397 | 397 | | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
398 | 410 | | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
399 | 430 | | |
400 | 431 | | |
401 | 432 | | |
402 | | - | |
| 433 | + | |
403 | 434 | | |
404 | 435 | | |
405 | 436 | | |
| |||
419 | 450 | | |
420 | 451 | | |
421 | 452 | | |
422 | | - | |
423 | | - | |
424 | | - | |
425 | | - | |
426 | | - | |
427 | | - | |
428 | | - | |
429 | | - | |
430 | | - | |
431 | | - | |
432 | | - | |
433 | 453 | | |
434 | 454 | | |
435 | 455 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
455 | 455 | | |
456 | 456 | | |
457 | 457 | | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
458 | 511 | | |
459 | 512 | | |
460 | 513 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
| |||
29 | 30 | | |
30 | 31 | | |
31 | 32 | | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
32 | 59 | | |
33 | 60 | | |
34 | 61 | | |
| |||
0 commit comments