mirror of
https://github.com/ryankazokas/turbovault-app.git
synced 2026-04-16 22:12:53 +00:00
Adds gitea configuration
This commit is contained in:
92
.gitea/workflows/build-and-deploy.yml
Normal file
92
.gitea/workflows/build-and-deploy.yml
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
name: Build and Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*.*.*'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Extract version from tag
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
if [[ "${{ github.ref }}" =~ ^refs/tags/v(.*)$ ]]; then
|
||||||
|
echo "version=${BASH_REMATCH[1]}" >> $GITHUB_OUTPUT
|
||||||
|
echo "tag=${BASH_REMATCH[0]#refs/tags/}" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "version=latest" >> $GITHUB_OUTPUT
|
||||||
|
echo "tag=latest" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Log in to Gitea Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: gitea.kazcloud.dev
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITEA_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
gitea.kazcloud.dev/ryankazokas/turbovault-app:${{ steps.version.outputs.tag }}
|
||||||
|
gitea.kazcloud.dev/ryankazokas/turbovault-app:latest
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
|
- name: Deploy to Kubernetes
|
||||||
|
env:
|
||||||
|
KUBECONFIG_CONTENT: ${{ secrets.KUBECONFIG }}
|
||||||
|
run: |
|
||||||
|
# Setup kubectl
|
||||||
|
mkdir -p ~/.kube
|
||||||
|
echo "$KUBECONFIG_CONTENT" | base64 -d > ~/.kube/config
|
||||||
|
chmod 600 ~/.kube/config
|
||||||
|
|
||||||
|
# Deploy
|
||||||
|
echo "🚀 Deploying version ${{ steps.version.outputs.tag }} to Kubernetes..."
|
||||||
|
kubectl set image deployment/turbovault \
|
||||||
|
turbovault=gitea.kazcloud.dev/ryankazokas/turbovault-app:${{ steps.version.outputs.tag }} \
|
||||||
|
-n turbovault
|
||||||
|
|
||||||
|
# Wait for rollout
|
||||||
|
kubectl rollout status deployment/turbovault -n turbovault --timeout=5m
|
||||||
|
|
||||||
|
echo "✅ Deployment complete!"
|
||||||
|
|
||||||
|
# Show current pods
|
||||||
|
kubectl get pods -n turbovault -l app=turbovault
|
||||||
|
|
||||||
|
- name: Deployment summary
|
||||||
|
if: success()
|
||||||
|
run: |
|
||||||
|
echo "✅ Build and deployment successful!"
|
||||||
|
echo ""
|
||||||
|
echo "📦 Image: gitea.kazcloud.dev/ryankazokas/turbovault-app:${{ steps.version.outputs.tag }}"
|
||||||
|
echo "🚀 Deployed to: turbovault namespace"
|
||||||
|
echo ""
|
||||||
|
echo "View logs:"
|
||||||
|
echo "kubectl logs -f -l app=turbovault -n turbovault"
|
||||||
|
|
||||||
|
- name: Rollback on failure
|
||||||
|
if: failure()
|
||||||
|
env:
|
||||||
|
KUBECONFIG_CONTENT: ${{ secrets.KUBECONFIG }}
|
||||||
|
run: |
|
||||||
|
echo "❌ Deployment failed! Rolling back..."
|
||||||
|
mkdir -p ~/.kube
|
||||||
|
echo "$KUBECONFIG_CONTENT" | base64 -d > ~/.kube/config
|
||||||
|
kubectl rollout undo deployment/turbovault -n turbovault || true
|
||||||
|
echo "⚠️ Attempted rollback. Check cluster status manually."
|
||||||
78
.github/workflows/build-and-push.yml
vendored
78
.github/workflows/build-and-push.yml
vendored
@@ -1,78 +0,0 @@
|
|||||||
name: Build and Push Docker Image
|
|
||||||
|
|
||||||
on:
|
|
||||||
# Trigger on version tags
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- 'v*.*.*'
|
|
||||||
|
|
||||||
# Allow manual triggering
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
tag:
|
|
||||||
description: 'Image tag (e.g., v1.0.0 or latest)'
|
|
||||||
required: true
|
|
||||||
default: 'latest'
|
|
||||||
|
|
||||||
env:
|
|
||||||
REGISTRY: ghcr.io
|
|
||||||
IMAGE_NAME: ${{ github.repository }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Determine image tag
|
|
||||||
id: tag
|
|
||||||
run: |
|
|
||||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
||||||
echo "tag=${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "tag=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Log in to Container Registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ${{ env.REGISTRY }}
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Extract metadata
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
||||||
tags: |
|
|
||||||
type=semver,pattern={{version}}
|
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
|
||||||
type=ref,event=branch
|
|
||||||
type=raw,value=latest,enable={{is_default_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 }}
|
|
||||||
cache-from: type=gha
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
|
|
||||||
- name: Image pushed successfully
|
|
||||||
run: |
|
|
||||||
echo "✅ Image built and pushed!"
|
|
||||||
echo "📦 Image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }}"
|
|
||||||
echo ""
|
|
||||||
echo "🚀 Deploy to Kubernetes:"
|
|
||||||
echo "kubectl set image deployment/turbovault turbovault=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }} -n turbovault"
|
|
||||||
124
.github/workflows/ci.yml
vendored
124
.github/workflows/ci.yml
vendored
@@ -1,124 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ main, develop ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ main, develop ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lint:
|
|
||||||
name: Linting & Security
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Ruby
|
|
||||||
uses: ruby/setup-ruby@v1
|
|
||||||
with:
|
|
||||||
ruby-version: '3.3'
|
|
||||||
bundler-cache: true
|
|
||||||
|
|
||||||
- name: Run RuboCop (style/linting)
|
|
||||||
run: bundle exec rubocop --parallel --format progress
|
|
||||||
|
|
||||||
- name: Run Brakeman (security scan)
|
|
||||||
run: bundle exec brakeman -q --no-pager
|
|
||||||
continue-on-error: true # Security warnings shouldn't block PRs
|
|
||||||
|
|
||||||
typecheck:
|
|
||||||
name: Type Checking
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Ruby
|
|
||||||
uses: ruby/setup-ruby@v1
|
|
||||||
with:
|
|
||||||
ruby-version: '3.3'
|
|
||||||
bundler-cache: true
|
|
||||||
|
|
||||||
- name: Generate Sorbet RBI files
|
|
||||||
run: |
|
|
||||||
bundle exec tapioca gems --no-doc --workers 1
|
|
||||||
bundle exec tapioca dsl
|
|
||||||
|
|
||||||
- name: Run Sorbet type checker
|
|
||||||
run: bundle exec srb tc
|
|
||||||
|
|
||||||
test:
|
|
||||||
name: Tests
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
services:
|
|
||||||
postgres:
|
|
||||||
image: postgres:15
|
|
||||||
env:
|
|
||||||
POSTGRES_USER: turbovault
|
|
||||||
POSTGRES_PASSWORD: postgres
|
|
||||||
POSTGRES_DB: turbovault_test
|
|
||||||
ports:
|
|
||||||
- 5432:5432
|
|
||||||
options: >-
|
|
||||||
--health-cmd pg_isready
|
|
||||||
--health-interval 10s
|
|
||||||
--health-timeout 5s
|
|
||||||
--health-retries 5
|
|
||||||
|
|
||||||
env:
|
|
||||||
DATABASE_HOST: localhost
|
|
||||||
DATABASE_USERNAME: turbovault
|
|
||||||
DATABASE_PASSWORD: postgres
|
|
||||||
DATABASE_NAME: turbovault_test
|
|
||||||
RAILS_ENV: test
|
|
||||||
RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Ruby
|
|
||||||
uses: ruby/setup-ruby@v1
|
|
||||||
with:
|
|
||||||
ruby-version: '3.3'
|
|
||||||
bundler-cache: true
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y libpq-dev
|
|
||||||
|
|
||||||
- name: Setup database
|
|
||||||
run: |
|
|
||||||
bundle exec rails db:create
|
|
||||||
bundle exec rails db:schema:load
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: bundle exec rails test
|
|
||||||
|
|
||||||
- name: Report test results
|
|
||||||
if: always()
|
|
||||||
run: echo "✅ Tests completed"
|
|
||||||
|
|
||||||
build-test:
|
|
||||||
name: Docker Build
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Build Docker image (test)
|
|
||||||
run: docker build -t turbovault:test .
|
|
||||||
|
|
||||||
- name: Test Docker image
|
|
||||||
run: |
|
|
||||||
docker run --rm turbovault:test bundle exec ruby --version
|
|
||||||
echo "✅ Docker image builds successfully"
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
> Your personal video game collection tracker
|
> Your personal video game collection tracker
|
||||||
|
|
||||||
[](https://rubyonrails.org/)
|
[](https://rubyonrails.org/)
|
||||||

|
[](https://gitea.kazcloud.dev/ryankazokas/turbovault-app)
|
||||||
|
|
||||||
Track your physical and digital game collection with automatic metadata from IGDB.
|
Track your physical and digital game collection with automatic metadata from IGDB.
|
||||||
|
|
||||||
|
|||||||
202
docs/GITEA_SECRETS.md
Normal file
202
docs/GITEA_SECRETS.md
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
# Gitea Secrets Configuration
|
||||||
|
|
||||||
|
This document explains what secrets you need to configure in Gitea for automatic builds and deployments.
|
||||||
|
|
||||||
|
## Required Secrets
|
||||||
|
|
||||||
|
### 1. GITEA_TOKEN
|
||||||
|
|
||||||
|
**Purpose:** Allows Gitea Actions to push Docker images to Gitea Container Registry
|
||||||
|
|
||||||
|
**How to create:**
|
||||||
|
|
||||||
|
1. Go to Gitea → **Settings** → **Applications**
|
||||||
|
2. Under **"Generate New Token"**, enter name: `gitea-actions`
|
||||||
|
3. Select scopes:
|
||||||
|
- ✅ `write:package` (push container images)
|
||||||
|
- ✅ `read:package` (pull container images)
|
||||||
|
4. Click **"Generate Token"**
|
||||||
|
5. Copy the token (starts with `glpat-...` or similar)
|
||||||
|
|
||||||
|
**How to add to repository:**
|
||||||
|
|
||||||
|
1. Go to your Gitea repository: `gitea.kazcloud.dev/ryankazokas/turbovault-app`
|
||||||
|
2. Click **Settings** → **Secrets**
|
||||||
|
3. Click **"Add Secret"**
|
||||||
|
4. Name: `GITEA_TOKEN`
|
||||||
|
5. Value: Paste the token you copied
|
||||||
|
6. Click **"Add Secret"**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. KUBECONFIG
|
||||||
|
|
||||||
|
**Purpose:** Allows Gitea Actions to deploy to your Kubernetes cluster
|
||||||
|
|
||||||
|
**How to create:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Export your kubeconfig as base64
|
||||||
|
cat ~/.kube/config | base64 -w 0 > kubeconfig-base64.txt
|
||||||
|
|
||||||
|
# Copy the contents of kubeconfig-base64.txt
|
||||||
|
cat kubeconfig-base64.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
**How to add to repository:**
|
||||||
|
|
||||||
|
1. Go to your Gitea repository: `gitea.kazcloud.dev/ryankazokas/turbovault-app`
|
||||||
|
2. Click **Settings** → **Secrets**
|
||||||
|
3. Click **"Add Secret"**
|
||||||
|
4. Name: `KUBECONFIG`
|
||||||
|
5. Value: Paste the base64-encoded kubeconfig
|
||||||
|
6. Click **"Add Secret"**
|
||||||
|
|
||||||
|
**⚠️ Security Note:** This gives Gitea Actions full access to your Kubernetes cluster. Only add this to trusted repositories!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Optional: Scoped Kubeconfig (More Secure)
|
||||||
|
|
||||||
|
Instead of using your full kubeconfig, create a limited service account:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create service account for deployments
|
||||||
|
kubectl create serviceaccount turbovault-deployer -n turbovault
|
||||||
|
|
||||||
|
# Create role with deployment permissions
|
||||||
|
cat <<EOF | kubectl apply -f -
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: turbovault-deployer
|
||||||
|
namespace: turbovault
|
||||||
|
rules:
|
||||||
|
- apiGroups: ["apps"]
|
||||||
|
resources: ["deployments"]
|
||||||
|
verbs: ["get", "list", "patch", "update"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods"]
|
||||||
|
verbs: ["get", "list"]
|
||||||
|
- apiGroups: ["apps"]
|
||||||
|
resources: ["deployments/status"]
|
||||||
|
verbs: ["get"]
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Bind role to service account
|
||||||
|
kubectl create rolebinding turbovault-deployer \
|
||||||
|
--role=turbovault-deployer \
|
||||||
|
--serviceaccount=turbovault:turbovault-deployer \
|
||||||
|
-n turbovault
|
||||||
|
|
||||||
|
# Get service account token
|
||||||
|
kubectl create token turbovault-deployer -n turbovault --duration=87600h > token.txt
|
||||||
|
|
||||||
|
# Create minimal kubeconfig
|
||||||
|
cat <<EOF > deployer-kubeconfig.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Config
|
||||||
|
clusters:
|
||||||
|
- cluster:
|
||||||
|
server: https://100.101.31.99:6443
|
||||||
|
# Add certificate-authority-data from your main kubeconfig if needed
|
||||||
|
insecure-skip-tls-verify: true
|
||||||
|
name: k3s
|
||||||
|
contexts:
|
||||||
|
- context:
|
||||||
|
cluster: k3s
|
||||||
|
namespace: turbovault
|
||||||
|
user: turbovault-deployer
|
||||||
|
name: k3s
|
||||||
|
current-context: k3s
|
||||||
|
users:
|
||||||
|
- name: turbovault-deployer
|
||||||
|
user:
|
||||||
|
token: $(cat token.txt)
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Encode for Gitea
|
||||||
|
cat deployer-kubeconfig.yaml | base64 -w 0 > deployer-kubeconfig-base64.txt
|
||||||
|
|
||||||
|
# Use this in KUBECONFIG secret instead
|
||||||
|
cat deployer-kubeconfig-base64.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
This limits Gitea Actions to only deploying TurboVault, not full cluster access.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Verifying Secrets
|
||||||
|
|
||||||
|
After adding secrets, you can verify they're set:
|
||||||
|
|
||||||
|
1. Go to repository → **Settings** → **Secrets**
|
||||||
|
2. You should see:
|
||||||
|
- `GITEA_TOKEN` ✅
|
||||||
|
- `KUBECONFIG` ✅
|
||||||
|
|
||||||
|
**Note:** You can't view secret values after creation (security feature).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing the Workflow
|
||||||
|
|
||||||
|
After secrets are configured:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create a test tag
|
||||||
|
git tag v0.0.1-test
|
||||||
|
git push origin v0.0.1-test
|
||||||
|
```
|
||||||
|
|
||||||
|
Watch the workflow at:
|
||||||
|
`gitea.kazcloud.dev/ryankazokas/turbovault-app/actions`
|
||||||
|
|
||||||
|
The workflow should:
|
||||||
|
1. ✅ Build Docker image
|
||||||
|
2. ✅ Push to Gitea registry
|
||||||
|
3. ✅ Deploy to Kubernetes
|
||||||
|
4. ✅ Wait for rollout to complete
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "Error: authentication required"
|
||||||
|
- Check `GITEA_TOKEN` is set and has `write:package` scope
|
||||||
|
|
||||||
|
### "Error: Unable to connect to the server"
|
||||||
|
- Check `KUBECONFIG` secret is set correctly
|
||||||
|
- Verify base64 encoding (no line breaks with `-w 0`)
|
||||||
|
- Test kubeconfig works locally: `kubectl --kubeconfig=<file> get pods -n turbovault`
|
||||||
|
|
||||||
|
### "Error: deployment not found"
|
||||||
|
- Make sure initial deployment is done first: `./scripts/deploy-k8s.sh`
|
||||||
|
- Workflow only updates existing deployments, doesn't create them
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Security Best Practices
|
||||||
|
|
||||||
|
✅ **DO:**
|
||||||
|
- Use service account with minimal permissions (Role, not ClusterRole)
|
||||||
|
- Rotate tokens regularly
|
||||||
|
- Only add secrets to repositories you control
|
||||||
|
|
||||||
|
❌ **DON'T:**
|
||||||
|
- Share secrets in code or documentation
|
||||||
|
- Use admin kubeconfig if possible
|
||||||
|
- Commit secrets to git
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
**Two secrets required:**
|
||||||
|
|
||||||
|
1. **GITEA_TOKEN** - For pushing container images
|
||||||
|
2. **KUBECONFIG** - For deploying to Kubernetes
|
||||||
|
|
||||||
|
Both added at: `gitea.kazcloud.dev/ryankazokas/turbovault-app/settings/secrets`
|
||||||
|
|
||||||
|
After setup, just push tags to trigger automatic builds and deployments! 🚀
|
||||||
323
docs/GITEA_WORKFLOW.md
Normal file
323
docs/GITEA_WORKFLOW.md
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
# Gitea CI/CD Workflow
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
TurboVault uses Gitea Actions for fully automated builds and deployments:
|
||||||
|
|
||||||
|
1. **Push code to GitHub** (primary repository)
|
||||||
|
2. **Gitea mirrors** from GitHub automatically
|
||||||
|
3. **Gitea Actions** builds Docker image and deploys to Kubernetes
|
||||||
|
|
||||||
|
All automatic! 🚀
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Setup (One-Time)
|
||||||
|
|
||||||
|
### 1. Mirror GitHub Repository to Gitea
|
||||||
|
|
||||||
|
In Gitea:
|
||||||
|
|
||||||
|
1. Go to `gitea.kazcloud.dev` → **New Repository**
|
||||||
|
2. Choose **"New Migration"** → **"GitHub"**
|
||||||
|
3. URL: `https://github.com/ryankazokas/turbovault-app`
|
||||||
|
4. Enable **"This repository will be a mirror"**
|
||||||
|
5. Set sync interval: **10 minutes** (or setup webhook for instant sync)
|
||||||
|
6. Click **"Migrate Repository"**
|
||||||
|
|
||||||
|
**Webhook for instant sync (optional):**
|
||||||
|
- In GitHub repo → Settings → Webhooks → Add webhook
|
||||||
|
- Payload URL: `https://gitea.kazcloud.dev/ryankazokas/turbovault-app/mirror-sync`
|
||||||
|
- Content type: `application/json`
|
||||||
|
- Events: Just the push event
|
||||||
|
|
||||||
|
### 2. Configure Gitea Secrets
|
||||||
|
|
||||||
|
See [GITEA_SECRETS.md](GITEA_SECRETS.md) for detailed instructions.
|
||||||
|
|
||||||
|
**Required secrets:**
|
||||||
|
- `GITEA_TOKEN` - For pushing images to registry
|
||||||
|
- `KUBECONFIG` - For deploying to Kubernetes
|
||||||
|
|
||||||
|
Add at: `gitea.kazcloud.dev/ryankazokas/turbovault-app/settings/secrets`
|
||||||
|
|
||||||
|
### 3. Initial Deployment to Kubernetes
|
||||||
|
|
||||||
|
Before automation works, do initial deployment:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build and push first image
|
||||||
|
docker build -t gitea.kazcloud.dev/ryankazokas/turbovault-app:v1.0.0 .
|
||||||
|
docker login gitea.kazcloud.dev
|
||||||
|
docker push gitea.kazcloud.dev/ryankazokas/turbovault-app:v1.0.0
|
||||||
|
|
||||||
|
# Configure secrets and database
|
||||||
|
cp k8s/secrets.yaml.example k8s/secrets.yaml
|
||||||
|
nano k8s/secrets.yaml # Add SECRET_KEY_BASE, DATABASE_PASSWORD, etc.
|
||||||
|
nano k8s/configmap.yaml # Add DATABASE_HOST, etc.
|
||||||
|
|
||||||
|
# Deploy to Kubernetes
|
||||||
|
./scripts/deploy-k8s.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
When script asks for registry credentials:
|
||||||
|
- Registry: `gitea.kazcloud.dev`
|
||||||
|
- Username: `ryankazokas`
|
||||||
|
- Password: `<your-gitea-token>`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Daily Workflow
|
||||||
|
|
||||||
|
After setup, deployments are fully automatic:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Make changes in GitHub
|
||||||
|
git add .
|
||||||
|
git commit -m "Feature: add new functionality"
|
||||||
|
git push origin main
|
||||||
|
|
||||||
|
# 2. When ready to deploy, create version tag
|
||||||
|
git tag v1.0.1
|
||||||
|
git push origin v1.0.1
|
||||||
|
|
||||||
|
# 3. That's it! ✅
|
||||||
|
# Gitea auto-syncs → builds → deploys to Kubernetes
|
||||||
|
```
|
||||||
|
|
||||||
|
**Watch build and deployment:**
|
||||||
|
`https://gitea.kazcloud.dev/ryankazokas/turbovault-app/actions`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
```
|
||||||
|
GitHub (code)
|
||||||
|
↓ (mirror sync)
|
||||||
|
Gitea (code mirror)
|
||||||
|
↓ (on tag push)
|
||||||
|
Gitea Actions:
|
||||||
|
1. Build Docker image
|
||||||
|
2. Push to gitea.kazcloud.dev registry
|
||||||
|
3. Deploy to Kubernetes (kubectl)
|
||||||
|
4. Wait for rollout
|
||||||
|
5. Show status
|
||||||
|
↓
|
||||||
|
Kubernetes pulls image and updates deployment ✅
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Workflow Features
|
||||||
|
|
||||||
|
### ✅ Automatic Rollout Status
|
||||||
|
Workflow waits for rollout to complete before marking as success.
|
||||||
|
|
||||||
|
### ✅ Automatic Rollback on Failure
|
||||||
|
If deployment fails, workflow automatically rolls back to previous version.
|
||||||
|
|
||||||
|
### ✅ Multiple Tags
|
||||||
|
Each version gets two tags:
|
||||||
|
- `v1.0.0` (specific version)
|
||||||
|
- `latest` (always points to most recent)
|
||||||
|
|
||||||
|
### ✅ Manual Trigger
|
||||||
|
Can manually trigger builds via Gitea Actions UI if needed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Manual Deployment (If Needed)
|
||||||
|
|
||||||
|
If you want to deploy manually without waiting for Gitea sync:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build and push
|
||||||
|
docker build -t gitea.kazcloud.dev/ryankazokas/turbovault-app:v1.0.1 .
|
||||||
|
docker push gitea.kazcloud.dev/ryankazokas/turbovault-app:v1.0.1
|
||||||
|
|
||||||
|
# Deploy
|
||||||
|
./scripts/update-deployment.sh v1.0.1
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Version Management
|
||||||
|
|
||||||
|
### Semantic Versioning
|
||||||
|
|
||||||
|
Use semantic versioning for tags:
|
||||||
|
- `v1.0.0` - Major.Minor.Patch
|
||||||
|
- `v1.0.1` - Patch update (bug fixes)
|
||||||
|
- `v1.1.0` - Minor update (new features)
|
||||||
|
- `v2.0.0` - Major update (breaking changes)
|
||||||
|
|
||||||
|
### Viewing Deployed Version
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check current image
|
||||||
|
kubectl get deployment turbovault -n turbovault -o jsonpath='{.spec.template.spec.containers[0].image}'
|
||||||
|
|
||||||
|
# Check all pods
|
||||||
|
kubectl get pods -n turbovault -l app=turbovault
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Workflow Fails at "Build and push"
|
||||||
|
|
||||||
|
**Issue:** Can't push to registry
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
- Check `GITEA_TOKEN` secret is set
|
||||||
|
- Verify token has `write:package` scope
|
||||||
|
- Test: `docker login gitea.kazcloud.dev` with token
|
||||||
|
|
||||||
|
### Workflow Fails at "Deploy to Kubernetes"
|
||||||
|
|
||||||
|
**Issue:** Can't connect to Kubernetes
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
- Check `KUBECONFIG` secret is set correctly
|
||||||
|
- Verify base64 encoding: `echo "$SECRET" | base64 -d | kubectl --kubeconfig=/dev/stdin get nodes`
|
||||||
|
- Check cluster is reachable from Gitea Actions runner
|
||||||
|
|
||||||
|
### Deployment Succeeds but Pods Not Starting
|
||||||
|
|
||||||
|
**Issue:** Image pull errors or configuration issues
|
||||||
|
|
||||||
|
**Check:**
|
||||||
|
```bash
|
||||||
|
kubectl get pods -n turbovault
|
||||||
|
kubectl describe pod <pod-name> -n turbovault
|
||||||
|
kubectl logs <pod-name> -n turbovault
|
||||||
|
```
|
||||||
|
|
||||||
|
**Common causes:**
|
||||||
|
- Image pull secret not configured (run `./scripts/deploy-k8s.sh` again)
|
||||||
|
- Database connection issues (check `k8s/configmap.yaml` and `k8s/secrets.yaml`)
|
||||||
|
- Missing environment variables
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Monitoring Deployments
|
||||||
|
|
||||||
|
### Watch Live Deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Watch pods update
|
||||||
|
kubectl get pods -n turbovault -w
|
||||||
|
|
||||||
|
# Watch rollout status
|
||||||
|
kubectl rollout status deployment/turbovault -n turbovault
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
kubectl logs -f -l app=turbovault -n turbovault
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deployment History
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View rollout history
|
||||||
|
kubectl rollout history deployment/turbovault -n turbovault
|
||||||
|
|
||||||
|
# View specific revision
|
||||||
|
kubectl rollout history deployment/turbovault --revision=2 -n turbovault
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rollback
|
||||||
|
|
||||||
|
### Automatic Rollback
|
||||||
|
Workflow automatically rolls back if deployment fails.
|
||||||
|
|
||||||
|
### Manual Rollback
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Rollback to previous version
|
||||||
|
kubectl rollout undo deployment/turbovault -n turbovault
|
||||||
|
|
||||||
|
# Rollback to specific revision
|
||||||
|
kubectl rollout undo deployment/turbovault --to-revision=3 -n turbovault
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
### Secrets Management
|
||||||
|
- All secrets in Gitea are encrypted
|
||||||
|
- Secrets never appear in logs
|
||||||
|
- Use service account kubeconfig (not admin)
|
||||||
|
|
||||||
|
### Network Security
|
||||||
|
- Gitea Actions runners on internal network
|
||||||
|
- Can reach Kubernetes API (not exposed publicly)
|
||||||
|
- Images pulled from internal registry
|
||||||
|
|
||||||
|
### Access Control
|
||||||
|
- Only repository collaborators can trigger workflows
|
||||||
|
- Gitea token scoped to package registry only
|
||||||
|
- Kubeconfig scoped to turbovault namespace only (recommended)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Advanced: Staging vs Production
|
||||||
|
|
||||||
|
To add staging environment:
|
||||||
|
|
||||||
|
1. Create `v*.*.*-rc*` tags for release candidates
|
||||||
|
2. Deploy to staging namespace
|
||||||
|
3. Update workflow to detect RC tags:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Determine environment
|
||||||
|
id: env
|
||||||
|
run: |
|
||||||
|
if [[ "${{ github.ref }}" =~ -rc ]]; then
|
||||||
|
echo "namespace=turbovault-staging" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "namespace=turbovault" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy new version
|
||||||
|
git tag v1.0.1
|
||||||
|
git push origin v1.0.1
|
||||||
|
|
||||||
|
# Watch deployment
|
||||||
|
kubectl get pods -n turbovault -w
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
kubectl logs -f -l app=turbovault -n turbovault
|
||||||
|
|
||||||
|
# Rollback if needed
|
||||||
|
kubectl rollout undo deployment/turbovault -n turbovault
|
||||||
|
|
||||||
|
# Check current version
|
||||||
|
kubectl get deployment turbovault -n turbovault -o jsonpath='{.spec.template.spec.containers[0].image}'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
**Setup once:**
|
||||||
|
1. Mirror GitHub → Gitea
|
||||||
|
2. Add Gitea secrets (GITEA_TOKEN, KUBECONFIG)
|
||||||
|
3. Initial deployment with `./scripts/deploy-k8s.sh`
|
||||||
|
|
||||||
|
**Daily workflow:**
|
||||||
|
1. Push code to GitHub
|
||||||
|
2. Create version tag
|
||||||
|
3. Everything else is automatic! ✅
|
||||||
|
|
||||||
|
Questions? Check [GITEA_SECRETS.md](GITEA_SECRETS.md) for secret configuration details.
|
||||||
@@ -9,7 +9,7 @@ data:
|
|||||||
RAILS_SERVE_STATIC_FILES: "true"
|
RAILS_SERVE_STATIC_FILES: "true"
|
||||||
RAILS_MAX_THREADS: "5"
|
RAILS_MAX_THREADS: "5"
|
||||||
# Update these values for your environment
|
# Update these values for your environment
|
||||||
DATABASE_HOST: "postgres-service" # Your PostgreSQL service name or external host
|
DATABASE_HOST: "db.rbeowfzliacsawrziniv.supabase.co" # Your PostgreSQL service name or external host
|
||||||
DATABASE_PORT: "5432"
|
DATABASE_PORT: "5432"
|
||||||
DATABASE_NAME: "turbovault_production"
|
DATABASE_NAME: "postgres"
|
||||||
DATABASE_USERNAME: "turbovault"
|
DATABASE_USERNAME: "postgres"
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ spec:
|
|||||||
- name: turbovault
|
- name: turbovault
|
||||||
# UPDATE THIS: Replace with your registry path
|
# UPDATE THIS: Replace with your registry path
|
||||||
# Examples:
|
# Examples:
|
||||||
|
# - Gitea: gitea.kazcloud.dev/ryankazokas/turbovault-app:latest
|
||||||
# - GitHub Container Registry: ghcr.io/ryankazokas/turbovault-app:latest
|
# - GitHub Container Registry: ghcr.io/ryankazokas/turbovault-app:latest
|
||||||
# - Docker Hub: docker.io/username/turbovault:latest
|
# - Docker Hub: docker.io/username/turbovault:latest
|
||||||
# - Private registry: registry.example.com/turbovault:latest
|
image: gitea.kazcloud.dev/ryankazokas/turbovault-app:latest
|
||||||
image: ghcr.io/ryankazokas/turbovault-app:latest
|
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 3000
|
- containerPort: 3000
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ spec:
|
|||||||
containers:
|
containers:
|
||||||
- name: migrate
|
- name: migrate
|
||||||
# UPDATE THIS: Replace with your registry path (same as deployment.yaml)
|
# UPDATE THIS: Replace with your registry path (same as deployment.yaml)
|
||||||
image: ghcr.io/ryankazokas/turbovault-app:latest
|
image: gitea.kazcloud.dev/ryankazokas/turbovault-app:latest
|
||||||
command: ["bundle", "exec", "rails", "db:migrate"]
|
command: ["bundle", "exec", "rails", "db:migrate"]
|
||||||
env:
|
env:
|
||||||
# Load from ConfigMap
|
# Load from ConfigMap
|
||||||
|
|||||||
32
scripts/update-deployment.sh
Executable file
32
scripts/update-deployment.sh
Executable file
@@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Update TurboVault deployment with new image version
|
||||||
|
# Usage: ./scripts/update-deployment.sh v1.0.1
|
||||||
|
|
||||||
|
VERSION=${1:-latest}
|
||||||
|
IMAGE="gitea.kazcloud.dev/ryankazokas/turbovault-app:${VERSION}"
|
||||||
|
NAMESPACE="turbovault"
|
||||||
|
|
||||||
|
echo "🚀 Updating TurboVault deployment to ${VERSION}..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Update deployment
|
||||||
|
kubectl set image deployment/turbovault \
|
||||||
|
turbovault=${IMAGE} \
|
||||||
|
-n ${NAMESPACE}
|
||||||
|
|
||||||
|
echo "✅ Deployment updated to: ${IMAGE}"
|
||||||
|
echo ""
|
||||||
|
echo "⏳ Watching rollout status..."
|
||||||
|
kubectl rollout status deployment/turbovault -n ${NAMESPACE}
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ Deployment complete!"
|
||||||
|
echo ""
|
||||||
|
echo "📊 Current pods:"
|
||||||
|
kubectl get pods -n ${NAMESPACE} -l app=turbovault
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📝 View logs:"
|
||||||
|
echo "kubectl logs -f -l app=turbovault -n ${NAMESPACE}"
|
||||||
Reference in New Issue
Block a user