1+ name : Deploy MCP Web Interface
2+
3+ on :
4+ push :
5+ branches : [main]
6+ tags : ['v*']
7+ pull_request :
8+ branches : [main]
9+
10+ env :
11+ NODE_VERSION : ' 18'
12+ REGISTRY : ghcr.io
13+ IMAGE_NAME : ${{ github.repository }}
14+
15+ jobs :
16+ test :
17+ runs-on : ubuntu-latest
18+ steps :
19+ - uses : actions/checkout@v4
20+
21+ - name : Setup Node.js
22+ uses : actions/setup-node@v4
23+ with :
24+ node-version : ${{ env.NODE_VERSION }}
25+ cache : ' npm'
26+ cache-dependency-path : web/package-lock.json
27+
28+ - name : Install dependencies
29+ run : |
30+ cd web
31+ npm ci
32+
33+ - name : Run type check
34+ run : |
35+ cd web
36+ npm run type-check
37+
38+ - name : Run linting
39+ run : |
40+ cd web
41+ npm run lint
42+
43+ - name : Run tests
44+ run : |
45+ cd web
46+ npm run test:all
47+
48+ build :
49+ needs : test
50+ runs-on : ubuntu-latest
51+ outputs :
52+ image : ${{ steps.image.outputs.image }}
53+ digest : ${{ steps.build.outputs.digest }}
54+ steps :
55+ - uses : actions/checkout@v4
56+
57+ - name : Setup Node.js
58+ uses : actions/setup-node@v4
59+ with :
60+ node-version : ${{ env.NODE_VERSION }}
61+ cache : ' npm'
62+ cache-dependency-path : web/package-lock.json
63+
64+ - name : Install dependencies
65+ run : |
66+ cd web
67+ npm ci
68+
69+ - name : Build application
70+ run : |
71+ cd web
72+ npm run build:production
73+ env :
74+ NODE_ENV : production
75+
76+ - name : Upload build artifacts
77+ uses : actions/upload-artifact@v4
78+ with :
79+ name : build-files
80+ path : web/dist/
81+ retention-days : 7
82+
83+ - name : Set up Docker Buildx
84+ uses : docker/setup-buildx-action@v3
85+
86+ - name : Log in to Container Registry
87+ uses : docker/login-action@v3
88+ with :
89+ registry : ${{ env.REGISTRY }}
90+ username : ${{ github.actor }}
91+ password : ${{ secrets.GITHUB_TOKEN }}
92+
93+ - name : Extract metadata
94+ id : meta
95+ uses : docker/metadata-action@v5
96+ with :
97+ images : ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
98+ tags : |
99+ type=ref,event=branch
100+ type=ref,event=pr
101+ type=semver,pattern={{version}}
102+ type=semver,pattern={{major}}.{{minor}}
103+ type=sha
104+
105+ - name : Build and push Docker image
106+ id : build
107+ uses : docker/build-push-action@v5
108+ with :
109+ context : ./web
110+ push : true
111+ tags : ${{ steps.meta.outputs.tags }}
112+ labels : ${{ steps.meta.outputs.labels }}
113+ cache-from : type=gha
114+ cache-to : type=gha,mode=max
115+ platforms : linux/amd64,linux/arm64
116+
117+ - name : Output image
118+ id : image
119+ run : |
120+ echo "image=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}" >> $GITHUB_OUTPUT
121+
122+ deploy-vercel :
123+ needs : build
124+ runs-on : ubuntu-latest
125+ if : github.ref == 'refs/heads/main'
126+ steps :
127+ - uses : actions/checkout@v4
128+
129+ - name : Download build artifacts
130+ uses : actions/download-artifact@v4
131+ with :
132+ name : build-files
133+ path : web/dist/
134+
135+ - name : Deploy to Vercel
136+ uses : amondnet/vercel-action@v25
137+ with :
138+ vercel-token : ${{ secrets.VERCEL_TOKEN }}
139+ vercel-org-id : ${{ secrets.VERCEL_ORG_ID }}
140+ vercel-project-id : ${{ secrets.VERCEL_PROJECT_ID }}
141+ working-directory : ./web
142+ vercel-args : ' --prod'
143+
144+ deploy-netlify :
145+ needs : build
146+ runs-on : ubuntu-latest
147+ if : github.ref == 'refs/heads/main'
148+ steps :
149+ - uses : actions/checkout@v4
150+
151+ - name : Download build artifacts
152+ uses : actions/download-artifact@v4
153+ with :
154+ name : build-files
155+ path : web/dist/
156+
157+ - name : Deploy to Netlify
158+ uses : nwtgck/actions-netlify@v3.0
159+ with :
160+ publish-dir : ' ./web/dist'
161+ production-branch : main
162+ github-token : ${{ secrets.GITHUB_TOKEN }}
163+ deploy-message : " Deploy from GitHub Actions"
164+ enable-pull-request-comment : false
165+ enable-commit-comment : true
166+ overwrites-pull-request-comment : true
167+ env :
168+ NETLIFY_AUTH_TOKEN : ${{ secrets.NETLIFY_AUTH_TOKEN }}
169+ NETLIFY_SITE_ID : ${{ secrets.NETLIFY_SITE_ID }}
170+
171+ deploy-aws :
172+ needs : build
173+ runs-on : ubuntu-latest
174+ if : github.ref == 'refs/heads/main'
175+ steps :
176+ - uses : actions/checkout@v4
177+
178+ - name : Configure AWS credentials
179+ uses : aws-actions/configure-aws-credentials@v4
180+ with :
181+ aws-access-key-id : ${{ secrets.AWS_ACCESS_KEY_ID }}
182+ aws-secret-access-key : ${{ secrets.AWS_SECRET_ACCESS_KEY }}
183+ aws-region : us-east-1
184+
185+ - name : Download build artifacts
186+ uses : actions/download-artifact@v4
187+ with :
188+ name : build-files
189+ path : web/dist/
190+
191+ - name : Deploy to S3
192+ run : |
193+ aws s3 sync web/dist/ s3://${{ secrets.AWS_S3_BUCKET }} --delete
194+
195+ - name : Invalidate CloudFront
196+ run : |
197+ aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CLOUDFRONT_DISTRIBUTION_ID }} --paths "/*"
198+
199+ deploy-docker :
200+ needs : build
201+ runs-on : ubuntu-latest
202+ if : github.ref == 'refs/heads/main'
203+ steps :
204+ - name : Deploy to production server
205+ uses : appleboy/ssh-action@v1.0.0
206+ with :
207+ host : ${{ secrets.PRODUCTION_HOST }}
208+ username : ${{ secrets.PRODUCTION_USER }}
209+ key : ${{ secrets.PRODUCTION_SSH_KEY }}
210+ script : |
211+ docker pull ${{ needs.build.outputs.image }}
212+ docker stop mcp-web-interface || true
213+ docker rm mcp-web-interface || true
214+ docker run -d \
215+ --name mcp-web-interface \
216+ --restart unless-stopped \
217+ -p 3000:3000 \
218+ -e NODE_ENV=production \
219+ ${{ needs.build.outputs.image }}
220+
221+ security-scan :
222+ needs : build
223+ runs-on : ubuntu-latest
224+ steps :
225+ - name : Run Trivy vulnerability scanner
226+ uses : aquasecurity/trivy-action@master
227+ with :
228+ image-ref : ${{ needs.build.outputs.image }}
229+ format : ' sarif'
230+ output : ' trivy-results.sarif'
231+
232+ - name : Upload Trivy scan results to GitHub Security tab
233+ uses : github/codeql-action/upload-sarif@v3
234+ with :
235+ sarif_file : ' trivy-results.sarif'
0 commit comments