Add GitHub Actions workflows for building and deploying application

This commit is contained in:
2025-10-01 14:11:56 +08:00
parent 24154f42d4
commit 79411d2eb3
4 changed files with 264 additions and 0 deletions

50
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
name: Build Container Image
on:
workflow_dispatch:
inputs:
tag:
description: 'Image tag'
required: false
default: 'latest'
type: string
env:
REGISTRY: ${{ secrets.CONTAINER_REGISTRY }}
IMAGE_NAME: ${{ secrets.IMAGE_NAME }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=${{ inputs.tag }}
type=sha,prefix={{branch}}-
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Output image tags
run: |
echo "Built and pushed image tags: ${{ steps.meta.outputs.tags }}"

123
.github/workflows/deploy.yml vendored Normal file
View File

@@ -0,0 +1,123 @@
name: Deploy to Kubernetes
on:
workflow_dispatch:
inputs:
image_tag:
description: 'Docker image tag to deploy'
required: true
default: 'latest'
type: string
environment:
description: 'Deployment environment'
required: false
default: 'production'
type: string
env:
REGISTRY: ${{ secrets.CONTAINER_REGISTRY }}
IMAGE_NAME: ${{ secrets.IMAGE_NAME }}
APP_NAME: ${{ secrets.APP_NAME }}
HOST: ${{ secrets.HOST }}
NAMESPACE: ${{ secrets.K8S_NAMESPACE }}
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup kubectl
uses: azure/setup-kubectl@v3
with:
version: 'v1.28.0'
- name: Configure kubectl
run: |
echo "${{ secrets.KUBECONFIG_BASE64 }}" | base64 -d > kubeconfig
export KUBECONFIG=kubeconfig
kubectl config current-context
- name: Create namespace if not exists
run: |
export KUBECONFIG=kubeconfig
kubectl create namespace ${{ env.NAMESPACE }} --dry-run=client -o yaml | kubectl apply -f -
- name: Deploy to Kubernetes
run: |
export KUBECONFIG=kubeconfig
# Create deployment
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${{ env.APP_NAME }}
namespace: ${{ env.NAMESPACE }}
labels:
app: ${{ env.APP_NAME }}
spec:
replicas: 2
selector:
matchLabels:
app: ${{ env.APP_NAME }}
template:
metadata:
labels:
app: ${{ env.APP_NAME }}
spec:
containers:
- name: ${{ env.APP_NAME }}
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ inputs.image_tag }}
ports:
- containerPort: 5173
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: ${{ env.APP_NAME }}-service
namespace: ${{ env.NAMESPACE }}
spec:
selector:
app: ${{ env.APP_NAME }}
ports:
- protocol: TCP
port: 80
targetPort: 5173
type: ClusterIP
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ${{ env.APP_NAME }}-ingress
namespace: ${{ env.NAMESPACE }}
spec:
entryPoints:
- web
routes:
- match: Host(\`${{ env.HOST }}\`)
kind: Rule
services:
- name: ${{ env.APP_NAME }}-service
port: 80
EOF
- name: Verify deployment
run: |
export KUBECONFIG=kubeconfig
kubectl rollout status deployment/${{ env.APP_NAME }} -n ${{ env.NAMESPACE }}
kubectl get pods -n ${{ env.NAMESPACE }} -l app=${{ env.APP_NAME }}
- name: Cleanup
if: always()
run: |
rm -f kubeconfig

18
Dockerfile Normal file
View File

@@ -0,0 +1,18 @@
FROM node:18-alpine
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy source code
COPY . .
# Expose the port that Vite dev server runs on
EXPOSE 5173
# Run the development server
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]

73
GITHUB_ACTIONS_README.md Normal file
View File

@@ -0,0 +1,73 @@
# GitHub Actions Configuration
This repository contains two separate GitHub Actions workflows for building and deploying your application:
## Workflows
### 1. Build Workflow (`build.yml`)
- **Trigger**: Manual dispatch only
- **Purpose**: Builds Docker image and pushes to private container registry
### 2. Deploy Workflow (`deploy.yml`)
- **Trigger**: Manual dispatch only
- **Purpose**: Deploys application to Kubernetes cluster with Traefik ingress
## Required GitHub Secrets
You need to configure the following secrets in your GitHub repository settings:
### Container Registry Secrets
- `CONTAINER_REGISTRY` - Your private container registry URL (e.g., `myregistry.azurecr.io`)
- `REGISTRY_USERNAME` - Username for container registry authentication
- `REGISTRY_PASSWORD` - Password/token for container registry authentication
- `IMAGE_NAME` - Name of your container image (e.g., `www-cialloo-com`)
### Kubernetes Secrets
- `KUBECONFIG_BASE64` - Base64 encoded kubeconfig file for your remote K8s cluster
- `K8S_NAMESPACE` - Kubernetes namespace to deploy to (e.g., `default` or `production`)
### Application Secrets
- `APP_NAME` - Name of your application in Kubernetes (e.g., `www-cialloo-com`)
- `HOST` - Your domain host (e.g., `www.cialloo.com`)
## How to Use
### Building an Image
1. Go to Actions tab in your GitHub repository
2. Select "Build Container Image" workflow
3. Click "Run workflow"
4. Optionally specify a custom tag (defaults to 'latest')
### Deploying to Kubernetes
1. Go to Actions tab in your GitHub repository
2. Select "Deploy to Kubernetes" workflow
3. Click "Run workflow"
4. Specify the image tag to deploy (e.g., 'latest', 'v1.0.0')
5. Optionally specify environment (defaults to 'production')
## Setup Instructions
### 1. Configure Secrets
Add all the required secrets listed above in your GitHub repository:
- Go to Settings → Secrets and variables → Actions
- Click "New repository secret" for each secret
### 2. Get Base64 Kubeconfig
To get your `KUBECONFIG_BASE64` secret:
```bash
# On your local machine with kubectl configured for your cluster
cat ~/.kube/config | base64 -w 0
```
Copy the output and use it as the `KUBECONFIG_BASE64` secret value.
### 3. Container Registry Setup
Make sure your private container registry is set up and you have credentials that can push images.
## Architecture
The deployment creates:
- **Deployment**: 2 replicas of your application
- **Service**: ClusterIP service exposing port 80 → 5173
- **IngressRoute**: Traefik ingress without TLS
The application runs `npm run dev` and serves on port 5173 inside the container.