ci: Migrate deployment to Docker-based infrastructure
This commit is contained in:
parent
9c7e33499a
commit
529b4f9d37
43
.github/workflows/deploy.yml
vendored
43
.github/workflows/deploy.yml
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
name: Deploy to Production
|
name: Build Production
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
|
@ -6,8 +6,8 @@ on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
build:
|
||||||
name: Deploy to Netlify/Vercel
|
name: Build Production Artifacts
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -33,35 +33,20 @@ jobs:
|
||||||
VITE_ENV: production
|
VITE_ENV: production
|
||||||
VITE_SENTRY_DSN: ${{ secrets.VITE_SENTRY_DSN }}
|
VITE_SENTRY_DSN: ${{ secrets.VITE_SENTRY_DSN }}
|
||||||
|
|
||||||
# Option 1: Deploy to Netlify
|
- name: Upload production artifacts
|
||||||
- name: Deploy to Netlify
|
uses: actions/upload-artifact@v4
|
||||||
uses: nwtgck/actions-netlify@v3.0
|
|
||||||
with:
|
with:
|
||||||
publish-dir: './dist'
|
name: production-build
|
||||||
production-branch: main
|
path: dist/
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
retention-days: 30
|
||||||
deploy-message: "Deploy from GitHub Actions"
|
|
||||||
enable-pull-request-comment: true
|
|
||||||
enable-commit-comment: true
|
|
||||||
env:
|
|
||||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
|
||||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
|
||||||
timeout-minutes: 5
|
|
||||||
|
|
||||||
# Option 2: Deploy to Vercel (comment out Netlify if using this)
|
- name: Build Docker image
|
||||||
# - name: Deploy to Vercel
|
run: docker build -t yaltopia-admin:${{ github.sha }} .
|
||||||
# uses: amondnet/vercel-action@v25
|
|
||||||
# with:
|
|
||||||
# vercel-token: ${{ secrets.VERCEL_TOKEN }}
|
|
||||||
# vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
|
|
||||||
# vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
|
|
||||||
# vercel-args: '--prod'
|
|
||||||
# working-directory: ./
|
|
||||||
|
|
||||||
- name: Notify deployment success
|
- name: Build success notification
|
||||||
if: success()
|
if: success()
|
||||||
run: echo "Deployment successful!"
|
run: echo "Production build successful!"
|
||||||
|
|
||||||
- name: Notify deployment failure
|
- name: Build failure notification
|
||||||
if: failure()
|
if: failure()
|
||||||
run: echo "Deployment failed!"
|
run: echo "Production build failed!"
|
||||||
|
|
|
||||||
72
README.md
72
README.md
|
|
@ -103,59 +103,39 @@ npm run preview
|
||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
|
|
||||||
### Static Hosting (Netlify, Vercel, etc.)
|
### Docker Deployment (Recommended)
|
||||||
|
|
||||||
|
1. Build the Docker image:
|
||||||
|
```bash
|
||||||
|
docker build -t yaltopia-admin:latest .
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Run the container:
|
||||||
|
```bash
|
||||||
|
docker run -p 8080:80 yaltopia-admin:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Deploy to your cloud provider (AWS, GCP, Azure, DigitalOcean, etc.)
|
||||||
|
|
||||||
|
### Traditional VPS Deployment
|
||||||
|
|
||||||
1. Build the application: `npm run build:prod`
|
1. Build the application: `npm run build:prod`
|
||||||
2. Deploy the `dist` directory
|
2. Copy the `dist` directory to your web server
|
||||||
3. Configure environment variables in your hosting platform
|
3. Configure nginx or Apache to serve the static files
|
||||||
4. Set up redirects for SPA routing (see below)
|
4. Set up redirects for SPA routing (see nginx.conf example)
|
||||||
|
|
||||||
### SPA Routing Configuration
|
### SPA Routing Configuration
|
||||||
|
|
||||||
For proper routing, add a redirect rule:
|
For proper routing with nginx, use the included `nginx.conf` file or add this configuration:
|
||||||
|
|
||||||
**Netlify** (`netlify.toml`):
|
|
||||||
```toml
|
|
||||||
[[redirects]]
|
|
||||||
from = "/*"
|
|
||||||
to = "/index.html"
|
|
||||||
status = 200
|
|
||||||
```
|
|
||||||
|
|
||||||
**Vercel** (`vercel.json`):
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Docker Deployment
|
|
||||||
|
|
||||||
Create a `Dockerfile`:
|
|
||||||
|
|
||||||
```dockerfile
|
|
||||||
FROM node:18-alpine as build
|
|
||||||
WORKDIR /app
|
|
||||||
COPY package*.json ./
|
|
||||||
RUN npm ci
|
|
||||||
COPY . .
|
|
||||||
RUN npm run build:prod
|
|
||||||
|
|
||||||
FROM nginx:alpine
|
|
||||||
COPY --from=build /app/dist /usr/share/nginx/html
|
|
||||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
|
||||||
EXPOSE 80
|
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
|
||||||
```
|
|
||||||
|
|
||||||
Create `nginx.conf`:
|
|
||||||
|
|
||||||
```nginx
|
```nginx
|
||||||
server {
|
location / {
|
||||||
listen 80;
|
try_files $uri $uri/ /index.html;
|
||||||
server_name _;
|
}
|
||||||
root /usr/share/nginx/html;
|
```
|
||||||
index index.html;
|
The project includes a `Dockerfile` and `nginx.conf` for containerized deployment.
|
||||||
|
|
||||||
|
See [DEPLOYMENT.md](dev-docs/DEPLOYMENT.md) for detailed deployment instructions.
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
|
|
|
||||||
|
|
@ -51,47 +51,7 @@
|
||||||
|
|
||||||
## Deployment Options
|
## Deployment Options
|
||||||
|
|
||||||
### Option 1: Vercel (Recommended for Quick Deploy)
|
### Option 1: Docker + Cloud Provider (Recommended)
|
||||||
|
|
||||||
1. Install Vercel CLI:
|
|
||||||
```bash
|
|
||||||
npm i -g vercel
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Login to Vercel:
|
|
||||||
```bash
|
|
||||||
vercel login
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Deploy:
|
|
||||||
```bash
|
|
||||||
vercel --prod
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Set environment variables in Vercel dashboard:
|
|
||||||
- Go to Project Settings → Environment Variables
|
|
||||||
- Add `VITE_API_URL` with your production API URL
|
|
||||||
|
|
||||||
### Option 2: Netlify
|
|
||||||
|
|
||||||
1. Install Netlify CLI:
|
|
||||||
```bash
|
|
||||||
npm i -g netlify-cli
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Login:
|
|
||||||
```bash
|
|
||||||
netlify login
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Deploy:
|
|
||||||
```bash
|
|
||||||
netlify deploy --prod
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Set environment variables in Netlify dashboard
|
|
||||||
|
|
||||||
### Option 3: Docker + Cloud Provider
|
|
||||||
|
|
||||||
1. Build Docker image:
|
1. Build Docker image:
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -121,7 +81,7 @@ docker push account-id.dkr.ecr.region.amazonaws.com/yaltopia-admin:latest
|
||||||
- Azure Container Instances
|
- Azure Container Instances
|
||||||
- DigitalOcean App Platform
|
- DigitalOcean App Platform
|
||||||
|
|
||||||
### Option 4: Traditional VPS (Ubuntu/Debian)
|
### Option 2: Traditional VPS (Ubuntu/Debian)
|
||||||
|
|
||||||
1. SSH into your server
|
1. SSH into your server
|
||||||
|
|
||||||
|
|
@ -181,26 +141,42 @@ sudo cp -r dist/* /var/www/html/
|
||||||
|
|
||||||
### GitHub Actions (Automated)
|
### GitHub Actions (Automated)
|
||||||
|
|
||||||
The `.github/workflows/ci.yml` file is configured for CI.
|
The `.github/workflows/ci.yml` file is configured for CI, and `.github/workflows/deploy.yml` builds production artifacts.
|
||||||
|
|
||||||
For CD, add deployment step:
|
For automated deployment, you can extend the workflow to:
|
||||||
|
|
||||||
|
1. **Push Docker image to registry:**
|
||||||
```yaml
|
```yaml
|
||||||
- name: Deploy to Vercel
|
- name: Login to Docker Registry
|
||||||
if: github.ref == 'refs/heads/main'
|
uses: docker/login-action@v3
|
||||||
run: |
|
with:
|
||||||
npm i -g vercel
|
registry: ${{ secrets.DOCKER_REGISTRY }}
|
||||||
vercel --prod --token=${{ secrets.VERCEL_TOKEN }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ secrets.DOCKER_REGISTRY }}/yaltopia-admin:latest
|
||||||
|
${{ secrets.DOCKER_REGISTRY }}/yaltopia-admin:${{ github.sha }}
|
||||||
```
|
```
|
||||||
|
|
||||||
Or for Netlify:
|
2. **Deploy to your server via SSH:**
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Deploy to Netlify
|
- name: Deploy to production server
|
||||||
if: github.ref == 'refs/heads/main'
|
uses: appleboy/ssh-action@v1.0.0
|
||||||
run: |
|
with:
|
||||||
npm i -g netlify-cli
|
host: ${{ secrets.DEPLOY_HOST }}
|
||||||
netlify deploy --prod --auth=${{ secrets.NETLIFY_AUTH_TOKEN }} --site=${{ secrets.NETLIFY_SITE_ID }}
|
username: ${{ secrets.DEPLOY_USER }}
|
||||||
|
key: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||||
|
script: |
|
||||||
|
cd /opt/yaltopia-admin
|
||||||
|
docker pull ${{ secrets.DOCKER_REGISTRY }}/yaltopia-admin:latest
|
||||||
|
docker-compose down
|
||||||
|
docker-compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ Testing setup and practices:
|
||||||
### [Deployment Guide](./DEPLOYMENT.md)
|
### [Deployment Guide](./DEPLOYMENT.md)
|
||||||
Production deployment:
|
Production deployment:
|
||||||
- Pre-deployment checklist
|
- Pre-deployment checklist
|
||||||
- Deployment options (Vercel, Netlify, Docker)
|
- Deployment options (Docker, VPS)
|
||||||
- Environment configuration
|
- Environment configuration
|
||||||
- CI/CD setup
|
- CI/CD setup
|
||||||
|
|
||||||
|
|
|
||||||
24
netlify.toml
24
netlify.toml
|
|
@ -1,24 +0,0 @@
|
||||||
[build]
|
|
||||||
command = "npm run build:prod"
|
|
||||||
publish = "dist"
|
|
||||||
|
|
||||||
[[redirects]]
|
|
||||||
from = "/*"
|
|
||||||
to = "/index.html"
|
|
||||||
status = 200
|
|
||||||
|
|
||||||
[build.environment]
|
|
||||||
NODE_VERSION = "18"
|
|
||||||
|
|
||||||
[[headers]]
|
|
||||||
for = "/*"
|
|
||||||
[headers.values]
|
|
||||||
X-Frame-Options = "SAMEORIGIN"
|
|
||||||
X-Content-Type-Options = "nosniff"
|
|
||||||
X-XSS-Protection = "1; mode=block"
|
|
||||||
Referrer-Policy = "strict-origin-when-cross-origin"
|
|
||||||
|
|
||||||
[[headers]]
|
|
||||||
for = "/assets/*"
|
|
||||||
[headers.values]
|
|
||||||
Cache-Control = "public, max-age=31536000, immutable"
|
|
||||||
42
vercel.json
42
vercel.json
|
|
@ -1,42 +0,0 @@
|
||||||
{
|
|
||||||
"buildCommand": "npm run build:prod",
|
|
||||||
"outputDirectory": "dist",
|
|
||||||
"rewrites": [
|
|
||||||
{
|
|
||||||
"source": "/(.*)",
|
|
||||||
"destination": "/index.html"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"headers": [
|
|
||||||
{
|
|
||||||
"source": "/(.*)",
|
|
||||||
"headers": [
|
|
||||||
{
|
|
||||||
"key": "X-Frame-Options",
|
|
||||||
"value": "SAMEORIGIN"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "X-Content-Type-Options",
|
|
||||||
"value": "nosniff"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "X-XSS-Protection",
|
|
||||||
"value": "1; mode=block"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Referrer-Policy",
|
|
||||||
"value": "strict-origin-when-cross-origin"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"source": "/assets/(.*)",
|
|
||||||
"headers": [
|
|
||||||
{
|
|
||||||
"key": "Cache-Control",
|
|
||||||
"value": "public, max-age=31536000, immutable"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user