Skip to content

Conversation

@Cesarucho
Copy link

@Cesarucho Cesarucho commented Dec 19, 2025

#15

Introduces the devcontainer and Taskfile automation so contributors get a reproducible VS Code environment and can build binaries for each supported platform without manual setup.

Automation and reproducible workspace
  • Added the .devcontainer/ directory with VS Code settings, recommended extensions, and tooling (Go SDK, Task CLI, packaging tools) so everyone starts with the same environment.
  • Extended Taskfile.yml with tasks for cleaning (task clean), local builds (task build), and multi-platform releases (task release) that leverage goreleaser and the project’s configured variables.
  • Documented the prerequisites and steps to prepare the workspace before running the tasks (install Task CLI, refresh Go modules, etc.).
Commits
  • c080bdc feat: add DevContainer and Taskfile for release automation
  • c080bdc feat: add DevContainer and Taskfile for release automation

Testing:

Not run (configuration-only change).
please execute task clean and task release in the container/host to validate, for it u can install Task CLI or use the devcontainer terminal, then run:

task clean           # remove previous artifacts
task release         # builds linux/darwin/windows binaries
Example
vscode ➜ /workspaces/api-cli (main) $ task clean
task: [clean] rm -rf ${DIST_DIR}
vscode ➜ /workspaces/api-cli (main) $ task release
task: [ensure] go mod download
task: [ensure] go mod download
task: [ensure] go mod download
task: [ensure] go mod download
task: [ensure] go mod download
task: [ensure] go mod download
task: [ensure] go mod download
task: [ensure] go mod download
task: [build.linux-arm64] mkdir -p ${DIST_DIR}/linux-arm64
task: [build.windows-arm64] mkdir -p ${DIST_DIR}/windows-arm64
task: [build.windows-386] mkdir -p ${DIST_DIR}/windows-386
task: [build.linux-386] mkdir -p ${DIST_DIR}/linux-386
task: [build.darwin-arm64] mkdir -p ${DIST_DIR}/darwin-arm64
task: [build.darwin-amd64] mkdir -p ${DIST_DIR}/darwin-amd64
task: [build.windows-amd64] mkdir -p ${DIST_DIR}/windows-amd64
task: [build.linux-amd64] mkdir -p ${DIST_DIR}/linux-amd64
task: [build.darwin-arm64] GOOS=darwin GOARCH=arm64 go build -ldflags="${LDFLAGS}" -o ${DIST_DIR}/darwin-arm64/${BINARY} main.go
task: [build.linux-386] GOOS=linux GOARCH=386 go build -ldflags="${LDFLAGS}" -o ${DIST_DIR}/linux-386/${BINARY} main.go
task: [build.darwin-amd64] GOOS=darwin GOARCH=amd64 go build -ldflags="${LDFLAGS}" -o ${DIST_DIR}/darwin-amd64/${BINARY} main.go
task: [build.windows-386] GOOS=windows GOARCH=386 go build -ldflags="${LDFLAGS}" -o ${DIST_DIR}/windows-386/${BINARY}.exe main.go
task: [build.windows-amd64] GOOS=windows GOARCH=amd64 go build -ldflags="${LDFLAGS}" -o ${DIST_DIR}/windows-amd64/${BINARY}.exe main.go
task: [build.linux-arm64] GOOS=linux GOARCH=arm64 go build -ldflags="${LDFLAGS}" -o ${DIST_DIR}/linux-arm64/${BINARY} main.go
task: [build.linux-amd64] GOOS=linux GOARCH=amd64 go build -ldflags="${LDFLAGS}" -o ${DIST_DIR}/linux-amd64/${BINARY} main.go
task: [build.windows-arm64] GOOS=windows GOARCH=arm64 go build -ldflags="${LDFLAGS}" -o ${DIST_DIR}/windows-arm64/${BINARY}.exe main.go
task: [package.windows-arm64] sh -c 'version=$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD); tar czf ${DIST_DIR}/${BINARY}-$version-windows-arm64.tar.gz -C ${DIST_DIR}/windows-arm64 ${BINARY}.exe'
task: [package.windows-386] sh -c 'version=$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD); tar czf ${DIST_DIR}/${BINARY}-$version-windows-386.tar.gz -C ${DIST_DIR}/windows-386 ${BINARY}.exe'
task: [package.windows-amd64] sh -c 'version=$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD); tar czf ${DIST_DIR}/${BINARY}-$version-windows-amd64.tar.gz -C ${DIST_DIR}/windows-amd64 ${BINARY}.exe'
task: [package.linux-386] sh -c 'version=$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD); tar czf ${DIST_DIR}/${BINARY}-$version-linux-386.tar.gz -C ${DIST_DIR}/linux-386 ${BINARY}'
task: [package.darwin-amd64] sh -c 'version=$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD); tar czf ${DIST_DIR}/${BINARY}-$version-darwin-amd64.tar.gz -C ${DIST_DIR}/darwin-amd64 ${BINARY}'
task: [package.linux-amd64] sh -c 'version=$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD); tar czf ${DIST_DIR}/${BINARY}-$version-linux-amd64.tar.gz -C ${DIST_DIR}/linux-amd64 ${BINARY}'
task: [package.darwin-arm64] sh -c 'version=$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD); tar czf ${DIST_DIR}/${BINARY}-$version-darwin-arm64.tar.gz -C ${DIST_DIR}/darwin-arm64 ${BINARY}'
task: [package.linux-arm64] sh -c 'version=$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD); tar czf ${DIST_DIR}/${BINARY}-$version-linux-arm64.tar.gz -C ${DIST_DIR}/linux-arm64 ${BINARY}'
task: [package.checksums] sh -c 'version=$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD); cd ${DIST_DIR}; sha256sum ${BINARY}-$version-*.tar.gz > ${BINARY}-$version-checksums.sha256'
vscode ➜ /workspaces/api-cli (main) $ tree ./dist/
./dist/
├── darwin-amd64
│   └── hapi
├── darwin-arm64
│   └── hapi
├── hapi-v0.1.12-checksums.sha256
├── hapi-v0.1.12-darwin-amd64.tar.gz
├── hapi-v0.1.12-darwin-arm64.tar.gz
├── hapi-v0.1.12-linux-386.tar.gz
├── hapi-v0.1.12-linux-amd64.tar.gz
├── hapi-v0.1.12-linux-arm64.tar.gz
├── hapi-v0.1.12-windows-386.tar.gz
├── hapi-v0.1.12-windows-amd64.tar.gz
├── hapi-v0.1.12-windows-arm64.tar.gz
├── linux-386
│   └── hapi
├── linux-amd64
│   └── hapi
├── linux-arm64
│   └── hapi
├── windows-386
│   └── hapi.exe
├── windows-amd64
│   └── hapi.exe
└── windows-arm64
    └── hapi.exe

