Skip to content

feat(container): add static curl - #83

Merged
IceCodeNew merged 1 commit into
masterfrom
codex/add-static-curl
Jul 21, 2026
Merged

feat(container): add static curl#83
IceCodeNew merged 1 commit into
masterfrom
codex/add-static-curl

Conversation

@IceCodeNew

@IceCodeNew IceCodeNew commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Summary

  • add static-curl 8.21.0 for amd64 and arm64 without a musl runtime
  • cache release archives by architecture and CURL_VERSION with actions/cache v6.1.0
  • let Renovate update CURL_VERSION through inline GitHub releases metadata
  • extract the local archive in an isolated ADD --link stage and copy only curl into the final image
  • extend smoke tests to verify curl, UID 65532, the existing CLI, and absence of PT_INTERP

Verification

  • prek run --all-files
  • full pytest branch coverage suite: 817 passed; line 99.85%, branch 99.50%
  • local linux/amd64 and linux/arm64 image builds
  • curl --version, application --help, UID 65532, no musl runtime files, and no PT_INTERP on both architectures

Summary by CodeRabbit

  • New Features

    • Container images now include a fixed-version, statically linked curl utility.
    • The bundled utility is available at /usr/bin/curl.
  • Bug Fixes

    • Improved image validation confirms the expected curl version, static linking, and non-root runtime execution.
  • Documentation

    • Updated image build and publishing documentation to describe the bundled curl utility.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@IceCodeNew, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 42 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4bc76660-dc4b-48b8-b626-ee273d43f1cc

📥 Commits

Reviewing files that changed from the base of the PR and between 01e4b18 and 8cde0f4.

📒 Files selected for processing (2)
  • .github/workflows/image.yml
  • Dockerfile
📝 Walkthrough

Walkthrough

The image workflow now installs a fixed-version static curl binary, provides it to Docker through a named build context, embeds it in the runtime image, and smoke-tests its user ID, version, and static linking.

Changes

Static curl image integration

Layer / File(s) Summary
Static curl build context wiring
.github/workflows/image.yml, .gitignore, docs/design.md
The workflow installs and stages the configured static-curl binary, passes it to Docker as a build context, ignores the staging directory, and documents the build process.
Docker runtime embedding and smoke validation
Dockerfile, .github/workflows/image.yml
The runtime image copies static curl to /usr/bin/curl; smoke tests verify UID 65532, the expected version, and the absence of an INTERP entry.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant MiseAction
  participant DockerBuild
  participant RuntimeImage
  participant SmokeTest
  GitHubActions->>MiseAction: install configured static-curl
  MiseAction-->>GitHubActions: provide curl binary
  GitHubActions->>DockerBuild: pass static-curl build context
  DockerBuild->>RuntimeImage: copy curl to /usr/bin/curl
  SmokeTest->>RuntimeImage: check user, version, and static linking
  RuntimeImage-->>SmokeTest: return validation results
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding a static curl binary to the container image.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/add-static-curl

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add pinned static curl to distroless image with cached, verified downloads

✨ Enhancement ⚙️ Configuration changes 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Bundle pinned static-curl 8.21.0 (musl) into the final distroless image.
• Cache and SHA-256 verify per-arch archives in CI before Docker builds.
• Extend image smoke tests to validate curl, nonroot UID, and no dynamic loader.
Diagram

