feat(api): add Envied API config and Dio/Retrofit client scaffold#8
feat(api): add Envied API config and Dio/Retrofit client scaffold#8
Conversation
📝 WalkthroughWalkthroughAdds CI and Docker steps to write API_URL into a .env during build, introduces Envied-based runtime environment access, a centralized ApiPaths, a Retrofit ApiClient scaffold, and registers Dio + ApiClient in DI; also adds envied packages and updates CHANGELOG. Changes
Sequence Diagram(s)sequenceDiagram
participant CI as CI Workflow
participant Builder as Docker Build
participant Image as App Image
participant App as Dart App (runtime)
participant API as External API
CI->>Builder: provide `API_URL` secret (analyze job & build)
Builder->>Builder: write `/run/secrets/api_url` -> create `.env` in image
Builder->>Image: produce container image with .env
Image->>App: start runtime (Env reads generated config)
App->>App: Env.apiUrl -> ApiPaths.baseUrl
App->>App: DI provides Dio configured with baseUrl -> ApiClient
App->>API: ApiClient makes HTTP request to baseUrl (External API)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
.github/workflows/main.yml (1)
37-39: Fail fast whenAPI_URLis missing in CI.If the secret isn’t available (e.g., forked PRs), the
.envfile is created empty and the build fails later with a vague error. Add an explicit check to make failures clear and immediate.🔧 Suggested guard
- - name: Create .env file - run: echo "API_URL=${{ secrets.API_URL }}" > .env + - name: Create .env file + run: | + if [ -z "${{ secrets.API_URL }}" ]; then + echo "API_URL secret is missing" >&2 + exit 1 + fi + printf 'API_URL=%s\n' "${{ secrets.API_URL }}" > .env🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/main.yml around lines 37 - 39, The "Create .env file" CI step writes API_URL directly from the secret without verifying it's present; change that step to validate that the secret (secrets.API_URL) is non-empty and fail fast with a clear error if missing, then only write the .env file when present. Concretely, update the step's run script to check the value of secrets.API_URL (the API_URL secret), emit a descriptive error and exit non‑zero when empty, otherwise write "API_URL=..." into .env; keep the step name "Create .env file" so reviewers can find it.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@Dockerfile`:
- Line 9: The Dockerfile currently declares a build-arg "ARG API_URL" which can
leak sensitive values into image history; remove this ARG and switch to BuildKit
secrets: accept no API_URL build-arg, instead read the secret at build time
(e.g., via RUN --mount=type=secret,id=api_url) and write it into the generated
.env or required config file inside the image (use the secret content to create
the .env in the same stage where API_URL was needed); also update the CI
workflow/action that performs docker buildx to pass the secret via the buildx
"secrets" option (map the secret name "api_url" to the repository secret) so the
secret is never passed as a build-arg or embedded in image history.
In `@lib/api/service/api_client.dart`:
- Around line 6-10: The factory constructor for ApiClient declares an optional
named parameter baseUrl as non-nullable which violates Dart 3.10 null-safety;
change the factory signature in ApiClient so the named parameter is nullable
(e.g., make baseUrl a String?) or give it a default value so it is always
non-null; update the factory declaration (factory ApiClient(Dio dio, {String?
baseUrl} = _ApiClient;) — locate the ApiClient factory in the abstract class and
adjust the baseUrl parameter to be nullable (String?) or provide a sensible
default to fix the null-safety violation and match call sites like
ApiClient(di<Dio>()).
---
Nitpick comments:
In @.github/workflows/main.yml:
- Around line 37-39: The "Create .env file" CI step writes API_URL directly from
the secret without verifying it's present; change that step to validate that the
secret (secrets.API_URL) is non-empty and fail fast with a clear error if
missing, then only write the .env file when present. Concretely, update the
step's run script to check the value of secrets.API_URL (the API_URL secret),
emit a descriptive error and exit non‑zero when empty, otherwise write
"API_URL=..." into .env; keep the step name "Create .env file" so reviewers can
find it.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Dockerfile (1)
159-191:⚠️ Potential issue | 🟠 MajorAvoid running the runtime image as root.
The runtime stage never drops privileges, which is a security posture gap. Add a non-root user and ensure
/artifactsis owned by it.🔐 Suggested fix
FROM alpine:latest AS runtime @@ -# Create directory for APKs -RUN mkdir -p /artifacts +# Create non-root user and directory for APKs +RUN addgroup -S app && adduser -S app -G app && \ + mkdir -p /artifacts @@ -# Copy built APKs from builder stage -COPY --from=builder /app/build/app/outputs/flutter-apk/*.apk /artifacts/ +# Copy built APKs from builder stage +COPY --from=builder --chown=app:app /app/build/app/outputs/flutter-apk/*.apk /artifacts/ @@ # Set working directory WORKDIR /artifacts + +# Drop privileges +USER app🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Dockerfile` around lines 159 - 191, The runtime stage runs as root; create a non-root user and group (e.g., appuser/appgroup) in the runtime stage, chown /artifacts to that user after creating the directory or after copying the APKs from the builder stage, and switch to that user with the USER directive before the WORKDIR/CMD so the container never runs as root; update references in this Dockerfile runtime stage (COPY --from=builder, /artifacts, WORKDIR, CMD) accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@Dockerfile`:
- Around line 159-191: The runtime stage runs as root; create a non-root user
and group (e.g., appuser/appgroup) in the runtime stage, chown /artifacts to
that user after creating the directory or after copying the APKs from the
builder stage, and switch to that user with the USER directive before the
WORKDIR/CMD so the container never runs as root; update references in this
Dockerfile runtime stage (COPY --from=builder, /artifacts, WORKDIR, CMD)
accordingly.
🚀 Summary
Introduces the API client foundation for the next auth work: environment-based API configuration (
Envied) + baseline Dio/Retrofit wiring in DI, with CI/Docker support to injectAPI_URLduring codegen/build.✨ Changes
API_URL) using Envied.API_URLduring code generation (GitHub secret + Docker BuildKit secret), so builds work the same outside local machines.API_URLin GitHub Secrets for code generation/build jobs..envfile withAPI_URL.🧪 Verification
flutter pub getdart run build_runner build --delete-conflicting-outputsflutter analyzeflutter test