9 directories, 17 files

Summary by CodeRabbit

  • Chores

    • Added a reproducible Go development environment with editor extensions, UI theming, persistent git/credential volumes, and automated post-setup provisioning.
    • Introduced a Task-based multi-platform build & release workflow with per-target builds, packaging, and checksum generation.
    • Expanded ignored file patterns to include build artifacts.
  • Documentation

    • Added "Building from source" guide with build/release steps and artifact locations.
    • Expanded shell auto-completion instructions and supported shells.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 19, 2025

📝 Walkthrough

Walkthrough

Adds a devcontainer and setup script for a Go dev environment, a Taskfile for cross-platform build/package workflows, README updates for building and shell completion, and expands .gitignore to include bin/ and dist/.

Changes

Cohort / File(s) Change Summary
Dev container
.devcontainer/devcontainer.json, .devcontainer/setup.sh
New devcontainer configuration using mcr.microsoft.com/devcontainers/go:2-1.25-trixie, VS Code extensions and UI customizations, host-volume mounts for codex session and gitconfig, postCreateCommand runs .devcontainer/setup.sh. Setup script enforces strict shell flags, conditionally installs Task CLI, adjusts ownership/permissions, creates/symlinks gitconfig and git-credentials volumes, and marks the repo as a safe Git directory.
Build & release automation
Taskfile.yml
New Taskfile defining cross-platform build tasks (multiple GOOS/GOARCH targets), per-target packaging into tarballs, checksum generation (SHA256), and a release task that sequences builds → packages → checksums.
Docs & ignores
README.md, .gitignore
README adds "Building from source" instructions (Taskfile usage, devcontainer option, artifact locations) and expands shell auto-completion guidance; .gitignore updated to add bin/ and dist/.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review Taskfile.yml for GOOS/GOARCH correctness, output paths, ldflags usage, and task dependencies.
  • Inspect .devcontainer/setup.sh for ownership/permission safety, idempotence, and symlink handling when target files already exist.
  • Validate .devcontainer/devcontainer.json mounts, extension list, and postCreateCommand path.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately and clearly describes the main changes: adding devcontainer configuration and Taskfile workflow for multi-platform builds, which aligns with all modified files and the PR objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

@Cesarucho Cesarucho marked this pull request as ready for review December 19, 2025 19:56
@Cesarucho Cesarucho requested a review from a team as a code owner December 19, 2025 19:56
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (4)
.devcontainer/devcontainer.json (1)

9-13: Redundant Go feature.

The base image mcr.microsoft.com/devcontainers/go:2-1.25-trixie already includes the Go SDK. Adding ghcr.io/devcontainers/features/go:1 may cause version conflicts or is simply unnecessary overhead.

🔎 Proposed fix
     "features": {
-        "ghcr.io/devcontainers/features/go:1": {},
         "ghcr.io/guiyomh/features/golangci-lint:0": {},
         "ghcr.io/guiyomh/features/goreleaser:0": {}
     },
.devcontainer/setup.sh (1)

10-10: Potential failure if .codex directory doesn't exist.

If the volume mount hasn't created /home/vscode/.codex yet, this chown command will fail. Consider adding a directory creation guard.

🔎 Proposed fix
+mkdir -p /home/vscode/.codex
 sudo chown -R ${UID}:${UID} /home/vscode/.codex
Taskfile.yml (2)

32-87: Consider reducing duplication with Taskfile's dynamic features.

The build tasks share nearly identical structure. Taskfile supports for loops or dynamic task generation that could consolidate these into a single parameterized task, improving maintainability.

This is optional since the current explicit approach is clear and functional.


3-6: Consider embedding version info in LDFLAGS.

Adding -X linker flags to embed version, commit, and build date into the binary helps with debugging and user support (e.g., hapi --version showing full build info).

🔎 Example enhancement
env:
  DIST_DIR: dist
  BINARY: hapi
  VERSION:
    sh: git describe --tags --abbrev=0 2>/dev/null || echo "dev"
  COMMIT:
    sh: git rev-parse --short HEAD
  LDFLAGS: -s -w -X main.version={{.VERSION}} -X main.commit={{.COMMIT}}

This requires corresponding variables in main.go to receive these values.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c5daf9a and c080bdc.

📒 Files selected for processing (5)
  • .devcontainer/devcontainer.json (1 hunks)
  • .devcontainer/setup.sh (1 hunks)
  • .gitignore (1 hunks)
  • README.md (2 hunks)
  • Taskfile.yml (1 hunks)
🔇 Additional comments (3)
.gitignore (1)

1-4: LGTM!

The additions of bin/ and dist/ correctly align with the new Taskfile-based build workflow, preventing build artifacts from being committed.

README.md (1)

48-72: Good documentation for the build workflow.

The new "Building from source" section clearly explains both the Taskfile approach and manual go build commands, with appropriate artifact locations documented.

.devcontainer/devcontainer.json (1)

6-6: The image tag 2-1.25-trixie is valid and current. Go 1.25.5 was released on December 2, 2025, making this a stable and appropriate choice for a dev container.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
Taskfile.yml (1)

118-134: Fix Windows package tasks to reference .exe files.

The Windows package tasks attempt to tar ${BINARY}, but the Windows build tasks output ${BINARY}.exe. This mismatch will cause tar to fail with "file not found" errors.

🔎 Proposed fix
   package.windows-386:
     desc: Package the Windows 386 binary into a tarball.
     deps: [build.windows-386]
     cmds:
-      - sh -c 'version=$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD); tar czf ${DIST_DIR}/${BINARY}-$version-windows-386.tar.gz -C ${DIST_DIR}/windows-386 ${BINARY}'
+      - sh -c 'version=$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD); tar czf ${DIST_DIR}/${BINARY}-$version-windows-386.tar.gz -C ${DIST_DIR}/windows-386 ${BINARY}.exe'

   package.windows-amd64:
     desc: Package the Windows amd64 binary into a tarball.
     deps: [build.windows-amd64]
     cmds:
-      - sh -c 'version=$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD); tar czf ${DIST_DIR}/${BINARY}-$version-windows-amd64.tar.gz -C ${DIST_DIR}/windows-amd64 ${BINARY}'
+      - sh -c 'version=$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD); tar czf ${DIST_DIR}/${BINARY}-$version-windows-amd64.tar.gz -C ${DIST_DIR}/windows-amd64 ${BINARY}.exe'

   package.windows-arm64:
     desc: Package the Windows arm64 binary into a tarball.
     deps: [build.windows-arm64]
     cmds:
-      - sh -c 'version=$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD); tar czf ${DIST_DIR}/${BINARY}-$version-windows-arm64.tar.gz -C ${DIST_DIR}/windows-arm64 ${BINARY}'
+      - sh -c 'version=$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD); tar czf ${DIST_DIR}/${BINARY}-$version-windows-arm64.tar.gz -C ${DIST_DIR}/windows-arm64 ${BINARY}.exe'
🧹 Nitpick comments (2)
.devcontainer/setup.sh (2)