graph TD
  CI["GitHub Actions workflow"] --> Cache[("Static-curl cache")] --> Archive[".build/static-curl.tar.xz"] --> DF["Dockerfile (ADD/COPY)"] --> Build["Buildx build"] --> Image["Final distroless image"] --> Smoke["Smoke tests"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Install curl from distro packages in a builder stage, then copy binary
  • ➕ No dependency on third-party static-curl release artifacts
  • ➕ Can rely on distro CVE patching cadence
  • ➖ Likely pulls in dynamic loader/glibc/more runtime dependencies unless carefully copied
  • ➖ Harder to guarantee distroless compatibility and 'no PT_INTERP' property
2. Build curl from source as part of the Docker build
  • ➕ Full control over compile flags (static, PIE, features)
  • ➕ Can vendor/verify source tarballs and toolchain versions
  • ➖ Significantly longer build times and more complex toolchain setup
  • ➖ Higher maintenance burden for multi-arch reproducibility
3. Keep runtime image minimal; use a separate debug/ops image for curl-based diagnostics
  • ➕ Strictly minimal production image; reduced attack surface
  • ➕ Avoids embedding diagnostic tooling in runtime
  • ➖ Worsens operational UX for in-container connectivity debugging
  • ➖ Requires extra workflows/docs for attaching the debug image

Recommendation: Keep the PR’s approach: embedding a pinned, verified, fully static curl is a good fit for distroless while preserving a minimal runtime boundary (copy only /curl) and adding strong validation (SHA-256 + PT_INTERP checks). The main thing to watch is ongoing upgrade discipline (update version + per-arch SHA together) and monitoring upstream artifact provenance.

Files changed (7) +60 / -6

Enhancement (1) +3 / -0
DockerfileAdd scratch stage to extract static-curl and copy curl into runtime image +3/-0

Add scratch stage to extract static-curl and copy curl into runtime image

• Adds a scratch build stage that ADDs the pre-downloaded static-curl tar.xz with --link, then copies only the /curl binary into /usr/bin/curl in the distroless runtime stage.

Dockerfile

Documentation (3) +10 / -0
README.mdDocument that the official image includes curl for in-container diagnostics +2/-0

Document that the official image includes curl for in-container diagnostics

• Notes that the official container image now includes curl for validating third-party API connectivity and request parameters from inside the container.

README.md

design.mdDesign doc: describe static-curl provenance, caching, and verification strategy +2/-0

Design doc: describe static-curl provenance, caching, and verification strategy

• Documents the pinned static-curl musl artifact approach, per-arch caching in CI, SHA-256 verification, and the Dockerfile layering strategy using a local archive.

docs/design.md

notes.mdOperational note: enforce 'no musl runtime' and validate no dynamic loader +6/-0

Operational note: enforce 'no musl runtime' and validate no dynamic loader

• Adds rationale and constraints for using a static PIE curl without a dynamic loader, and describes the CI checks that enforce curl --version and absence of PT_INTERP during upgrades.

docs/notes.md

Other (3) +47 / -6
.dockerignoreAllow static-curl build artifact to be sent to Docker build context +1/-0

Allow static-curl build artifact to be sent to Docker build context

• Adds an exception for .build/static-curl.tar.xz so the cached/downloaded archive is available to Docker builds even with a blanket ignore rule.

.dockerignore

image.ymlCache, verify, and test static-curl in multi-arch image workflow +45/-6

Cache, verify, and test static-curl in multi-arch image workflow

• Introduces STATIC_CURL_VERSION and per-arch SHA-256 values, caches the tarball by (arch, version, sha), downloads on cache miss, and verifies the digest before building. Extends smoke tests to validate nonroot UID 65532, curl version output, and that the curl binary lacks a PT_INTERP (dynamic loader) program header.

.github/workflows/image.yml

.gitignoreIgnore local .build directory used for cached artifacts +1/-0

Ignore local .build directory used for cached artifacts

• Adds .build/ to gitignore to avoid committing CI/local build artifacts used for static-curl caching.

.gitignore

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Around line 133-134: Update the curl troubleshooting guidance in README.md to
warn that request parameters may contain credentials, private URLs, or user
data. Instruct operators to use sanitized examples and avoid exposing secrets
through shell history, process listings, terminal output, or logs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: de62e536-9881-4860-8d1a-0e7fab096e95

📥 Commits

Reviewing files that changed from the base of the PR and between f9062e6 and 9b6c002.

📒 Files selected for processing (7)
  • .dockerignore
  • .github/workflows/image.yml
  • .gitignore
  • Dockerfile
  • README.md
  • docs/design.md
  • docs/notes.md

Comment thread README.md Outdated
@qodo-code-review

qodo-code-review Bot commented Jul 21, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 39 rules

Grey Divider


Action required

1. Curl tarball ignored ✓ Resolved 🐞 Bug ☼ Reliability
Description
Dockerfile now unconditionally runs ADD --link .build/static-curl.tar.xz /, but .dockerignore
starts with ** and only negates the file path (not the parent .build/ directory), so the tarball
can remain excluded from the build context and cause the ADD step to fail.
Code

.dockerignore[R1-3]

**
!README.md
+!.build/static-curl.tar.xz
Relevance

⭐⭐ Medium

No prior reviews about .dockerignore negation/parent-dir inclusion; .dockerignore appears newly
added in this PR.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The build context is whitelisted via .dockerignore (** + negations). Dockerfile requires
.build/static-curl.tar.xz from the context, and the workflow populates that file under .build/,
but .dockerignore does not re-include .build/ itself, which can prevent the tarball from being
sent to the builder.

.dockerignore[1-7]
Dockerfile[3-10]
.github/workflows/image.yml[42-65]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The Docker build context is likely excluding `.build/static-curl.tar.xz` because `.dockerignore` ignores everything (`**`) and only un-ignores the file path, not the parent directory. When a parent directory is ignored, Docker ignore processing cannot reliably re-include only a child file, so `ADD --link .build/static-curl.tar.xz /` can fail with a missing-file error.

### Issue Context
The workflow downloads/restores the archive into `.build/static-curl.tar.xz`, and the Dockerfile expects it to be present in the build context.

### Fix Focus Areas
- .dockerignore[1-7]
- Dockerfile[3-10]

### Suggested change
Update `.dockerignore` to explicitly re-include the parent directory before the file, e.g.:
```dockerignore
**
!.build/
!.build/static-curl.tar.xz
...
```
(Keeping the existing whitelist approach intact.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. static-curl note missing justification ✓ Resolved 📘 Rule violation ⌂ Architecture
Description
The new docs/notes.md entry describes a technical choice but does not explicitly state the
assumption/constraint and why it is acceptable now, as required for revisitable notes. This reduces
future maintainability because readers cannot evaluate when/why the choice was made or whether it
remains valid.
Code

docs/notes.md[R7-11]

+## static-curl 不携带 musl 运行时
+
+固定版本的 static-curl 发布产物是 static PIE,没有动态加载器。最终镜像只复制 `curl` 二进制,不增加 musl 运行时。
+
+镜像工作流会在两个目标架构上执行 `curl --version`,并检查二进制没有 `PT_INTERP`。升级 static-curl 时如果产物需要动态加载器,必须先设计并验证新的运行时边界。
Relevance

⭐⭐⭐ High

History shows reviewers push for explicit assumptions/boundaries + reevaluation triggers in
docs/notes.md entries.

PR-#54
PR-#63

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2141673 requires each docs/notes.md entry to explicitly include an
assumption/constraint, justification, and revisit condition. The added static-curl section states
the approach and includes a revisit scenario, but it does not explicitly state the
assumption/constraint and why it is acceptable now.

Rule 2141673: Constrain docs/notes.md entries to documented, revisitable assumptions
Rule 2141676: Document assumptions and review triggers in docs/notes.md entries
docs/notes.md[7-12]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The newly added `static-curl` note does not explicitly include all required elements: an assumption/constraint, a justification for why it is acceptable now, and a clear revisit condition.

## Issue Context
Compliance requires each touched `docs/notes.md` entry to be written as a documented, revisitable assumption/constraint with explicit justification and a concrete trigger for re-evaluation.

## Fix Focus Areas
- docs/notes.md[7-12]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread docs/notes.md Outdated
Comment thread .dockerignore
@IceCodeNew
IceCodeNew force-pushed the codex/add-static-curl branch from 5cc8459 to 01e4b18 Compare July 21, 2026 11:14
@IceCodeNew
IceCodeNew force-pushed the codex/add-static-curl branch from 01e4b18 to 8cde0f4 Compare July 21, 2026 11:32
@IceCodeNew
IceCodeNew merged commit 042511d into master Jul 21, 2026
6 of 7 checks passed
@IceCodeNew
IceCodeNew deleted the codex/add-static-curl branch July 21, 2026 11:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant