memory-journal-mcp 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/.dockerignore +88 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +76 -0
  3. package/.github/ISSUE_TEMPLATE/config.yml +11 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +89 -0
  5. package/.github/ISSUE_TEMPLATE/question.md +63 -0
  6. package/.github/dependabot.yml +110 -0
  7. package/.github/pull_request_template.md +110 -0
  8. package/.github/workflows/DOCKER_DEPLOYMENT_SETUP.md +346 -0
  9. package/.github/workflows/codeql.yml +45 -0
  10. package/.github/workflows/dependabot-auto-merge.yml +42 -0
  11. package/.github/workflows/docker-publish.yml +277 -0
  12. package/.github/workflows/lint-and-test.yml +58 -0
  13. package/.github/workflows/publish-npm.yml +75 -0
  14. package/.github/workflows/secrets-scanning.yml +32 -0
  15. package/.github/workflows/security-update.yml +99 -0
  16. package/.memory-journal-team.db +0 -0
  17. package/.trivyignore +18 -0
  18. package/CHANGELOG.md +19 -0
  19. package/CODE_OF_CONDUCT.md +128 -0
  20. package/CONTRIBUTING.md +209 -0
  21. package/DOCKER_README.md +377 -0
  22. package/Dockerfile +64 -0
  23. package/LICENSE +21 -0
  24. package/README.md +461 -0
  25. package/SECURITY.md +200 -0
  26. package/VERSION +1 -0
  27. package/dist/cli.d.ts +5 -0
  28. package/dist/cli.d.ts.map +1 -0
  29. package/dist/cli.js +42 -0
  30. package/dist/cli.js.map +1 -0
  31. package/dist/constants/ServerInstructions.d.ts +8 -0
  32. package/dist/constants/ServerInstructions.d.ts.map +1 -0
  33. package/dist/constants/ServerInstructions.js +26 -0
  34. package/dist/constants/ServerInstructions.js.map +1 -0
  35. package/dist/database/SqliteAdapter.d.ts +198 -0
  36. package/dist/database/SqliteAdapter.d.ts.map +1 -0
  37. package/dist/database/SqliteAdapter.js +736 -0
  38. package/dist/database/SqliteAdapter.js.map +1 -0
  39. package/dist/filtering/ToolFilter.d.ts +63 -0
  40. package/dist/filtering/ToolFilter.d.ts.map +1 -0
  41. package/dist/filtering/ToolFilter.js +242 -0
  42. package/dist/filtering/ToolFilter.js.map +1 -0
  43. package/dist/github/GitHubIntegration.d.ts +91 -0
  44. package/dist/github/GitHubIntegration.d.ts.map +1 -0
  45. package/dist/github/GitHubIntegration.js +317 -0
  46. package/dist/github/GitHubIntegration.js.map +1 -0
  47. package/dist/handlers/prompts/index.d.ts +28 -0
  48. package/dist/handlers/prompts/index.d.ts.map +1 -0
  49. package/dist/handlers/prompts/index.js +366 -0
  50. package/dist/handlers/prompts/index.js.map +1 -0
  51. package/dist/handlers/resources/index.d.ts +27 -0
  52. package/dist/handlers/resources/index.d.ts.map +1 -0
  53. package/dist/handlers/resources/index.js +453 -0
  54. package/dist/handlers/resources/index.js.map +1 -0
  55. package/dist/handlers/tools/index.d.ts +26 -0
  56. package/dist/handlers/tools/index.d.ts.map +1 -0
  57. package/dist/handlers/tools/index.js +982 -0
  58. package/dist/handlers/tools/index.js.map +1 -0
  59. package/dist/index.d.ts +11 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +13 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/server/McpServer.d.ts +18 -0
  64. package/dist/server/McpServer.d.ts.map +1 -0
  65. package/dist/server/McpServer.js +171 -0
  66. package/dist/server/McpServer.js.map +1 -0
  67. package/dist/types/index.d.ts +300 -0
  68. package/dist/types/index.d.ts.map +1 -0
  69. package/dist/types/index.js +15 -0
  70. package/dist/types/index.js.map +1 -0
  71. package/dist/utils/McpLogger.d.ts +61 -0
  72. package/dist/utils/McpLogger.d.ts.map +1 -0
  73. package/dist/utils/McpLogger.js +113 -0
  74. package/dist/utils/McpLogger.js.map +1 -0
  75. package/dist/utils/logger.d.ts +30 -0
  76. package/dist/utils/logger.d.ts.map +1 -0
  77. package/dist/utils/logger.js +70 -0
  78. package/dist/utils/logger.js.map +1 -0
  79. package/dist/vector/VectorSearchManager.d.ts +63 -0
  80. package/dist/vector/VectorSearchManager.d.ts.map +1 -0
  81. package/dist/vector/VectorSearchManager.js +235 -0
  82. package/dist/vector/VectorSearchManager.js.map +1 -0
  83. package/docker-compose.yml +37 -0
  84. package/eslint.config.js +86 -0
  85. package/mcp-config-example.json +21 -0
  86. package/package.json +71 -0
  87. package/releases/release-notes-v2.2.0.md +165 -0
  88. package/releases/release-notes.md +214 -0
  89. package/releases/v3.0.0.md +236 -0
  90. package/server.json +42 -0
  91. package/src/cli.ts +52 -0
  92. package/src/constants/ServerInstructions.ts +25 -0
  93. package/src/database/SqliteAdapter.ts +952 -0
  94. package/src/filtering/ToolFilter.ts +271 -0
  95. package/src/github/GitHubIntegration.ts +409 -0
  96. package/src/handlers/prompts/index.ts +420 -0
  97. package/src/handlers/resources/index.ts +529 -0
  98. package/src/handlers/tools/index.ts +1081 -0
  99. package/src/index.ts +53 -0
  100. package/src/server/McpServer.ts +230 -0
  101. package/src/types/index.ts +435 -0
  102. package/src/types/sql.js.d.ts +34 -0
  103. package/src/utils/McpLogger.ts +155 -0
  104. package/src/utils/logger.ts +98 -0
  105. package/src/vector/VectorSearchManager.ts +277 -0
  106. package/tools.json +300 -0
  107. package/tsconfig.json +51 -0
