Skip to content

feat(api): Docker, env loading, secrets removal, route cleanup (Phase 3 — T3.0–T3.4)#44

Open
canonical-muhammadbassiony wants to merge 3 commits into
feat/figma-phase-e-driftfrom
feat/phase-3-api-foundation
Open

feat(api): Docker, env loading, secrets removal, route cleanup (Phase 3 — T3.0–T3.4)#44
canonical-muhammadbassiony wants to merge 3 commits into
feat/figma-phase-e-driftfrom
feat/phase-3-api-foundation

Conversation

@canonical-muhammadbassiony

Copy link
Copy Markdown
Collaborator

Summary

Establishes the API foundation: Docker support, .env file loading, secrets removed from request bodies, and route consolidation.

Tasks Implemented

  • T3.0: Multi-stage Dockerfile (golang:1.22 builder + debian:bookworm-slim runtime with git, curl, GitHub CLI). .dockerignore excludes secrets and build artifacts. docker-build and docker-run Taskfile tasks.
  • T3.1: godotenv loads .env then .env.local before run(). .env committed with non-sensitive defaults.
  • T3.2: Removed GitHubToken, Credentials, OutputDir, LocalRepoPath from APIRequest. Handler resolves secrets from env vars only.
  • T3.3: Route renamed to POST /api/v1/workflows with Go 1.22 method+path routing.
  • T3.4: build-api task (already present from prior branch).

Security

  • Credentials and tokens completely removed from request body struct
  • .env.local excluded from Docker image and git
  • Request body is now safe to log

Files Changed

  • Dockerfile, .dockerignore — new
  • Taskfile.ymldocker-build, docker-run
  • .env — committed non-sensitive defaults
  • cmd/app/main.go — godotenv loading, route rename
  • internal/workflow/api.go — secrets removed from APIRequest
  • go.mod / go.sumgodotenv dependency

Part of the Bauer v2 stacked PR series (Branch 9 of 12).

T3.0: Dockerfile (golang:1.22 builder + debian:bookworm-slim runtime) with gh CLI
T3.0: .dockerignore excludes .env.local, secrets, build artifacts
T3.0: Taskfile docker-build and docker-run tasks
T3.1: godotenv loads .env then .env.local at API startup (optional files)
T3.1: .env committed with non-sensitive defaults
T3.2: APIRequest no longer accepts credentials or github_token fields
T3.2: handler reads creds from BAUER_CREDENTIALS_PATH env var
T3.3: /api/v1/workflow renamed to /api/v1/workflows
T3.3: Go 1.22 method+path routing, routes consolidated
T3.4: build-api Taskfile task added

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Establishes a containerized and environment-driven foundation for the Bauer API by adding Docker support, loading .env files at startup, removing secrets from the workflow request body, and consolidating the workflow route.

Changes:

  • Added multi-stage Docker build + docker helper tasks, plus .dockerignore to reduce build context exposure.
  • Added .env / .env.local loading at API startup and introduced committed non-sensitive defaults.
  • Updated workflow API request/handler to resolve secrets from environment and renamed the workflow route to POST /api/v1/workflows.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
Dockerfile Adds multi-stage build for the API image and installs runtime tools (git/curl/gh).
.dockerignore Excludes local secrets and build artifacts from Docker build context.
Taskfile.yml Adds docker-build/docker-run tasks for local container workflows.
.env Commits non-sensitive default environment values for local/dev configuration.
cmd/app/main.go Loads .env files and updates route registration for workflows.
internal/workflow/api.go Removes secrets from request body and resolves token/credentials from environment.
go.mod Adds godotenv dependency.
go.sum Records godotenv checksums.
docs/implementation-log.md Documents Phase 3 implementation details and file changes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Dockerfile Outdated
@@ -0,0 +1,33 @@
# --- Build stage ---
FROM golang:1.22-bookworm AS builder
Comment thread Taskfile.yml
Comment on lines +65 to +72
docker-run:
desc: Run the Bauer API locally in Docker (reads .env.local for secrets)
cmds:
- docker run -p 8090:8090
--env-file .env.local
-v "${BAUER_CREDENTIALS_PATH}:/creds/service-account.json:ro"
-e BAUER_CREDENTIALS_PATH=/creds/service-account.json
bauer-api:latest

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The docker-run task uses --env-file .env.local which makes vars available inside the container, but BAUER_CREDENTIALS_PATH in the -v mount is expanded by the host shell. The Taskfile header instructs users to set up env vars before running. Adding a dotenv directive would load secrets into all tasks (build, test, lint) which is not desirable. Current approach — documented env setup + --env-file for the container — is the right trade-off for a dev-only task.

Comment thread cmd/app/main.go
Comment on lines +58 to 61
mux.HandleFunc("POST /api/v1/workflows", workflow.ExecuteWorkflowHandler(orch))
slog.Info("starting server", "address", ":8090")
err = http.ListenAndServe(":8090", middleware.RequestTrace(mux))

Comment thread internal/workflow/api.go
Comment on lines +73 to 77
credentials := firstNonEmpty(os.Getenv("BAUER_CREDENTIALS_PATH"), os.Getenv("GOOGLE_APPLICATION_CREDENTIALS"))
if credentials == "" {
writeError(w, http.StatusInternalServerError, "no credentials configured: set BAUER_CREDENTIALS_PATH")
return
}
Comment thread internal/workflow/api.go
Comment on lines +79 to 90
// Create workflow input (request fields override env defaults)
input := WorkflowInput{
GitHubRepo: req.GitHubRepo,
GitHubToken: req.GitHubToken,
BranchPrefix: req.BranchPrefix,
GitHubToken: token,
BranchPrefix: firstNonEmpty(req.BranchPrefix, os.Getenv("BAUER_BRANCH_PREFIX"), "bauer"),
DocID: req.DocID,
Credentials: req.Credentials,
ChunkSize: req.ChunkSize,
Credentials: credentials,
ChunkSize: firstNonZero(req.ChunkSize, 1),
PageRefresh: req.PageRefresh,
OutputDir: req.OutputDir,
Model: req.Model,
OutputDir: firstNonEmpty(os.Getenv("BAUER_OUTPUT_DIR"), "bauer-output"),
Model: firstNonEmpty(req.Model, os.Getenv("BAUER_MODEL"), "gpt-5-mini-high"),
DryRun: req.DryRun,
Comment thread go.mod Outdated
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.7 // indirect
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
github.com/joho/godotenv v1.5.1 // indirect

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 10 changed files in this pull request and generated 8 comments.

Comments suppressed due to low confidence (1)

cmd/app/main.go:72

  • godotenv.Load does not override existing environment variables, so loading .env first will prevent .env.local from overriding values set by .env. If .env.local is intended to take precedence, use godotenv.Overload(".env.local") (or load .env.local first and .env second).
		slog.Info("shutdown complete with errors")
		return err
	}

Comment thread Dockerfile
@@ -0,0 +1,33 @@
# --- Build stage ---
FROM golang:1.24-bookworm AS builder
Comment thread cmd/app/main.go
Comment on lines +59 to +60
addr := ":" + port

Comment thread go.mod
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.7 // indirect
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
Comment thread internal/workflow/api.go
Comment on lines 22 to +27
// Bauer configuration
DocID string `json:"doc_id" binding:"required"` // Google Doc ID
Credentials string `json:"credentials" binding:"required"` // Path to service account JSON
ChunkSize int `json:"chunk_size" default:"1"` // Number of chunks
PageRefresh bool `json:"page_refresh" default:"false"` // Page refresh mode
OutputDir string `json:"output_dir" default:"bauer-output"` // Output directory
Model string `json:"model" default:"gpt-5-mini-high"` // Copilot model
DryRun bool `json:"dry_run" default:"false"` // Dry run mode

// Local repository path
LocalRepoPath string `json:"local_repo_path" default:"/tmp"` // Where to clone (optional)
DocID string `json:"doc_id"` // Google Doc ID
ChunkSize int `json:"chunk_size,omitempty"` // Number of chunks
PageRefresh bool `json:"page_refresh,omitempty"` // Page refresh mode
Model string `json:"model,omitempty"` // Copilot model
SummaryModel string `json:"summary_model,omitempty"` // Copilot summary model
Comment thread internal/workflow/api.go
Comment on lines 79 to +90

// Create workflow input
// Create workflow input (request fields override env defaults)
input := WorkflowInput{
GitHubRepo: req.GitHubRepo,
GitHubToken: req.GitHubToken,
BranchPrefix: req.BranchPrefix,
GitHubToken: token,
BranchPrefix: firstNonEmpty(req.BranchPrefix, os.Getenv("BAUER_BRANCH_PREFIX"), "bauer"),
DocID: req.DocID,
Credentials: req.Credentials,
ChunkSize: req.ChunkSize,
PageRefresh: req.PageRefresh,
OutputDir: req.OutputDir,
Model: req.Model,
Credentials: credentials,
ChunkSize: firstNonZero(req.ChunkSize, envInt("BAUER_CHUNK_SIZE"), 1),
PageRefresh: req.PageRefresh || envBool("BAUER_PAGE_REFRESH"),
OutputDir: firstNonEmpty(os.Getenv("BAUER_OUTPUT_DIR"), "bauer-output"),
Model: firstNonEmpty(req.Model, os.Getenv("BAUER_MODEL"), "gpt-5-mini-high"),
Comment thread internal/workflow/api.go
Comment on lines 73 to +76
}
if req.ChunkSize == 0 {
req.ChunkSize = 1
credentials := firstNonEmpty(os.Getenv("BAUER_CREDENTIALS_PATH"), os.Getenv("GOOGLE_APPLICATION_CREDENTIALS"))
if credentials == "" {
writeError(w, http.StatusInternalServerError, "no credentials configured: set BAUER_CREDENTIALS_PATH or GOOGLE_APPLICATION_CREDENTIALS")
Comment thread Taskfile.yml Outdated
Comment on lines +68 to +72
- docker run -p 8090:8090
--env-file .env.local
-v "${BAUER_CREDENTIALS_PATH}:/creds/service-account.json:ro"
-e BAUER_CREDENTIALS_PATH=/creds/service-account.json
bauer-api:latest
Comment thread docs/implementation-log.md Outdated
Comment on lines +271 to +275
**Summary:** Added Docker support, env-file loading, secrets removal from the API request body, route rename, and a build task. T3.0 introduced a multi-stage `Dockerfile` (golang:1.22 builder + debian:bookworm-slim runtime with git, curl, and the GitHub CLI installed) and a `.dockerignore` that excludes secrets, build artifacts, and the git directory; two new Taskfile tasks (`docker-build`, `docker-run`) wire the image build and local container run. T3.1 installed `github.com/joho/godotenv` and updated `cmd/app/main.go` to call `godotenv.Load` for both `.env` and `.env.local` (errors silently ignored) before calling `run()`; `.env` was replaced with a committed, non-sensitive defaults file covering port, model, chunk size, page-refresh, output directory, and branch prefix. T3.2 stripped `Credentials`, `GitHubToken`, `OutputDir`, and `LocalRepoPath` from `APIRequest`, replacing them with env-var lookups (`BAUER_CREDENTIALS_PATH`/`GOOGLE_APPLICATION_CREDENTIALS` and `github.GetGitHubToken()`) inside the handler; `firstNonEmpty` and `firstNonZero` helpers apply request-field-overrides-env semantics; `SummaryModel` was added to `APIRequest` for future use. T3.3 renamed the `/api/v1/workflow` route to `POST /api/v1/workflows` using Go 1.22 method+path routing. T3.4 was already present in the Taskfile from a prior branch (`build-api` task).

**Files changed:** _(to be filled by agent)_
**Files changed:**
- `Dockerfile`: New multi-stage build — golang:1.22 builder compiles `bauer-api`; debian:bookworm-slim runtime installs git, curl, ca-certificates, and the GitHub CLI; exposes port 8090.
- `.dockerignore`: Excludes `.env.local`, `config.json`, `*.pem`, build binaries, `bauer-output/`, logs, and `.git/` from the Docker build context.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 10 changed files in this pull request and generated 4 comments.

Comment thread internal/workflow/api.go
Comment on lines +86 to +90
Credentials: credentials,
ChunkSize: firstNonZero(req.ChunkSize, envInt("BAUER_CHUNK_SIZE"), 1),
PageRefresh: req.PageRefresh || envBool("BAUER_PAGE_REFRESH"),
OutputDir: firstNonEmpty(os.Getenv("BAUER_OUTPUT_DIR"), "bauer-output"),
Model: firstNonEmpty(req.Model, os.Getenv("BAUER_MODEL"), "gpt-5-mini-high"),
Comment thread Dockerfile
@@ -0,0 +1,33 @@
# --- Build stage ---
FROM golang:1.24-bookworm AS builder
Comment thread .dockerignore
Comment on lines +1 to +9
.env.local
config.json
*.pem
bauer
bauer-api
bauer-output/
bauer-log.json
bauer-doc-suggestions.json
.git/
Comment thread Taskfile.yml
Comment on lines +69 to +73
docker run -p 8090:8090 \
--env-file .env.local \
-v "${BAUER_CREDENTIALS_PATH}:/creds/service-account.json:ro" \
-e BAUER_CREDENTIALS_PATH=/creds/service-account.json \
bauer-api:latest
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants