Skip to content

Commit 6d33f8f

Browse files
authored
feat(devcontainer): base on Ubuntu 26.04 and add Claude Code CLI (#44)
feat(devcontainer): base on Ubuntu 26.04 and add Claude Code CLI
2 parents a6b1075 + bd291f3 commit 6d33f8f

8 files changed

Lines changed: 326 additions & 116 deletions

File tree

.devcontainer/Dockerfile

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04
1+
FROM mcr.microsoft.com/devcontainers/base:ubuntu26.04
22

33
# hadolint ignore=DL3008
44
RUN set -eux; \
@@ -13,4 +13,9 @@ RUN set -eux; \
1313
apt-get -y purge linux-libc-dev; \
1414
apt-get -y autoremove --purge; \
1515
apt-get clean; \
16-
rm -rf /var/lib/apt/lists/*
16+
rm -rf /var/lib/apt/lists/*; \
17+
# Remove Pebble, an unused ACME/TLS test server baked into the base
18+
# image. It is not owned by apt, has no systemd unit, and is never run,
19+
# yet its outdated Go runtime (golang.org/x/net, x/sys, stdlib) is the
20+
# sole source of all fixable HIGH CVEs in the image.
21+
rm -rf /usr/bin/pebble /var/lib/pebble
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"features": {
3+
"ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {
4+
"version": "1.0.5",
5+
"resolved": "ghcr.io/anthropics/devcontainer-features/claude-code@sha256:cfc2e7d3e9fd3b9b01f8d5cb158508a884c8c0ede2e23ed10f32dea5d4ffe69a",
6+
"integrity": "sha256:cfc2e7d3e9fd3b9b01f8d5cb158508a884c8c0ede2e23ed10f32dea5d4ffe69a"
7+
},
8+
"ghcr.io/devcontainers/features/common-utils:2": {
9+
"version": "2.5.9",
10+
"resolved": "ghcr.io/devcontainers/features/common-utils@sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a",
11+
"integrity": "sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a"
12+
},
13+
"ghcr.io/devcontainers/features/github-cli:1": {
14+
"version": "1.1.0",
15+
"resolved": "ghcr.io/devcontainers/features/github-cli@sha256:d22f50b70ed75339b4eed1ba9ecde3a1791f90e88d37936517e3bace0bbad671",
16+
"integrity": "sha256:d22f50b70ed75339b4eed1ba9ecde3a1791f90e88d37936517e3bace0bbad671"
17+
},
18+
"ghcr.io/devcontainers/features/node:1": {
19+
"version": "1.7.1",
20+
"resolved": "ghcr.io/devcontainers/features/node@sha256:8c0de46939b61958041700ee89e3493f3b2e4131a06dc46b4d9423427d06e5f6",
21+
"integrity": "sha256:8c0de46939b61958041700ee89e3493f3b2e4131a06dc46b4d9423427d06e5f6"
22+
},
23+
"ghcr.io/devcontainers/features/sshd:1": {
24+
"version": "1.1.0",
25+
"resolved": "ghcr.io/devcontainers/features/sshd@sha256:f5251b8e4325f68f7280973c6cd65daff414449c66f240621502d4e8e74eb7ee",
26+
"integrity": "sha256:f5251b8e4325f68f7280973c6cd65daff414449c66f240621502d4e8e74eb7ee"
27+
}
28+
}
29+
}

.devcontainer/devcontainer.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,16 @@
2424
},
2525
"ghcr.io/devcontainers/features/github-cli:1": {
2626
"version": "latest"
27-
}
27+
},
28+
"ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {}
2829
},
30+
"mounts": [
31+
"source=claude-code-config-${devcontainerId},target=/home/vscode/.claude,type=volume"
32+
],
2933
"customizations": {
3034
"vscode": {
3135
"extensions": [
36+
"anthropic.claude-code",
3237
"github.copilot",
3338
"github.copilot-chat",
3439
"ms-python.python",

.github/dependabot.yml

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# Keep devcontainer dependencies up to date
22
version: 2
33
updates:
4-
# Monitor GitHub Actions
4+
# Monitor GitHub Actions — daily, security-critical supply-chain component
55
- package-ecosystem: "github-actions"
66
directory: "/"
77
schedule:
8-
interval: "weekly"
9-
open-pull-requests-limit: 5
8+
interval: "daily"
9+
open-pull-requests-limit: 10
1010
labels:
1111
- "dependencies"
1212
- "github-actions"
@@ -19,12 +19,12 @@ updates:
1919
- "minor"
2020
- "patch"
2121

22-
# Monitor Docker base images
22+
# Monitor Docker base images — daily, CVEs ship in base images
2323
- package-ecosystem: "docker"
2424
directory: "/.devcontainer"
2525
schedule:
26-
interval: "weekly"
27-
open-pull-requests-limit: 5
26+
interval: "daily"
27+
open-pull-requests-limit: 10
2828
labels:
2929
- "dependencies"
3030
- "docker"
@@ -36,3 +36,16 @@ updates:
3636
update-types:
3737
- "minor"
3838
- "patch"
39+
40+
# Monitor devcontainer features — daily, includes claude-code, node, github-cli, common-utils, sshd
41+
- package-ecosystem: "devcontainers"
42+
directory: "/.devcontainer"
43+
schedule:
44+
interval: "daily"
45+
open-pull-requests-limit: 10
46+
labels:
47+
- "dependencies"
48+
- "devcontainers"
49+
commit-message:
50+
prefix: "feat"
51+
include: "scope"

.github/workflows/ci.yml

Lines changed: 118 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ on:
55
branches: [ main ]
66
pull_request:
77
branches: [ main ]
8+
schedule:
9+
- cron: '0 2 * * *'
10+
workflow_dispatch:
811

912
permissions:
1013
contents: read
11-
actions: read
12-
security-events: write
1314

1415
concurrency:
1516
group: ${{ github.workflow }}-${{ github.ref }}
@@ -20,6 +21,9 @@ jobs:
2021
runs-on: ubuntu-latest
2122
name: Build and Validate
2223
timeout-minutes: 15
24+
permissions:
25+
contents: read
26+
security-events: write
2327
steps:
2428
- name: Checkout
2529
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
@@ -58,20 +62,34 @@ jobs:
5862
--report-path gitleaks.sarif
5963
6064
- name: Upload gitleaks SARIF
61-
if: always()
65+
if: >
66+
always() &&
67+
(github.event_name != 'pull_request' ||
68+
github.event.pull_request.head.repo.full_name == github.repository)
6269
uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4
6370
with:
6471
sarif_file: gitleaks.sarif
6572
category: security-analysis/gitleaks
6673

6774
- name: Build Docker image
68-
run: docker build --pull -t dev-template:latest .devcontainer/
75+
run: |
76+
docker build --pull -t "dev-template:${{ github.sha }}" .devcontainer/
77+
docker save "dev-template:${{ github.sha }}" -o /tmp/dev-template.tar
78+
79+
- name: Upload image artifact
80+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
81+
with:
82+
name: docker-image-${{ github.sha }}
83+
path: /tmp/dev-template.tar
84+
retention-days: 1
6985

7086
test:
7187
runs-on: ubuntu-latest
7288
name: Test Devcontainer
7389
needs: build
7490
timeout-minutes: 20
91+
permissions:
92+
contents: read
7593
steps:
7694
- name: Checkout
7795
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
@@ -84,7 +102,7 @@ jobs:
84102
push: never
85103
runCmd: |
86104
set -eu
87-
for cmd in python3 node npm gh opencode curl jq; do
105+
for cmd in python3 node npm gh opencode curl jq claude; do
88106
if ! command -v "$cmd" >/dev/null 2>&1; then
89107
echo "::error::$cmd is missing"
90108
exit 1
@@ -97,3 +115,98 @@ jobs:
97115
opencode --version
98116
curl --version | head -1
99117
jq --version
118+
claude --version
119+
120+
scan:
121+
runs-on: ubuntu-latest
122+
name: Security and SBOM Analysis
123+
needs: build
124+
timeout-minutes: 20
125+
permissions:
126+
contents: read
127+
security-events: write
128+
steps:
129+
- name: Checkout
130+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
131+
with:
132+
persist-credentials: false
133+
134+
- name: Download image artifact
135+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
136+
with:
137+
name: docker-image-${{ github.sha }}
138+
path: /tmp
139+
140+
- name: Load Docker image
141+
run: docker load -i /tmp/dev-template.tar
142+
143+
- name: Run Trivy vulnerability scanner (image)
144+
id: trivy-image
145+
continue-on-error: true
146+
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
147+
with:
148+
image-ref: 'dev-template:${{ github.sha }}'
149+
format: 'sarif'
150+
output: 'trivy-results.sarif'
151+
severity: 'CRITICAL'
152+
ignore-unfixed: true
153+
limit-severities-for-sarif: true
154+
exit-code: '1'
155+
cache: false
156+
157+
- name: Upload Trivy image scan results
158+
if: >
159+
always() &&
160+
(github.event_name != 'pull_request' ||
161+
github.event.pull_request.head.repo.full_name == github.repository)
162+
uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4
163+
with:
164+
sarif_file: 'trivy-results.sarif'
165+
category: 'security-analysis/trivy-image'
166+
167+
- name: Generate SBOM
168+
if: always()
169+
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0
170+
with:
171+
image: 'dev-template:${{ github.sha }}'
172+
format: 'spdx-json'
173+
output-file: 'sbom.spdx.json'
174+
175+
- name: Upload SBOM as artifact
176+
if: always()
177+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
178+
with:
179+
name: sbom-${{ github.sha }}
180+
path: sbom.spdx.json
181+
retention-days: 30
182+
183+
- name: Run Trivy vulnerability scanner (filesystem)
184+
id: trivy-fs
185+
continue-on-error: true
186+
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
187+
with:
188+
scan-type: 'fs'
189+
scan-ref: '.'
190+
format: 'sarif'
191+
output: 'trivy-fs-results.sarif'
192+
severity: 'CRITICAL'
193+
ignore-unfixed: true
194+
limit-severities-for-sarif: true
195+
exit-code: '1'
196+
cache: false
197+
198+
- name: Upload Trivy filesystem scan results
199+
if: >
200+
always() &&
201+
(github.event_name != 'pull_request' ||
202+
github.event.pull_request.head.repo.full_name == github.repository)
203+
uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4
204+
with:
205+
sarif_file: 'trivy-fs-results.sarif'
206+
category: 'security-analysis/trivy-filesystem'
207+
208+
- name: Fail job if any Trivy scan found CRITICAL vulnerabilities
209+
if: steps.trivy-image.outcome == 'failure' || steps.trivy-fs.outcome == 'failure'
210+
run: |
211+
echo "::error::Trivy found CRITICAL vulnerabilities. Review the Security tab for details."
212+
exit 1

.github/workflows/security.yml

Lines changed: 0 additions & 88 deletions
This file was deleted.

0 commit comments

Comments
 (0)