@@ -0,0 +1,346 @@
1
+ # Docker Deployment Setup Guide
2
+
3
+ *Last Updated: December 8, 2025 - Production/Stable v2.2.0*
4
+
5
+ ## 🚀 Automated Docker Deployment
6
+
7
+ This repository is configured for **automatic Docker image deployment** to Docker Hub on every push to the `main` branch and on tagged releases.
8
+
9
+ ## 📋 Current Status
10
+
11
+ ### ✅ Production-Ready Deployment
12
+ - **Version**: v2.2.0 (Production/Stable)
13
+ - **Base Image**: `python:3.13-alpine` (Alpine Linux 3.22)
14
+ - **Docker Hub**: `writenotenow/memory-journal-mcp`
15
+ - **Image Size**: ~225MB (Alpine-based with full ML capabilities)
16
+ - **Platforms**: `linux/amd64`, `linux/arm64` (Apple Silicon support)
17
+
18
+ ### 🔒 Security Posture
19
+ - **OpenSSL**: 3.5.4-r0 (latest)
20
+ - **curl**: 8.14.1-r2 (latest)
21
+ - **expat**: 2.7.3-r0 (latest)
22
+ - **pip**: â‰Ĩ25.0
23
+ - **setuptools**: â‰Ĩ78.1.1
24
+
25
+ ## đŸ“Ļ Required GitHub Secrets
26
+
27
+ Before the Docker deployment workflow can run, you need to add these secrets to your GitHub repository:
28
+
29
+ ### 1. Navigate to Repository Settings
30
+ 1. Go to your repository on GitHub: https://github.com/neverinfamous/memory-journal-mcp
31
+ 2. Click **Settings** → **Secrets and variables** → **Actions**
32
+ 3. Click **New repository secret**
33
+
34
+ ### 2. Required Secrets
35
+
36
+ #### `DOCKER_USERNAME`
37
+ - **Value**: `writenotenow` (Docker Hub username)
38
+ - **Description**: Docker Hub username for authentication
39
+ - **Status**: ✅ Configured
40
+
41
+ #### `DOCKER_PASSWORD`
42
+ - **Value**: Docker Hub access token (NOT your password)
43
+ - **Description**: Docker Hub access token for secure authentication
44
+ - **Status**: ✅ Configured
45
+
46
+ ### 3. Generate Docker Hub Access Token (If Needed)
47
+
48
+ 1. Go to [Docker Hub](https://hub.docker.com)
49
+ 2. Click your avatar → **Account Settings**
50
+ 3. Go to **Security** → **Personal Access Tokens**
51
+ 4. Click **Generate New Token**
52
+ 5. Name: `GitHub-Actions-memory-journal-mcp`
53
+ 6. Permissions: **Read, Write, Delete**
54
+ 7. Copy the token and use it as `DOCKER_PASSWORD`
55
+
56
+ ## đŸ—ī¸ What Gets Built
57
+
58
+ ### Image Configuration
59
+ - **Single Variant**: Alpine-based full-featured image (225MB)
60
+ - **ML Support**: Optional semantic search with graceful degradation
61
+ - ARM64: ML dependencies fail to install, continues without semantic search ✅
62
+ - AMD64: Full ML support with PyTorch, FAISS, sentence-transformers ✅
63
+ - **Base**: Python 3.13 on Alpine Linux 3.22
64
+
65
+ ### Supported Platforms
66
+ - **linux/amd64** - x86_64 architecture (full features)
67
+ - **linux/arm64** - Apple Silicon / ARM64 (core features, optional ML)
68
+
69
+ ### Tags Generated on Each Push
70
+ When you push to `main` branch, the workflow automatically creates:
71
+ - `latest` - Always points to most recent main branch build
72
+ - `v2.2.0` - Current version from pyproject.toml (automatically extracted)
73
+ - `sha-XXXXXXX` - Git commit SHA pinned tag (short format)
74
+
75
+ ## 🔄 Deployment Triggers
76
+
77
+ ### Automatic Deployment
78
+ - ✅ **Push to main** → Builds and pushes all tags
79
+ - ✅ **Create git tag** → Builds and pushes versioned tags (e.g., `v1.1.3`)
80
+ - ✅ **Pull requests** → Builds images for testing (doesn't push to Docker Hub)
81
+
82
+ ### Manual Deployment
83
+ ```bash
84
+ # Create and push a release tag
85
+ git tag v2.2.0
86
+ git push origin v2.2.0
87
+
88
+ # This will trigger deployment with tags:
89
+ # - v2.2.0
90
+ # - latest
91
+ # - sha-XXXXXXX
92
+ ```
93
+
94
+ ## đŸ›Ąī¸ Security Features
95
+
96
+ ### Multi-Layer Security Scanning
97
+ 1. **Docker Scout CLI** - Runs during build, blocks critical/high vulnerabilities
98
+ - Scans single-platform (linux/amd64) image locally
99
+ - 8-minute timeout for efficient CI/CD
100
+ - Blocks deployment if critical/high CVEs detected
101
+ - Allows low/medium severity (acceptable risk)
102
+
103
+ 2. **Trivy Scanner** (Weekly scheduled scan)
104
+ - Runs every Sunday at 2 AM UTC
105
+ - Creates GitHub issues for vulnerabilities
106
+ - Uploads SARIF results to Security tab
107
+ - Exit code 1 on critical/high/medium issues
108
+
109
+ ### Image Optimization
110
+ - **Multi-stage builds** keep images lean (225MB)
111
+ - **Layer caching** speeds up builds significantly
112
+ - **GitHub Actions cache** reduces build times by ~60%
113
+ - **Non-root user** (appuser:appgroup) for container security
114
+ - **WAL mode** for better concurrency and crash recovery
115
+
116
+ ### Supply Chain Security
117
+ - **Attestations**: Enabled for all images
118
+ - **Provenance**: Full build provenance tracking
119
+ - **SBOM**: Software Bill of Materials generated
120
+ - **Signature**: Docker content trust compatible
121
+
122
+ ## đŸ“Ļ What's Excluded from Docker Images
123
+
124
+ The `.dockerignore` file filters out development files:
125
+
126
+ ```
127
+ .github/ # GitHub workflows and templates
128
+ .git/ # Git history
129
+ __pycache__/ # Python cache
130
+ *.pyc # Compiled Python
131
+ *.pyo # Optimized Python
132
+ *.db # Database files
133
+ .venv/ # Virtual environments
134
+ dist/ # Build artifacts
135
+ *.egg-info/ # Package metadata
136
+ .pytest_cache/ # Test cache
137
+ htmlcov/ # Coverage reports
138
+ ```
139
+
140
+ ## đŸŽ¯ Docker Hub Integration
141
+
142
+ ### Automatic Updates
143
+ - **Tags**: Automatically created and pushed
144
+ - **Attestations**: Supply chain metadata attached to all tags
145
+ - **SBOM**: Software Bill of Materials for each build
146
+ - **Multi-arch manifests**: Single tag works on AMD64 and ARM64
147
+
148
+ ### Repository Information
149
+ - **Repository**: `writenotenow/memory-journal-mcp`
150
+ - **Visibility**: Public
151
+ - **URL**: https://hub.docker.com/r/writenotenow/memory-journal-mcp
152
+ - **Pulls**: Tracked by Docker Hub analytics
153
+
154
+ ## ⚡ Build Performance
155
+
156
+ ### Optimizations Implemented
157
+ - **Parallel builds** for AMD64 and ARM64
158
+ - **GitHub Actions cache** for Docker layers
159
+ - **Multi-platform builds** using QEMU and Buildx
160
+ - **Graceful ML fallback** (continues without ML on ARM64)
161
+ - **Strategic layer ordering** (requirements → dependencies → code)
162
+
163
+ ### Build Times (Actual)
164
+ - **AMD64 build**: ~3-4 minutes (with cache)
165
+ - **ARM64 build**: ~2-3 minutes (without ML dependencies)
166
+ - **Multi-platform total**: ~5-7 minutes
167
+ - **Security scanning**: ~30-60 seconds
168
+ - **First build (no cache)**: ~10-15 minutes
169
+
170
+ ### Caching Strategy
171
+ - **Layer caching**: Maximizes Docker layer reuse
172
+ - **Package caching**: pip packages cached between builds
173
+ - **Base image caching**: Python Alpine image cached locally
174
+
175
+ ## đŸ§Ē Testing
176
+
177
+ ### Automated CI/CD Tests
178
+
179
+ #### Test Matrix (Python 3.10, 3.11, 3.12)
180
+ - ✅ **Dependency installation** - All required packages
181
+ - ✅ **Linting** - flake8 code quality checks
182
+ - ✅ **Server import** - Python module loads correctly
183
+ - ✅ **Database schema** - SQLite schema validation
184
+
185
+ #### Docker Image Tests
186
+ - ✅ **Security scan** - Docker Scout CVE detection
187
+ - ✅ **Import test** - Server imports successfully in container
188
+ - ✅ **Multi-platform** - Both AMD64 and ARM64 verified
189
+ - ✅ **ML graceful degradation** - Continues without ML on ARM64
190
+
191
+ ### Manual Testing
192
+
193
+ #### Quick Verification
194
+ ```bash
195
+ # Test latest build
196
+ docker pull writenotenow/memory-journal-mcp:latest
197
+ docker run --rm writenotenow/memory-journal-mcp:latest python -c "import sys; sys.path.append('src'); import server; print('✅ Works!')"
198
+ ```
199
+
200
+ #### Full Functional Test
201
+ ```bash
202
+ # Create data directory
203
+ mkdir -p data
204
+
205
+ # Run server with volume mount
206
+ docker run --rm -i \
207
+ -v ./data:/app/data \
208
+ writenotenow/memory-journal-mcp:latest \
209
+ python src/server.py
210
+ ```
211
+
212
+ #### Test Specific Version
213
+ ```bash
214
+ # Test by version tag
215
+ docker pull writenotenow/memory-journal-mcp:v2.2.0
216
+ docker run --rm writenotenow/memory-journal-mcp:v2.2.0 python -c "print('v2.2.0 works!')"
217
+
218
+ # Test by commit SHA
219
+ docker pull writenotenow/memory-journal-mcp:sha-XXXXXXX
220
+ ```
221
+
222
+ ## 🚨 Troubleshooting
223
+
224
+ ### Common Issues
225
+
226
+ #### 1. Build fails with authentication error
227
+ **Symptoms**: `Error saving credentials: error storing credentials`
228
+ **Solution**:
229
+ - Verify `DOCKER_USERNAME` and `DOCKER_PASSWORD` secrets in GitHub
230
+ - Check Docker Hub access token hasn't expired
231
+ - Ensure token has Read, Write, Delete permissions
232
+
233
+ #### 2. ARM64 build warnings about ML dependencies
234
+ **Status**: ✅ Expected behavior, not an error
235
+ **Details**:
236
+ - PyTorch CPU builds not available for ARM64 Alpine
237
+ - Server continues without semantic search features
238
+ - Core functionality fully operational
239
+
240
+ #### 3. Security scan fails
241
+ **Symptoms**: Build blocked with "Critical or high severity vulnerabilities detected"
242
+ **Solution**:
243
+ 1. Review Docker Scout output in Actions logs
244
+ 2. Update base image in Dockerfile (`FROM python:3.13-alpine`)
245
+ 3. Update pinned packages (openssl, curl, expat)
246
+ 4. Commit and push changes to trigger new build
247
+
248
+ #### 4. Cache-related build failures
249
+ **Symptoms**: "Failed to save: Unable to reserve cache"
250
+ **Status**: ✅ Informational warning, not an error
251
+ **Details**: Another concurrent job may be writing to cache, image still builds successfully
252
+
253
+ ### Monitoring
254
+
255
+ #### GitHub Actions
256
+ - **Build Status**: https://github.com/neverinfamous/memory-journal-mcp/actions
257
+ - **Workflow File**: `.github/workflows/docker-publish.yml`
258
+ - **Security Scans**: `.github/workflows/security-update.yml`
259
+
260
+ #### Docker Hub
261
+ - **Repository**: https://hub.docker.com/r/writenotenow/memory-journal-mcp
262
+ - **Tags**: View all available tags
263
+ - **Image Layers**: Inspect layer sizes and contents
264
+ - **Security**: Docker Scout recommendations
265
+
266
+ #### GitHub Security Tab
267
+ - **SARIF Results**: Trivy scanner uploads
268
+ - **Dependabot Alerts**: Dependency vulnerabilities
269
+ - **Code Scanning**: Security analysis results
270
+
271
+ ## 📈 Usage Analytics
272
+
273
+ ### Metrics to Monitor
274
+
275
+ #### Docker Hub (Public)
276
+ - **Pull count** - Total downloads
277
+ - **Tag popularity** - Most-used versions
278
+ - **Geographic distribution** - User locations
279
+
280
+ #### GitHub (Private)
281
+ - **Build success rate** - CI/CD health
282
+ - **Build duration trends** - Performance monitoring
283
+ - **Security scan results** - Vulnerability tracking
284
+
285
+ ## 🔄 Update Process
286
+
287
+ ### Regular Updates (Recommended Monthly)
288
+
289
+ 1. **Check for base image updates**
290
+ ```bash
291
+ docker pull python:3.13-alpine
292
+ docker inspect python:3.13-alpine --format '{{.Created}}'
293
+ ```
294
+
295
+ 2. **Update pinned packages in Dockerfile**
296
+ ```bash
297
+ # Check latest Alpine package versions
298
+ docker run --rm python:3.13-alpine sh -c "apk update && apk info openssl curl expat"
299
+ ```
300
+
301
+ 3. **Update Dockerfile with new versions**
302
+ ```dockerfile
303
+ RUN apk add --no-cache --upgrade openssl=<version> curl=<version> expat=<version>
304
+ ```
305
+
306
+ 4. **Commit and push to trigger rebuild**
307
+ ```bash
308
+ git add Dockerfile
309
+ git commit -m "Update Docker base image with security fixes"
310
+ git push origin main
311
+ ```
312
+
313
+ 5. **Monitor GitHub Actions** for successful build
314
+ ```bash
315
+ gh run list --limit 3
316
+ gh run watch <run-id>
317
+ ```
318
+
319
+ ### Emergency Security Updates
320
+
321
+ If Docker Scout or Trivy detects critical vulnerabilities:
322
+
323
+ 1. **Immediate action required** - Block deployments
324
+ 2. **Review CVE details** in Actions logs or Security tab
325
+ 3. **Update affected packages** in Dockerfile
326
+ 4. **Test locally** before pushing
327
+ 5. **Deploy fix immediately** to main branch
328
+
329
+ ## 📚 Additional Resources
330
+
331
+ - **GitHub Wiki**: https://github.com/neverinfamous/memory-journal-mcp/wiki
332
+ - **PyPI Package**: https://pypi.org/project/memory-journal-mcp/
333
+ - **MCP Registry**: https://registry.modelcontextprotocol.io/
334
+ - **Docker Hub**: https://hub.docker.com/r/writenotenow/memory-journal-mcp
335
+ - **GitHub Gists**: https://gist.github.com/neverinfamous/ffedec3bdb5da08376a381733b80c1a7
336
+
337
+ ---
338
+
339
+ ## 🏆 Current Build Status
340
+
341
+ ✅ **Production/Stable** - All systems operational
342
+ - Latest version: v2.2.0
343
+ - Docker Scout: ✅ No critical/high vulnerabilities
344
+ - Multi-platform: ✅ AMD64 + ARM64 support
345
+ - Security packages: ✅ All at latest versions
346
+ - Image size: 225MB (optimized for deployment)
@@ -0,0 +1,45 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+ schedule:
9
+ - cron: '23 2 * * 1'
10
+
11
+ env:
12
+ CODEQL_ACTION_FEATURE_SANDWICH: false
13
+
14
+ jobs:
15
+ analyze:
16
+ name: Analyze
17
+ runs-on: ubuntu-latest
18
+ permissions:
19
+ actions: read
20
+ contents: read
21
+ security-events: write
22
+
23
+ strategy:
24
+ fail-fast: false
25
+ matrix:
26
+ language: [ 'javascript-typescript' ]
27
+
28
+ steps:
29
+ - name: Checkout repository
30
+ uses: actions/checkout@v5
31
+
32
+ - name: Initialize CodeQL
33
+ uses: github/codeql-action/init@v4
34
+ with:
35
+ languages: ${{ matrix.language }}
36
+ db-location: ${{ runner.temp }}/codeql_databases
37
+
38
+ - name: Autobuild
39
+ uses: github/codeql-action/autobuild@v4
40
+
41
+ - name: Perform CodeQL Analysis
42
+ uses: github/codeql-action/analyze@v4
43
+ with:
44
+ upload: always
45
+ wait-for-processing: false
@@ -0,0 +1,42 @@
1
+ name: Dependabot auto-merge
2
+
3
+ on:
4
+ pull_request:
5
+ paths:
6
+ - 'package*.json'
7
+ - '.github/workflows/dependabot-auto-merge.yml'
8
+
9
+ permissions:
10
+ pull-requests: write
11
+ contents: write
12
+
13
+ jobs:
14
+ dependabot:
15
+ runs-on: ubuntu-latest
16
+ if: ${{ github.actor == 'dependabot[bot]' }}
17
+ steps:
18
+ - name: Dependabot metadata
19
+ id: metadata
20
+ uses: dependabot/fetch-metadata@v2
21
+ with:
22
+ github-token: "${{ secrets.GITHUB_TOKEN }}"
23
+
24
+ - name: Enable auto-merge for Dependabot PRs
25
+ if: ${{ steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor' }}
26
+ run: gh pr merge --auto --squash "$PR_URL"
27
+ env:
28
+ PR_URL: ${{ github.event.pull_request.html_url }}
29
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30
+
31
+ - name: Comment on major version updates
32
+ if: ${{ steps.metadata.outputs.update-type == 'version-update:semver-major' }}
33
+ uses: actions/github-script@v8
34
+ with:
35
+ github-token: ${{ secrets.GITHUB_TOKEN }}
36
+ script: |
37
+ github.rest.issues.createComment({
38
+ issue_number: context.issue.number,
39
+ owner: context.repo.owner,
40
+ repo: context.repo.repo,
41
+ body: 'âš ī¸ This is a major version update. Please review carefully before merging.'
42
+ })
@@ -0,0 +1,277 @@
1
+ name: Build and Push Docker Images
2
+
3
+ on:
4
+ # Only run after lint-and-test completes successfully
5
+ workflow_run:
6
+ workflows: ["Lint and Test"]
7
+ types: [completed]
8
+ branches: [main]
9
+ # Also run on version tags (for releases)
10
+ push:
11
+ tags: [ 'v*' ]
12
+
13
+ env:
14
+ REGISTRY: docker.io
15
+ IMAGE_NAME: writenotenow/memory-journal-mcp
16
+
17
+ permissions:
18
+ contents: read
19
+ packages: write
20
+ security-events: write
21
+ pull-requests: write
22
+ id-token: write
23
+ attestations: write
24
+
25
+ jobs:
26
+ # Build each platform on native architecture (avoids QEMU emulation issues)
27
+ build-platform:
28
+ # Only run if lint-and-test succeeded OR if this is a tag push
29
+ if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'push' }}
30
+ strategy:
31
+ fail-fast: false
32
+ matrix:
33
+ include:
34
+ - platform: linux/amd64
35
+ runner: ubuntu-latest
36
+ - platform: linux/arm64
37
+ runner: ubuntu-24.04-arm
38
+
39
+ runs-on: ${{ matrix.runner }}
40
+ permissions:
41
+ contents: read
42
+ packages: write
43
+ id-token: write
44
+ attestations: write
45
+
46
+ outputs:
47
+ version: ${{ steps.version.outputs.version }}
48
+
49
+ steps:
50
+ - name: Checkout repository
51
+ uses: actions/checkout@v5
52
+
53
+ - name: Set up Docker Buildx
54
+ uses: docker/setup-buildx-action@v3
55
+
56
+ - name: Log in to Docker Hub
57
+ if: github.event_name != 'pull_request'
58
+ uses: docker/login-action@v3
59
+ continue-on-error: true
60
+ with:
61
+ registry: ${{ env.REGISTRY }}
62
+ username: ${{ secrets.DOCKER_USERNAME }}
63
+ password: ${{ secrets.DOCKER_PASSWORD }}
64
+
65
+ - name: Read version from VERSION file
66
+ id: version
67
+ run: |
68
+ if [ -f "VERSION" ]; then
69
+ VERSION=$(head -1 VERSION | tr -d '[:space:]')
70
+ fi
71
+ if [ -z "$VERSION" ]; then
72
+ VERSION=$(grep -oP '"version":\s*"\K[0-9.]+' package.json | head -1)
73
+ fi
74
+ if [ -z "$VERSION" ]; then
75
+ VERSION="1.0.0"
76
+ fi
77
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
78
+ echo "Detected version: $VERSION"
79
+
80
+ - name: Extract metadata
81
+ id: meta
82
+ uses: docker/metadata-action@v5
83
+ with:
84
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
85
+ flavor: |
86
+ latest=false
87
+ suffix=-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
88
+ tags: |
89
+ type=sha,prefix=sha-,format=short
90
+
91
+ - name: Build and push platform image
92
+ id: build
93
+ uses: docker/build-push-action@v6
94
+ with:
95
+ context: .
96
+ file: Dockerfile
97
+ platforms: ${{ matrix.platform }}
98
+ push: ${{ github.event_name != 'pull_request' }}
99
+ tags: ${{ steps.meta.outputs.tags }}
100
+ labels: ${{ steps.meta.outputs.labels }}
101
+ cache-from: type=gha,scope=${{ matrix.platform }}
102
+ cache-to: type=gha,scope=${{ matrix.platform }},mode=max
103
+ provenance: mode=max
104
+ sbom: true
105
+
106
+ - name: Export digest
107
+ if: github.event_name != 'pull_request'
108
+ run: |
109
+ mkdir -p /tmp/digests
110
+ digest="${{ steps.build.outputs.digest }}"
111
+ touch "/tmp/digests/${digest#sha256:}"
112
+
113
+ - name: Upload digest
114
+ if: github.event_name != 'pull_request'
115
+ uses: actions/upload-artifact@v4
116
+ with:
117
+ name: digests-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
118
+ path: /tmp/digests/*
119
+ if-no-files-found: error
120
+ retention-days: 1
121
+
122
+ # Security scan on amd64 image with strict gates (blocks on critical/high)
123
+ security-scan:
124
+ runs-on: ubuntu-latest
125
+ needs: build-platform
126
+ if: github.event_name != 'pull_request'
127
+ permissions:
128
+ contents: read
129
+ security-events: write
130
+
131
+ steps:
132
+ - name: Checkout repository
133
+ uses: actions/checkout@v5
134
+
135
+ - name: Set up Docker Buildx
136
+ uses: docker/setup-buildx-action@v3
137
+
138
+ - name: Build image for scanning
139
+ uses: docker/build-push-action@v6
140
+ with:
141
+ context: .
142
+ file: Dockerfile
143
+ platforms: linux/amd64
144
+ push: false
145
+ load: true
146
+ tags: local-scan:latest
147
+ cache-from: type=gha,scope=linux/amd64
148
+
149
+ - name: Docker Scout security scan
150
+ timeout-minutes: 10
151
+ run: |
152
+ curl -sSfL https://raw.githubusercontent.com/docker/scout-cli/main/install.sh | sh -s --
153
+ docker images local-scan:latest
154
+ echo "🔍 Running Docker Scout security scan for local-scan:latest"
155
+
156
+ echo "âąī¸ Running Docker Scout scan (max 8 minutes)..."
157
+ if timeout 480 docker scout cves local-scan:latest > scout_output.txt 2>&1; then
158
+ echo "📊 Scan completed successfully"
159
+ cat scout_output.txt
160
+
161
+ # Check if critical or high vulnerabilities are present in the output
162
+ # Look for non-zero counts in CRITICAL or HIGH columns (format: "1C" or "2H")
163
+ if grep -E "^\s+[1-9][0-9]*C\s+" scout_output.txt > /dev/null; then
164
+ echo "❌ Critical severity vulnerabilities detected"
165
+ echo "🚨 Build blocked due to unacceptable security risk"
166
+ exit 1
167
+ fi
168
+
169
+ if grep -E "^\s+0C\s+[1-9][0-9]*H\s+" scout_output.txt > /dev/null; then
170
+ echo "❌ High severity vulnerabilities detected"
171
+ echo "🚨 Build blocked due to unacceptable security risk"
172
+ exit 1
173
+ else
174
+ echo "✅ Security scan passed - no critical/high severity vulnerabilities"
175
+ echo "â„šī¸ Low/medium severity vulnerabilities are acceptable"
176
+ fi
177
+ else
178
+ echo "âš ī¸ Docker Scout scan timed out or failed"
179
+ echo "🔄 Continuing build - scan timeout is not a security failure"
180
+ echo "â„šī¸ Consider running scout scan locally for large images"
181
+ fi
182
+
183
+ # Merge platform images into multi-arch manifest
184
+ merge-and-push:
185
+ runs-on: ubuntu-latest
186
+ needs: [build-platform, security-scan]
187
+ if: github.event_name != 'pull_request'
188
+ permissions:
189
+ contents: read
190
+ packages: write
191
+ id-token: write
192
+ attestations: write
193
+ deployments: write
194
+
195
+ environment:
196
+ name: ${{ github.ref == 'refs/heads/main' && 'production' || '' }}
197
+ url: https://hub.docker.com/r/writenotenow/memory-journal-mcp
198
+
199
+ steps:
200
+ - name: Checkout repository
201
+ uses: actions/checkout@v5
202
+
203
+ - name: Download digests
204
+ uses: actions/download-artifact@v4
205
+ with:
206
+ path: /tmp/digests
207
+ pattern: digests-*
208
+ merge-multiple: true
209
+
210
+ - name: Set up Docker Buildx
211
+ uses: docker/setup-buildx-action@v3
212
+
213
+ - name: Log in to Docker Hub
214
+ uses: docker/login-action@v3
215
+ with:
216
+ registry: ${{ env.REGISTRY }}
217
+ username: ${{ secrets.DOCKER_USERNAME }}
218
+ password: ${{ secrets.DOCKER_PASSWORD }}
219
+
220
+ - name: Read version
221
+ id: version
222
+ run: |
223
+ if [ -f "VERSION" ]; then
224
+ VERSION=$(head -1 VERSION | tr -d '[:space:]')
225
+ fi
226
+ if [ -z "$VERSION" ]; then
227
+ VERSION=$(grep -oP '"version":\s*"\K[0-9.]+' package.json | head -1)
228
+ fi
229
+ if [ -z "$VERSION" ]; then
230
+ VERSION="1.0.0"
231
+ fi
232
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
233
+
234
+ - name: Extract metadata for manifest
235
+ id: meta
236
+ uses: docker/metadata-action@v5
237
+ with:
238
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
239
+ flavor: |
240
+ latest=auto
241
+ tags: |
242
+ type=semver,pattern=v{{version}}
243
+ type=raw,value=v${{ steps.version.outputs.version }},enable={{is_default_branch}}
244
+ type=raw,value=latest,enable={{is_default_branch}}
245
+ type=sha,prefix=sha-,format=short
246
+
247
+ - name: Create and push manifest
248
+ working-directory: /tmp/digests
249
+ run: |
250
+ docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
251
+ $(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
252
+
253
+ - name: Inspect manifest
254
+ run: |
255
+ docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
256
+
257
+ # Update Docker Hub description
258
+ - name: Update Docker Hub Description
259
+ if: github.ref == 'refs/heads/main'
260
+ uses: peter-evans/dockerhub-description@v5
261
+ continue-on-error: true
262
+ timeout-minutes: 5
263
+ with:
264
+ username: ${{ secrets.DOCKER_USERNAME }}
265
+ password: ${{ secrets.DOCKER_PASSWORD }}
266
+ repository: ${{ env.IMAGE_NAME }}
267
+ readme-filepath: ./DOCKER_README.md
268
+ short-description: "MCP server for Git-aware project memory, capturing code context, GitHub issues, PRs, and Actions."
269
+
270
+ - name: Deployment Summary
271
+ if: github.ref == 'refs/heads/main'
272
+ run: |
273
+ echo "✅ Successfully published Docker images to production"
274
+ echo "đŸŗ Registry: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
275
+ echo "đŸˇī¸ Tags: ${{ steps.meta.outputs.tags }}"
276
+ echo "📝 Commit: ${{ github.sha }}"
277
+ echo "👤 Published by: ${{ github.actor }}"