-
Notifications
You must be signed in to change notification settings - Fork 5
feat: Add Docker support and GitHub Container Registry CI/CD #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| # Dependencies | ||
| node_modules/ | ||
| npm-debug.log* | ||
| yarn-debug.log* | ||
| yarn-error.log* | ||
|
|
||
| # Build artifacts | ||
| lib/ | ||
| *.tsbuildinfo | ||
|
|
||
| # Tests | ||
| tests/ | ||
| coverage/ | ||
| *.test.js | ||
| *.test.ts | ||
|
|
||
| # Documentation | ||
| docs/ | ||
| *.md | ||
| !README.md | ||
|
|
||
| # Git | ||
| .git/ | ||
| .gitignore | ||
| .gitattributes | ||
|
|
||
| # IDE | ||
| .vscode/ | ||
| .idea/ | ||
| *.swp | ||
| *.swo | ||
| *~ | ||
|
|
||
| # CI/CD | ||
| .github/ | ||
| .travis.yml | ||
| .gitlab-ci.yml | ||
|
|
||
| # Misc | ||
| .DS_Store | ||
| .env | ||
| .env.* | ||
| *.log | ||
| tmp/ | ||
| temp/ | ||
| .cache/ | ||
|
|
||
| # Claude Code specific (not needed in container) | ||
| .claude/ | ||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,102 @@ | ||||||||||
| name: Build and Push Docker Image to GHCR | ||||||||||
|
|
||||||||||
| on: | ||||||||||
| push: | ||||||||||
| branches: | ||||||||||
| - main | ||||||||||
| - master | ||||||||||
| - 'claude/**' | ||||||||||
| tags: | ||||||||||
| - 'v*' | ||||||||||
| pull_request: | ||||||||||
| branches: | ||||||||||
| - main | ||||||||||
| - master | ||||||||||
| workflow_dispatch: | ||||||||||
|
|
||||||||||
| env: | ||||||||||
| REGISTRY: ghcr.io | ||||||||||
| IMAGE_NAME: ${{ github.repository }} | ||||||||||
|
|
||||||||||
| jobs: | ||||||||||
| build-and-push: | ||||||||||
| runs-on: ubuntu-latest | ||||||||||
| permissions: | ||||||||||
| contents: read | ||||||||||
| packages: write | ||||||||||
| id-token: write | ||||||||||
|
|
||||||||||
| steps: | ||||||||||
| - name: Checkout repository | ||||||||||
| uses: actions/checkout@v4 | ||||||||||
|
|
||||||||||
| - name: Set up Docker Buildx | ||||||||||
| uses: docker/setup-buildx-action@v3 | ||||||||||
|
|
||||||||||
| - name: Log in to GitHub Container Registry | ||||||||||
| if: github.event_name != 'pull_request' | ||||||||||
| uses: docker/login-action@v3 | ||||||||||
| with: | ||||||||||
| registry: ${{ env.REGISTRY }} | ||||||||||
| username: ${{ github.actor }} | ||||||||||
| password: ${{ secrets.GITHUB_TOKEN }} | ||||||||||
|
|
||||||||||
| - name: Extract metadata (tags, labels) for Docker | ||||||||||
| id: meta | ||||||||||
| uses: docker/metadata-action@v5 | ||||||||||
| with: | ||||||||||
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | ||||||||||
| tags: | | ||||||||||
| # Tag with version for release tags | ||||||||||
| type=semver,pattern={{version}} | ||||||||||
| type=semver,pattern={{major}}.{{minor}} | ||||||||||
| type=semver,pattern={{major}} | ||||||||||
| # Tag with branch name | ||||||||||
| type=ref,event=branch | ||||||||||
| # Tag with PR number for pull requests | ||||||||||
| type=ref,event=pr | ||||||||||
| # Tag with 'latest' for main/master branch | ||||||||||
| type=raw,value=latest,enable={{is_default_branch}} | ||||||||||
| # Tag with git sha | ||||||||||
| type=sha,prefix={{branch}}- | ||||||||||
|
|
||||||||||
| - name: Build and push Docker image | ||||||||||
| uses: docker/build-push-action@v5 | ||||||||||
| with: | ||||||||||
| context: . | ||||||||||
| platforms: linux/amd64,linux/arm64 | ||||||||||
| push: ${{ github.event_name != 'pull_request' }} | ||||||||||
| tags: ${{ steps.meta.outputs.tags }} | ||||||||||
| labels: ${{ steps.meta.outputs.labels }} | ||||||||||
| cache-from: type=gha | ||||||||||
| cache-to: type=gha,mode=max | ||||||||||
| build-args: | | ||||||||||
| BUILD_DATE=${{ github.event.head_commit.timestamp }} | ||||||||||
| VCS_REF=${{ github.sha }} | ||||||||||
| VERSION=${{ steps.meta.outputs.version }} | ||||||||||
|
Comment on lines
+63
to
+76
|
||||||||||
|
|
||||||||||
|
Comment on lines
+73
to
+77
|
||||||||||
| build-args: | | |
| BUILD_DATE=${{ github.event.head_commit.timestamp }} | |
| VCS_REF=${{ github.sha }} | |
| VERSION=${{ steps.meta.outputs.version }} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| # Multi-stage build for flashbacker MCP server | ||
| # Stage 1: Build | ||
| FROM node:22-alpine AS builder | ||
|
|
||
| # Install build dependencies | ||
| RUN apk add --no-cache python3 make g++ git | ||
|
|
||
| # Set working directory | ||
| WORKDIR /app | ||
|
|
||
| # Copy package files | ||
| COPY package*.json ./ | ||
|
|
||
| # Install dependencies (including dev dependencies for build) | ||
| RUN npm ci | ||
|
|
||
| # Copy source code | ||
| COPY . . | ||
|
|
||
| # Build TypeScript and copy templates | ||
| RUN npm run build | ||
|
|
||
| # Stage 2: Runtime | ||
| FROM node:22-alpine | ||
|
|
||
| # Install runtime dependencies only | ||
| RUN apk add --no-cache git | ||
|
|
||
| # Set working directory | ||
| WORKDIR /app | ||
|
|
||
| # Copy package files | ||
| COPY package*.json ./ | ||
|
|
||
| # Install production dependencies only | ||
| RUN npm ci --only=production | ||
|
|
||
| # Copy built files from builder stage | ||
| COPY --from=builder /app/lib ./lib | ||
| COPY --from=builder /app/bin ./bin | ||
| COPY --from=builder /app/templates ./templates | ||
| COPY README.md ./ | ||
|
|
||
| # Create a non-root user | ||
| RUN addgroup -g 1001 flashback && \ | ||
| adduser -D -u 1001 -G flashback flashback && \ | ||
| chown -R flashback:flashback /app | ||
|
|
||
| # Switch to non-root user | ||
| USER flashback | ||
|
|
||
| # Make the CLI executable globally available | ||
| ENV PATH="/app/bin:${PATH}" | ||
|
|
||
| # Set up entrypoint | ||
| ENTRYPOINT ["node", "/app/lib/cli.js"] | ||
|
|
||
| # Default command (shows help) | ||
| CMD ["--help"] | ||
|
|
||
| # Labels for container metadata | ||
| LABEL org.opencontainers.image.title="Flashbacker" | ||
| LABEL org.opencontainers.image.description="Claude Code state management with session continuity and AI personas" | ||
| LABEL org.opencontainers.image.source="https://github.com/agentsea/flashbacker" | ||
| LABEL org.opencontainers.image.licenses="MIT" |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,59 @@ | ||||
| version: '3.8' | ||||
|
|
||||
|
Comment on lines
+1
to
+2
|
||||
| version: '3.8' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The
.dockerignorefile excludeslib/(line 8), but the Dockerfile's runtime stage copies the builtlibdirectory from the builder stage (line 39 in Dockerfile). Since the builder stage builds the project (line 21), this works correctly. However, excludinglib/here could be confusing since it's explicitly copied in the Dockerfile.Consider adding a comment to clarify: