Skip to content

Commit cf83072

Browse files
committed
Refresh CI lab runtimes and workflow wiring
1 parent c2d1a93 commit cf83072

4 files changed

Lines changed: 44 additions & 39 deletions

File tree

.github/workflows/cicd.yml

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
branches: [main]
88

99
env:
10-
NODE_VERSION: "18.x"
10+
NODE_VERSION: "24.x"
1111
REGISTRY: ghcr.io
1212
IMAGE_NAME: ${{ github.repository }}
1313

@@ -19,26 +19,18 @@ jobs:
1919

2020
strategy:
2121
matrix:
22-
node-version: [18.x, 20.x]
22+
node-version: [22.x, 24.x]
2323

2424
steps:
2525
- name: Checkout code
2626
uses: actions/checkout@v4
2727

2828
- name: Setup Node.js ${{ matrix.node-version }}
29-
uses: actions/setup-node@v3
29+
uses: actions/setup-node@v6
3030
with:
3131
node-version: ${{ matrix.node-version }}
3232
cache: "npm"
3333

34-
- name: Cache Node modules
35-
uses: actions/cache@v3
36-
with:
37-
path: ~/.npm
38-
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
39-
restore-keys: |
40-
${{ runner.os }}-node-
41-
4234
- name: Install dependencies
4335
run: npm ci
4436

@@ -52,9 +44,9 @@ jobs:
5244
run: npm run test:coverage
5345

5446
- name: Upload coverage reports
55-
uses: codecov/codecov-action@v3
47+
uses: codecov/codecov-action@v5
5648
with:
57-
file: ./coverage/lcov.info
49+
files: ./coverage/lcov.info
5850
flags: unittests
5951
name: codecov-umbrella
6052
fail_ci_if_error: false
@@ -76,7 +68,7 @@ jobs:
7668
fetch-depth: 0
7769

7870
- name: Setup Node.js
79-
uses: actions/setup-node@v3
71+
uses: actions/setup-node@v6
8072
with:
8173
node-version: ${{ env.NODE_VERSION }}
8274
cache: "npm"
@@ -110,7 +102,7 @@ jobs:
110102
uses: actions/checkout@v4
111103

112104
- name: Run Trivy vulnerability scanner
113-
uses: aquasecurity/trivy-action@master
105+
uses: aquasecurity/trivy-action@v0.35.0
114106
with:
115107
scan-type: "fs"
116108
scan-ref: "."
@@ -126,28 +118,28 @@ jobs:
126118
build:
127119
name: Build Application
128120
runs-on: ubuntu-latest
129-
needs: [test, code-quality]
121+
needs: [test, code-quality, security]
130122
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
131123
permissions:
132124
contents: read
133125
packages: write
134126

135127
outputs:
136128
image-digest: ${{ steps.build.outputs.digest }}
137-
image-url: ${{ steps.build.outputs.image-url }}
129+
image-tags: ${{ steps.meta.outputs.tags }}
138130

139131
steps:
140132
- name: Checkout code
141133
uses: actions/checkout@v4
142134

143135
- name: Setup Node.js
144-
uses: actions/setup-node@v3
136+
uses: actions/setup-node@v6
145137
with:
146138
node-version: ${{ env.NODE_VERSION }}
147139
cache: "npm"
148140

149141
- name: Install dependencies
150-
run: npm ci --only=production
142+
run: npm ci --omit=dev
151143

152144
- name: Create production build
153145
run: |
@@ -197,13 +189,16 @@ jobs:
197189
environment:
198190
name: staging
199191
url: ${{ steps.deploy.outputs.url }}
192+
outputs:
193+
url: ${{ steps.deploy.outputs.url }}
200194

201195
steps:
202196
- name: Deploy to staging environment
203197
id: deploy
204198
run: |
205-
echo "🚀 Deploying to staging environment..."
206-
echo "Image: ${{ needs.build.outputs.image-url }}"
199+
echo "Simulating staging deployment"
200+
echo "Image tags:"
201+
echo "${{ needs.build.outputs.image-tags }}"
207202
echo "This would typically deploy to a staging server"
208203
echo "url=https://staging.your-app.com" >> $GITHUB_OUTPUT
209204
@@ -223,12 +218,12 @@ jobs:
223218
uses: actions/checkout@v4
224219

225220
- name: Setup Node.js
226-
uses: actions/setup-node@v3
221+
uses: actions/setup-node@v6
227222
with:
228223
node-version: ${{ env.NODE_VERSION }}
229224

230225
- name: Install test dependencies
231-
run: npm install --only=dev
226+
run: npm ci
232227

233228
- name: Run integration tests against staging
234229
run: |
@@ -244,13 +239,16 @@ jobs:
244239
environment:
245240
name: production
246241
url: ${{ steps.deploy.outputs.url }}
242+
outputs:
243+
url: ${{ steps.deploy.outputs.url }}
247244

248245
steps:
249246
- name: Deploy to production environment
250247
id: deploy
251248
run: |
252-
echo "🚀 Deploying to production environment..."
253-
echo "Image: ${{ needs.build.outputs.image-url }}"
249+
echo "Simulating production deployment"
250+
echo "Image tags:"
251+
echo "${{ needs.build.outputs.image-tags }}"
254252
echo "This would typically deploy to production servers"
255253
echo "url=https://your-app.com" >> $GITHUB_OUTPUT
256254
@@ -279,7 +277,7 @@ jobs:
279277
notify:
280278
name: Deployment Notification
281279
runs-on: ubuntu-latest
282-
needs: [smoke-tests]
280+
needs: [smoke-tests, deploy-production]
283281
if: always() && github.ref == 'refs/heads/main'
284282

285283
steps:
@@ -291,4 +289,4 @@ jobs:
291289
else
292290
echo "❌ Deployment failed or was cancelled"
293291
echo "🔍 Check the workflow logs for details"
294-
fi
292+
fi

Dockerfile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Multi-stage build for production optimization
2-
FROM node:18-alpine AS builder
2+
FROM node:24-alpine AS builder
33