10-10: Verify .codex directory exists or add defensive check.

The script assumes ${HOME}/.codex exists before changing ownership. If this directory is not guaranteed to exist (via volume mount or prior creation), the command will fail and halt the script due to set -e.

Consider adding a defensive check:

+mkdir -p ${HOME}/.codex
 sudo chown -R ${UID}:${UID} ${HOME}/.codex

10-10: Consider fallback for ${UID} variable.

The ${UID} variable may not be set in all container environments. While it's typically available in Bash, consider using $(id -u):$(id -g) for better portability.

🔎 Proposed refactor

Add at the top of the script after line 2:

 set -euo pipefail
+UID="${UID:-$(id -u)}"
+GID="${GID:-$(id -g)}"

Then update the chown commands to use ${UID}:${GID} or keep as-is if you prefer.

Also applies to: 13-13, 19-19, 23-23, 27-27

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c080bdc and 601662d.

📒 Files selected for processing (4)
  • .devcontainer/devcontainer.json (1 hunks)
  • .devcontainer/setup.sh (1 hunks)
  • README.md (2 hunks)
  • Taskfile.yml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • README.md
  • .devcontainer/devcontainer.json
🔇 Additional comments (8)
.devcontainer/setup.sh (2)

1-8: LGTM! Previous issue resolved.

The shebang, strict mode flags, and Task CLI installation logic are correct. The -y flag is now present on line 7, resolving the previous concern about non-interactive hangs.


12-16: LGTM! Previous issue resolved.

The file permission logic now correctly preserves execute bits on shell scripts by excluding *.sh files from the 644 permission set and explicitly setting them to 755. This resolves the previous concern about breaking executable scripts.

Taskfile.yml (6)

1-6: LGTM!

The Taskfile version and environment variable definitions are correct. The LDFLAGS -s -w appropriately strips debug information for smaller release binaries.


8-30: LGTM!

The default, clean, ensure, and build tasks are well-structured with appropriate descriptions, dependencies, and commands.


32-66: LGTM!

The Linux and macOS build tasks correctly specify GOOS/GOARCH environment variables and output paths for their respective platforms.


67-86: LGTM! Previous issue resolved.

The Windows build tasks now correctly output binaries with the .exe extension (lines 72, 79, 86), resolving the previous concern about extensionless Windows binaries.


88-116: LGTM! Previous issue resolved.

The Linux and macOS package tasks correctly use the git describe fallback pattern and reference the correct binary names.


136-157: LGTM! Previous issue resolved.

The aggregate tasks (packages, checksums, release) are well-structured with proper dependency chains. The checksums task includes the git describe fallback, resolving the previous concern.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
.devcontainer/setup.sh (2)

18-27: LGTM!

The Git configuration setup now correctly creates .git-credentials as a file rather than a directory. Previous issue has been resolved.

Optional: Remove redundant -R flag on line 27

The -R flag on line 27 is unnecessary since .git-credentials is a file/symlink, not a directory:

-sudo chown -R ${UID}:${UID} ${HOME}/.git-credentials
+sudo chown ${UID}:${UID} ${HOME}/.git-credentials

29-29: Consider using --replace-all to prevent duplicate entries.

Using --add can create duplicate safe.directory entries if the container is rebuilt or this script runs multiple times. Consider using --replace-all to ensure a single entry.

🔎 Suggested improvement
-git config --global --add safe.directory ${PWD}
+git config --global --replace-all safe.directory ${PWD}

Alternatively, check before adding:

git config --global --get-all safe.directory | grep -qF "${PWD}" || \
  git config --global --add safe.directory ${PWD}
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 601662d and ba7749c.

📒 Files selected for processing (2)
  • .devcontainer/setup.sh (1 hunks)
  • Taskfile.yml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Taskfile.yml
🔇 Additional comments (4)
.devcontainer/setup.sh (4)

1-2: LGTM!

Excellent use of strict error handling with set -euo pipefail to catch errors early.


4-8: LGTM!

The Task CLI installation now includes the -y flag for non-interactive execution. Previous issue has been resolved.


10-10: Ensure .codex directory exists before chown.

The script will fail if ${HOME}/.codex doesn't exist (due to set -e). If this directory is not guaranteed to be created before this script runs, consider creating it first.

🔎 Suggested safeguard
+mkdir -p ${HOME}/.codex
 sudo chown -R ${UID}:${UID} ${HOME}/.codex

Please verify whether the devcontainer or another setup step creates .codex before this script executes.


12-16: LGTM!

The permission fixes now correctly preserve executable permissions on shell scripts while setting standard permissions on other files. Previous issue has been resolved.

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.

1 participant