1- name : CI & Docker
1+ name : CI & Docker (GCP Cloud Run)
22
33on :
44 push :
1212 branches :
1313 - main
1414
15+ # Avoid overlapping deploys for the same ref
16+ concurrency :
17+ group : mcp-cicd-${{ github.ref }}
18+ cancel-in-progress : true
19+
20+ # Common env values
21+ env :
22+ NODE_VERSION : 20
23+ REGION : ${{ secrets.GCP_REGION }}
24+ PROJECT_ID : ${{ secrets.GCP_PROJECT_ID }}
25+ AR_HOST : us-east1-docker.pkg.dev
26+
27+ BACKEND_IMAGE_NAME : mcp-backend
28+ FRONTEND_IMAGE_NAME : mcp-frontend
29+
30+ BACKEND_AR_REPO : mcp-backend
31+ FRONTEND_AR_REPO : mcp-frontend
32+
33+ BACKEND_SERVICE : mcp-backend
34+ FRONTEND_SERVICE : mcp-frontend
35+
1536jobs :
1637 build-test :
1738 runs-on : ubuntu-latest
18-
1939 steps :
2040 - name : Checkout repository
2141 uses : actions/checkout@v4
2242
23- - name : Use Node.js 20
43+ - name : Use Node.js
2444 uses : actions/setup-node@v4
2545 with :
26- node-version : 20
46+ node-version : ${{ env.NODE_VERSION }}
2747 cache : npm
2848
2949 - name : Install dependencies
@@ -36,18 +56,13 @@ jobs:
3656 cd server
3757 npm test --if-present
3858
39- # backend image
40- docker-image :
59+ build-backend :
4160 needs : build-test
4261 runs-on : ubuntu-latest
43-
4462 permissions :
4563 contents : read
4664 packages : write
4765
48- env :
49- IMAGE_NAME : mcp-backend
50-
5166 steps :
5267 - name : Checkout repository
5368 uses : actions/checkout@v4
@@ -59,40 +74,36 @@ jobs:
5974 OWNER_LC="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')"
6075 echo "owner_lc=$OWNER_LC" >> "$GITHUB_OUTPUT"
6176
62- - name : Login to GitHub Container Registry
77+ - name : Login to GHCR
6378 uses : docker/login-action@v3
6479 with :
6580 registry : ghcr.io
6681 username : ${{ github.actor }}
6782 password : ${{ secrets.GITHUB_TOKEN }}
6883
69- - name : Build Docker image
84+ - name : Build backend image
85+ shell : bash
7086 run : |
71- IMAGE_ID ="ghcr.io/${{ steps.vars.outputs.owner_lc }}/${{ env.IMAGE_NAME }}"
87+ BACKEND_GHCR ="ghcr.io/${{ steps.vars.outputs.owner_lc }}/${{ env.BACKEND_IMAGE_NAME }}"
7288 VERSION="${{ github.sha }}"
7389
74- echo "IMAGE_ID=$IMAGE_ID " >> $GITHUB_ENV
75- echo "VERSION=$VERSION" >> $GITHUB_ENV
90+ echo "BACKEND_GHCR=$BACKEND_GHCR " >> " $GITHUB_ENV"
91+ echo "VERSION=$VERSION" >> " $GITHUB_ENV"
7692
77- docker build -t "$IMAGE_ID :$VERSION" -t "$IMAGE_ID :latest" .
93+ docker build -t "$BACKEND_GHCR :$VERSION" -t "$BACKEND_GHCR :latest" .
7894
79- - name : Push Docker image
95+ - name : Push backend image
8096 run : |
81- docker push "$IMAGE_ID :$VERSION"
82- docker push "$IMAGE_ID :latest"
97+ docker push "$BACKEND_GHCR :$VERSION"
98+ docker push "$BACKEND_GHCR :latest"
8399
84- # frontend image
85- frontend-docker-image :
100+ build-frontend :
86101 needs : build-test
87102 runs-on : ubuntu-latest
88-
89103 permissions :
90104 contents : read
91105 packages : write
92106
93- env :
94- IMAGE_NAME : mcp-frontend
95-
96107 steps :
97108 - name : Checkout repository
98109 uses : actions/checkout@v4
@@ -104,31 +115,31 @@ jobs:
104115 OWNER_LC="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')"
105116 echo "owner_lc=$OWNER_LC" >> "$GITHUB_OUTPUT"
106117
107- - name : Login to GitHub Container Registry
118+ - name : Login to GHCR
108119 uses : docker/login-action@v3
109120 with :
110121 registry : ghcr.io
111122 username : ${{ github.actor }}
112123 password : ${{ secrets.GITHUB_TOKEN }}
113124
114- - name : Build frontend Docker image
125+ - name : Build frontend image
126+ shell : bash
115127 run : |
116- FRONTEND_IMAGE_ID ="ghcr.io/${{ steps.vars.outputs.owner_lc }}/${{ env.IMAGE_NAME }}"
117- FRONTEND_VERSION ="${{ github.sha }}"
128+ FRONTEND_GHCR ="ghcr.io/${{ steps.vars.outputs.owner_lc }}/${{ env.FRONTEND_IMAGE_NAME }}"
129+ VERSION ="${{ github.sha }}"
118130
119- echo "FRONTEND_IMAGE_ID=$FRONTEND_IMAGE_ID " >> $GITHUB_ENV
120- echo "FRONTEND_VERSION=$FRONTEND_VERSION " >> $GITHUB_ENV
131+ echo "FRONTEND_GHCR=$FRONTEND_GHCR " >> " $GITHUB_ENV"
132+ echo "VERSION=$VERSION " >> " $GITHUB_ENV"
121133
122- docker build -f Dockerfile.frontend -t "$FRONTEND_IMAGE_ID:$FRONTEND_VERSION " -t "$FRONTEND_IMAGE_ID :latest" .
134+ docker build -f Dockerfile.frontend -t "$FRONTEND_GHCR:$VERSION " -t "$FRONTEND_GHCR :latest" .
123135
124- - name : Push frontend Docker image
136+ - name : Push frontend image
125137 run : |
126- docker push "$FRONTEND_IMAGE_ID:$FRONTEND_VERSION "
127- docker push "$FRONTEND_IMAGE_ID :latest"
138+ docker push "$FRONTEND_GHCR:$VERSION "
139+ docker push "$FRONTEND_GHCR :latest"
128140
129- # backend cloud deployment
130- deploy-gcp :
131- needs : docker-image
141+ deploy-backend :
142+ needs : build-backend
132143 runs-on : ubuntu-latest
133144 permissions :
134145 contents : read
@@ -145,50 +156,59 @@ jobs:
145156 OWNER_LC="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')"
146157 echo "owner_lc=$OWNER_LC" >> "$GITHUB_OUTPUT"
147158
159+ # NOTE: Using SA key json for now (works). Upgrade to OIDC/WIF later.
148160 - name : Authenticate to Google Cloud
149161 uses : google-github-actions/auth@v2
150162 with :
151163 credentials_json : ${{ secrets.GCP_SERVICE_ACCOUNT_KEY }}
152164
165+ - name : Debug GCP env
166+ run : |
167+ echo "PROJECT_ID=${{ env.PROJECT_ID }}"
168+ echo "REGION=${{ env.REGION }}"
169+
153170 - name : Set up gcloud
154171 uses : google-github-actions/setup-gcloud@v2
155172 with :
156- project_id : ${{ secrets.GCP_PROJECT_ID }}
173+ project_id : ${{ env.PROJECT_ID }}
157174
158175 - name : Configure Docker for Artifact Registry
159176 run : |
160- gcloud auth configure-docker us-east1-docker.pkg.dev --quiet
177+ gcloud auth configure-docker ${{ env.AR_HOST }} --quiet
161178
162- - name : Pull image from GHCR
179+ - name : Pull backend image from GHCR
180+ shell : bash
163181 run : |
164- IMAGE_ID ="ghcr.io/${{ steps.vars.outputs.owner_lc }}/mcp-backend "
182+ BACKEND_GHCR ="ghcr.io/${{ steps.vars.outputs.owner_lc }}/${{ env.BACKEND_IMAGE_NAME }} "
165183 VERSION="${{ github.sha }}"
166184
167- echo "IMAGE_ID=$IMAGE_ID " >> $GITHUB_ENV
168- echo "VERSION=$VERSION" >> $GITHUB_ENV
185+ echo "BACKEND_GHCR=$BACKEND_GHCR " >> " $GITHUB_ENV"
186+ echo "VERSION=$VERSION" >> " $GITHUB_ENV"
169187
170188 echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
171- docker pull "$IMAGE_ID :$VERSION"
189+ docker pull "$BACKEND_GHCR :$VERSION"
172190
173- - name : Tag and push image to Artifact Registry
191+ - name : Tag & push backend image to Artifact Registry
192+ shell : bash
174193 run : |
175- AR_IMAGE="us-east1-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/mcp-backend/mcp-backend"
176- docker tag "$IMAGE_ID:$VERSION" "$AR_IMAGE:$VERSION"
177- docker push "$AR_IMAGE:$VERSION"
178- echo "AR_IMAGE=$AR_IMAGE" >> $GITHUB_ENV
194+ BACKEND_AR_IMAGE="${{ env.AR_HOST }}/${{ env.PROJECT_ID }}/${{ env.BACKEND_AR_REPO }}/${{ env.BACKEND_IMAGE_NAME }}"
195+ echo "BACKEND_AR_IMAGE=$BACKEND_AR_IMAGE" >> "$GITHUB_ENV"
196+
197+ docker tag "$BACKEND_GHCR:$VERSION" "$BACKEND_AR_IMAGE:$VERSION"
198+ docker push "$BACKEND_AR_IMAGE:$VERSION"
179199
180- - name : Deploy to Cloud Run
200+ - name : Deploy backend to Cloud Run
181201 run : |
182- gcloud run deploy mcp-backend \
183- --image "$AR_IMAGE:${{ github.sha }} " \
184- --region "${{ secrets.GCP_REGION }}" \
202+ gcloud run deploy "${{ env.BACKEND_SERVICE }}" \
203+ --image "$BACKEND_AR_IMAGE:$VERSION " \
204+ --region "${{ env.REGION }}" \
185205 --platform managed \
186206 --allow-unauthenticated \
187- --port 3000
207+ --port 3000 \
208+ --quiet
188209
189- # frontend cloud deployment
190- deploy-gcp-frontend :
191- needs : frontend-docker-image
210+ deploy-frontend :
211+ needs : build-frontend
192212 runs-on : ubuntu-latest
193213 permissions :
194214 contents : read
@@ -205,43 +225,53 @@ jobs:
205225 OWNER_LC="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')"
206226 echo "owner_lc=$OWNER_LC" >> "$GITHUB_OUTPUT"
207227
228+ # NOTE: Using SA key json for now (works). Upgrade to OIDC/WIF later.
208229 - name : Authenticate to Google Cloud
209230 uses : google-github-actions/auth@v2
210231 with :
211232 credentials_json : ${{ secrets.GCP_SERVICE_ACCOUNT_KEY }}
212233
234+ - name : Debug GCP env
235+ run : |
236+ echo "PROJECT_ID=${{ env.PROJECT_ID }}"
237+ echo "REGION=${{ env.REGION }}"
238+
213239 - name : Set up gcloud
214240 uses : google-github-actions/setup-gcloud@v2
215241 with :
216- project_id : ${{ secrets.GCP_PROJECT_ID }}
242+ project_id : ${{ env.PROJECT_ID }}
217243
218244 - name : Configure Docker for Artifact Registry
219245 run : |
220- gcloud auth configure-docker us-east1-docker.pkg.dev --quiet
246+ gcloud auth configure-docker ${{ env.AR_HOST }} --quiet
221247
222248 - name : Pull frontend image from GHCR
249+ shell : bash
223250 run : |
224- FRONTEND_IMAGE_ID ="ghcr.io/${{ steps.vars.outputs.owner_lc }}/mcp-frontend "
225- FRONTEND_VERSION ="${{ github.sha }}"
251+ FRONTEND_GHCR ="ghcr.io/${{ steps.vars.outputs.owner_lc }}/${{ env.FRONTEND_IMAGE_NAME }} "
252+ VERSION ="${{ github.sha }}"
226253
227- echo "FRONTEND_IMAGE_ID=$FRONTEND_IMAGE_ID " >> $GITHUB_ENV
228- echo "FRONTEND_VERSION=$FRONTEND_VERSION " >> $GITHUB_ENV
254+ echo "FRONTEND_GHCR=$FRONTEND_GHCR " >> " $GITHUB_ENV"
255+ echo "VERSION=$VERSION " >> " $GITHUB_ENV"
229256
230257 echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
231- docker pull "$FRONTEND_IMAGE_ID:$FRONTEND_VERSION "
258+ docker pull "$FRONTEND_GHCR:$VERSION "
232259
233260 - name : Tag & push frontend image to Artifact Registry
261+ shell : bash
234262 run : |
235- AR_FRONTEND_IMAGE="us-east1-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/mcp-frontend/mcp-frontend"
236- docker tag "$FRONTEND_IMAGE_ID:$FRONTEND_VERSION" "$AR_FRONTEND_IMAGE:$FRONTEND_VERSION"
237- docker push "$AR_FRONTEND_IMAGE:$FRONTEND_VERSION"
238- echo "AR_FRONTEND_IMAGE=$AR_FRONTEND_IMAGE" >> $GITHUB_ENV
263+ FRONTEND_AR_IMAGE="${{ env.AR_HOST }}/${{ env.PROJECT_ID }}/${{ env.FRONTEND_AR_REPO }}/${{ env.FRONTEND_IMAGE_NAME }}"
264+ echo "FRONTEND_AR_IMAGE=$FRONTEND_AR_IMAGE" >> "$GITHUB_ENV"
265+
266+ docker tag "$FRONTEND_GHCR:$VERSION" "$FRONTEND_AR_IMAGE:$VERSION"
267+ docker push "$FRONTEND_AR_IMAGE:$VERSION"
239268
240269 - name : Deploy frontend to Cloud Run
241270 run : |
242- gcloud run deploy mcp-frontend \
243- --image "$AR_FRONTEND_IMAGE:${{ github.sha }} " \
244- --region "${{ secrets.GCP_REGION }}" \
271+ gcloud run deploy "${{ env.FRONTEND_SERVICE }}" \
272+ --image "$FRONTEND_AR_IMAGE:$VERSION " \
273+ --region "${{ env.REGION }}" \
245274 --platform managed \
246275 --allow-unauthenticated \
247- --port 80
276+ --port 80 \
277+ --quiet
0 commit comments