|
1 | | -name: 🚀 Docker CI/CD Pipeline |
| 1 | +name: Docker CI/CD Pipeline |
2 | 2 |
|
3 | 3 | on: |
4 | 4 | push: |
5 | 5 | branches: [main, develop] |
6 | 6 | pull_request: |
7 | 7 | branches: [main, develop] |
| 8 | + workflow_dispatch: |
8 | 9 |
|
9 | 10 | concurrency: |
10 | 11 | group: ${{ github.workflow }}-${{ github.ref }} |
11 | 12 | cancel-in-progress: true |
12 | 13 |
|
13 | 14 | env: |
14 | 15 | NODE_VERSION: "22.11.0" |
15 | | - IMAGE_NAME: docker-reactjs-sample |
16 | | - DOCKER_REPO: ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKERHUB_PROJECT_NAME }} |
17 | | - |
18 | | -permissions: |
19 | | - contents: read |
20 | | - id-token: write |
| 16 | + DOCKERHUB_REPO: ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKERHUB_PROJECT_NAME }} |
21 | 17 |
|
22 | 18 | jobs: |
23 | | - # Step 1: Install dependencies and save them as an artifact |
24 | | - dependencies: |
25 | | - name: Install Dependencies & Artifacts |
26 | | - runs-on: ubuntu-latest |
27 | | - steps: |
28 | | - - uses: actions/checkout@v4 |
29 | | - |
30 | | - - name: Setup Node.js |
31 | | - uses: actions/setup-node@v4 |
32 | | - with: |
33 | | - node-version: ${{ env.NODE_VERSION }} |
34 | | - |
35 | | - - name: Cache npm dependencies |
36 | | - uses: actions/cache@v4 |
37 | | - with: |
38 | | - path: ~/.npm |
39 | | - key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} |
40 | | - restore-keys: | |
41 | | - ${{ runner.os }}-node- |
42 | | -
|
43 | | - - name: Install dependencies |
44 | | - run: npm ci |
45 | | - |
46 | | - - name: Upload node_modules artifact |
47 | | - uses: actions/upload-artifact@v4 |
48 | | - with: |
49 | | - name: node-modules |
50 | | - path: node_modules/ |
51 | | - retention-days: 1 |
52 | | - |
53 | | - # Step 2: Lint (Uses downloaded artifact) |
| 19 | + # Step 1: Code Quality Checks |
54 | 20 | lint: |
55 | 21 | name: Lint Code |
56 | 22 | runs-on: ubuntu-latest |
57 | | - needs: [dependencies] |
58 | 23 |
|
59 | 24 | steps: |
60 | | - - uses: actions/checkout@v4 |
| 25 | + - name: Checkout code |
| 26 | + uses: actions/checkout@v4 |
61 | 27 |
|
62 | 28 | - name: Setup Node.js |
63 | 29 | uses: actions/setup-node@v4 |
64 | 30 | with: |
65 | 31 | node-version: ${{ env.NODE_VERSION }} |
| 32 | + cache: npm |
66 | 33 |
|
67 | | - - name: Download node_modules artifact |
68 | | - uses: actions/download-artifact@v4 |
69 | | - with: |
70 | | - name: node-modules |
71 | | - path: node_modules |
| 34 | + - name: Install dependencies |
| 35 | + run: npm ci |
72 | 36 |
|
73 | 37 | - name: Run ESLint |
74 | 38 | run: npm run lint |
75 | 39 |
|
76 | | - # Step 3: Test Suite (Uses downloaded artifact) |
| 40 | + # Step 2: Run Tests |
77 | 41 | test: |
78 | 42 | name: Run Tests |
79 | 43 | runs-on: ubuntu-latest |
80 | | - needs: [dependencies] |
81 | 44 |
|
82 | 45 | steps: |
83 | | - - uses: actions/checkout@v4 |
| 46 | + - name: Checkout code |
| 47 | + uses: actions/checkout@v4 |
84 | 48 |
|
85 | 49 | - name: Setup Node.js |
86 | 50 | uses: actions/setup-node@v4 |
87 | 51 | with: |
88 | 52 | node-version: ${{ env.NODE_VERSION }} |
| 53 | + cache: npm |
89 | 54 |
|
90 | | - - name: Download node_modules artifact |
91 | | - uses: actions/download-artifact@v4 |
92 | | - with: |
93 | | - name: node-modules |
94 | | - path: node_modules |
| 55 | + - name: Install dependencies |
| 56 | + run: npm ci |
| 57 | + |
| 58 | + - name: Run tests |
| 59 | + run: npm run test |
95 | 60 |
|
96 | 61 | - name: Run tests with coverage |
97 | 62 | run: npm run test:coverage |
98 | 63 |
|
99 | | - - name: Upload coverage report |
| 64 | + - name: Upload coverage reports |
100 | 65 | uses: actions/upload-artifact@v4 |
101 | 66 | if: always() |
102 | 67 | with: |
103 | 68 | name: coverage-report |
104 | 69 | path: coverage/ |
105 | 70 | retention-days: 7 |
106 | 71 |
|
107 | | - # Step 4: Docker Build (Needs successful Lint and Test) |
108 | | - build: |
109 | | - name: Build Docker Image |
110 | | - runs-on: ubuntu-latest |
111 | | - needs: [lint, test] |
112 | | - |
113 | | - steps: |
114 | | - - uses: actions/checkout@v4 |
115 | | - |
116 | | - - name: Set up Docker Buildx |
117 | | - uses: docker/setup-buildx-action@v3 |
118 | | - |
119 | | - - name: Extract metadata (tags, labels) |
120 | | - id: meta |
121 | | - uses: docker/metadata-action@v5 |
122 | | - with: |
123 | | - images: ${{ env.DOCKER_REPO }} |
124 | | - |
125 | | - - name: Build production image |
126 | | - uses: docker/build-push-action@v6 |
127 | | - with: |
128 | | - context: . |
129 | | - file: ./Dockerfile |
130 | | - target: production |
131 | | - tags: ${{ steps.meta.outputs.tags }} |
132 | | - build-args: | |
133 | | - NODE_VERSION=${{ env.NODE_VERSION }} |
134 | | - cache-from: type=gha,scope=${{ github.ref_name }} |
135 | | - cache-to: type=gha,mode=max,scope=${{ github.ref_name }} |
136 | | - load: true |
137 | | - |
138 | | - - name: Verify image tag (e.g., latest tag for main branch) |
139 | | - run: | |
140 | | - TAGS="${{ steps.meta.outputs.tags }}" |
141 | | - echo "Tags generated: $TAGS" |
142 | | - # Simple verification for one of the tags created (e.g., the first one) |
143 | | - FIRST_TAG=$(echo "$TAGS" | head -n 1 | tr -d '\n') |
144 | | - docker images "$FIRST_TAG" |
145 | | -
|
146 | | - # Step 5: Deploy to Docker Hub |
147 | | - deploy: |
148 | | - name: Deploy to Docker Hub |
149 | | - runs-on: ubuntu-latest |
150 | | - needs: [build] |
151 | | - if: github.ref == 'refs/heads/main' && github.event_name == 'push' |
152 | | - |
153 | | - steps: |
154 | | - - uses: actions/checkout@v4 |
155 | | - |
156 | | - - uses: docker/setup-qemu-action@v3 |
157 | | - - uses: docker/setup-buildx-action@v3 |
158 | | - |
159 | | - - name: Extract metadata (tags, labels) |
160 | | - id: meta |
161 | | - uses: docker/metadata-action@v5 |
162 | | - with: |
163 | | - images: ${{ env.DOCKER_REPO }} |
164 | | - |
| 72 | + # Step 3: |
165 | 73 | - name: Log in to Docker Hub |
166 | 74 | uses: docker/login-action@v3 |
167 | 75 | with: |
168 | 76 | username: ${{ secrets.DOCKER_USERNAME }} |
169 | 77 | password: ${{ secrets.DOCKERHUB_TOKEN }} |
170 | 78 |
|
171 | | - - name: Build and push image to Docker Hub |
| 79 | + # Step 4. Build and push production Docker image |
| 80 | + - name: Build and push production image |
172 | 81 | uses: docker/build-push-action@v6 |
173 | 82 | with: |
174 | 83 | context: . |
175 | | - file: ./Dockerfile |
176 | | - target: production |
177 | | - platforms: linux/amd64,linux/arm64 |
| 84 | + file: Dockerfile |
178 | 85 | push: true |
| 86 | + platforms: linux/amd64,linux/arm64 |
179 | 87 | tags: | |
180 | | - ${{ steps.meta.outputs.tags }} |
181 | | - ${{ env.DOCKER_REPO }}:${{ github.ref_name }} |
182 | | - build-args: | |
183 | | - NODE_VERSION=${{ env.NODE_VERSION }} |
184 | | - cache-from: type=gha,scope=${{ github.ref_name }} |
185 | | - cache-to: type=gha,mode=max,scope=${{ github.ref_name }} |
| 88 | + ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKERHUB_PROJECT_NAME }}:latest |
| 89 | + ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKERHUB_PROJECT_NAME }}:${{ steps.meta.outputs.SHORT_SHA }} |
| 90 | + cache-from: type=local,src=/tmp/.buildx-cache |
0 commit comments