44
# Set working directory
55
WORKDIR /app
@@ -17,7 +17,7 @@ COPY src/ ./src/
1717
RUN mkdir -p dist && cp -r src/* dist/
1818

1919
# Production stage
20-
FROM node:18-alpine AS production
20+
FROM node:24-alpine AS production
2121

2222
# Create app directory
2323
WORKDIR /app
@@ -30,7 +30,7 @@ RUN addgroup -g 1001 -S nodejs && \
3030
COPY package*.json ./
3131

3232
# Install only production dependencies
33-
RUN npm ci --only=production && npm cache clean --force
33+
RUN npm ci --omit=dev && npm cache clean --force
3434

3535
# Copy built application from builder stage
3636
COPY --from=builder /app/dist ./src/
@@ -47,4 +47,4 @@ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
4747
CMD node -e "require('http').get('http://localhost:3000/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1) })"
4848

4949
# Start the application
50-
CMD ["node", "src/app.js"]
50+
CMD ["node", "src/app.js"]

README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# github-actions-cicd-demo
22

3-
> Node.js CI/CD lab demonstrating matrix tests, linting, Trivy SARIF upload, Docker Buildx, GHCR publishing, and simulated staged deploys with GitHub Actions.
3+
> Node.js CI/CD lab demonstrating supported Node.js matrix tests, linting, Trivy SARIF upload, Docker Buildx, GHCR publishing, and simulated staged deploys with GitHub Actions.
44
55
**Context:** This is the pipeline implementation from [devops-labs Module-3 Mini-Project 9](https://github.com/darestack/devops-labs/tree/main/Module-3/mini-project-09). Full implementation notes live there.
66

@@ -10,7 +10,7 @@
1010

1111
| Stage | What It Does | Key Detail |
1212
|---|---|---|
13-
| `test` | Unit tests across multiple Node.js versions | Build matrix: Node 18 and 20 with npm dependency caching. This job also runs the hard lint gate. |
13+
| `test` | Unit tests across supported Node.js versions | Build matrix: Node 22 and 24 with npm dependency caching. This job also runs the hard lint gate. |
1414
| `code-quality` | ESLint SARIF upload | Publishes lint annotations to GitHub Code Scanning. The hard lint gate lives in the `test` job. |
1515
| `security` | Trivy vulnerability scan | Results uploaded as SARIF to GitHub Code Scanning |
1616
| `build` | Docker image creation | Pushes to GHCR tagged with both `branch-name` and `commit-SHA` |
@@ -23,7 +23,7 @@
2323
```
2424
Push to main / PR opened
2525
26-
├── test (matrix: Node 18, 20)
26+
├── test (matrix: Node 22, 24)
2727
│ └── npm ci (cached) → npm run lint → npm test → coverage report
2828
2929
├── code-quality
@@ -45,14 +45,18 @@ Push to main / PR opened
4545

4646
## Key Implementation Decisions
4747

48-
**GHCR image tagging:** Each image is tagged with both `latest` and the commit SHA — enabling rollback to any previous build without relying on the `latest` tag alone.
48+
**Supported Node versions:** The workflow uses Node 22 and 24 rather than EOL runtime lines. The Docker image uses Node 24 Alpine for the build and runtime stages.
49+
50+
**GHCR image tagging:** Each image is tagged with branch and commit-SHA-derived tags, and `latest` is emitted only for the default branch. That makes rollback easier than relying on `latest` alone.
4951

5052
**ESLint as a hard gate:** The matrix `test` job runs `npm run lint` before tests. The separate `code-quality` job keeps `continue-on-error` for SARIF upload so annotations can still be published for review.
5153

5254
**Trivy SARIF upload:** Required adding `security-events: write` to the job-level permissions block. Without this, the upload fails silently.
5355

5456
**Docker Buildx:** The default GitHub Actions Docker driver does not support cache export. Fixed by adding `docker/setup-buildx-action@v3` before the build step.
5557

58+
**Security scan before build:** The Docker build waits for tests, code-quality SARIF upload, and Trivy filesystem scanning.
59+
5660
**GHCR push permissions:** `GITHUB_TOKEN` requires explicit `packages: write` in the build job permissions to create new container packages.
5761

5862
---
@@ -73,7 +77,7 @@ Push to `main` or open a PR to trigger the full pipeline.
7377

7478
## Current Boundary
7579

76-
The staging and production deploy jobs are intentionally simulated in this lab. They show environment flow and dependency ordering, but they do not deploy to a real target yet. To make this a production deployment project, replace the `echo` deployment steps with a real target such as EC2, ECS, Kubernetes, or a PaaS and add deployment logs.
80+
The staging and production deploy jobs are intentionally simulated in this lab. They show environment flow, dependency ordering, image handoff, environment URLs, and notification wiring, but they do not deploy to a real target yet. To make this a production deployment project, replace the `echo` deployment steps with a real target such as EC2, ECS, Kubernetes, or a PaaS and add deployment logs.
7781

7882
---
7983

package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "github-actions-cicd-demo",
33
"version": "1.0.0",
4-
"description": "Continuous Integration demo with GitHub Actions",
4+
"description": "Node.js CI/CD lab with GitHub Actions, Docker Buildx, GHCR, ESLint SARIF, and Trivy scanning",
55
"main": "src/app.js",
66
"scripts": {
77
"start": "node src/app.js",
@@ -16,10 +16,13 @@
1616
"ci",
1717
"cd",
1818
"github-actions",
19-
"node.js",
19+
"nodejs",
20+
"docker",
21+
"ghcr",
22+
"trivy",
2023
"testing"
2124
],
22-
"author": "Your Name",
25+
"author": "Adeleke Dare",
2326
"license": "MIT",
2427
"dependencies": {
2528
"express": "^5.1.0"

0 commit comments

Comments
 (0)