feature/clean-public-urls #1
168
.gitea/workflows/README.md
Normal file
168
.gitea/workflows/README.md
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
# Gitea Workflows
|
||||||
|
|
||||||
|
This directory contains Gitea Actions workflows for CI/CD.
|
||||||
|
|
||||||
|
## Workflows
|
||||||
|
|
||||||
|
### `build.yml` - Build Application Image
|
||||||
|
|
||||||
|
Builds the application image using Cloud Native Buildpacks.
|
||||||
|
|
||||||
|
**Triggers:**
|
||||||
|
- Push to `main`, `production`, or `develop` branches
|
||||||
|
- Pull requests to `main` or `production`
|
||||||
|
- Manual workflow dispatch
|
||||||
|
|
||||||
|
**Outputs:**
|
||||||
|
- Docker image (tagged and optionally pushed to registry)
|
||||||
|
- Image artifact (if no registry configured)
|
||||||
|
|
||||||
|
### `deploy.yml` - Deploy to Production
|
||||||
|
|
||||||
|
Deploys the built image to production server.
|
||||||
|
|
||||||
|
**Triggers:**
|
||||||
|
- After successful `build.yml` workflow completion
|
||||||
|
- Manual workflow dispatch (with image tag input)
|
||||||
|
|
||||||
|
**Process:**
|
||||||
|
- Downloads image artifact or pulls from registry
|
||||||
|
- Transfers deployment files to production server
|
||||||
|
- Mounts Firebase credentials securely
|
||||||
|
- Starts container and verifies health
|
||||||
|
|
||||||
|
### `test.yml` - Run Tests
|
||||||
|
|
||||||
|
Runs Go tests and linting.
|
||||||
|
|
||||||
|
**Triggers:**
|
||||||
|
- Push to `main` or `develop` branches
|
||||||
|
- Pull requests to `main` or `develop`
|
||||||
|
|
||||||
|
**Jobs:**
|
||||||
|
- `test` - Runs Go tests with coverage
|
||||||
|
- `lint` - Runs golangci-lint
|
||||||
|
|
||||||
|
#### Triggers
|
||||||
|
|
||||||
|
- Push to `main` or `production` branches (when `backend/**` files change)
|
||||||
|
- Manual workflow dispatch with environment selection
|
||||||
|
|
||||||
|
## Workflow Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
Push to main/production
|
||||||
|
↓
|
||||||
|
[build.yml] → Builds image → Pushes to registry (optional)
|
||||||
|
↓
|
||||||
|
[deploy.yml] → Deploys to production → Verifies health
|
||||||
|
```
|
||||||
|
|
||||||
|
**Manual Deployment:**
|
||||||
|
1. Run `build.yml` manually (or wait for push)
|
||||||
|
2. Run `deploy.yml` manually with image tag
|
||||||
|
|
||||||
|
#### Required Secrets
|
||||||
|
|
||||||
|
Configure these secrets in Gitea repository settings:
|
||||||
|
|
||||||
|
**Build Secrets:**
|
||||||
|
- `FRONTEND_URL` - Frontend application URL
|
||||||
|
- `DB_HOST` - Database host
|
||||||
|
- `DB_PORT` - Database port
|
||||||
|
- `DB_USER` - Database username
|
||||||
|
- `DB_PASSWORD` - Database password
|
||||||
|
- `DB_NAME` - Database name
|
||||||
|
- `FIREBASE_PROJECT_ID` - Firebase project ID
|
||||||
|
- `FIREBASE_STORAGE_BUCKET` - Firebase storage bucket name
|
||||||
|
|
||||||
|
**Deployment Secrets:**
|
||||||
|
- `DEPLOY_HOST` - Production server hostname/IP
|
||||||
|
- `DEPLOY_USER` - SSH user for deployment
|
||||||
|
- `DEPLOY_PATH` - Deployment directory on server
|
||||||
|
- `SSH_PRIVATE_KEY` - SSH private key for server access
|
||||||
|
- `SSH_KNOWN_HOSTS` - SSH known hosts entry
|
||||||
|
- `FIREBASE_CREDENTIALS_FILE_PATH` - Path to Firebase credentials file on server
|
||||||
|
- `PORT` - Application port (default: 8080)
|
||||||
|
|
||||||
|
**Optional Secrets:**
|
||||||
|
- `REGISTRY_URL` - Container registry URL (if using registry)
|
||||||
|
- `REGISTRY_USERNAME` - Registry username
|
||||||
|
- `REGISTRY_PASSWORD` - Registry password
|
||||||
|
- `NOTIFICATION_WEBHOOK` - Webhook URL for deployment notifications
|
||||||
|
|
||||||
|
#### Security Considerations
|
||||||
|
|
||||||
|
1. **Firebase Credentials:**
|
||||||
|
- Credentials are **NOT** included in the build
|
||||||
|
- Credentials are mounted at runtime on the production server
|
||||||
|
- File must exist on production server at path specified in `FIREBASE_CREDENTIALS_FILE_PATH`
|
||||||
|
- Mounted with read-only and SELinux shared context (`:ro,z`)
|
||||||
|
|
||||||
|
2. **Database Credentials:**
|
||||||
|
- Stored as Gitea secrets
|
||||||
|
- Passed as environment variables at runtime
|
||||||
|
- Never committed to repository
|
||||||
|
|
||||||
|
3. **SSH Access:**
|
||||||
|
- Uses SSH key authentication
|
||||||
|
- Private key stored as Gitea secret
|
||||||
|
- Known hosts verified
|
||||||
|
|
||||||
|
#### Deployment Process
|
||||||
|
|
||||||
|
1. **Build Phase:**
|
||||||
|
- Checks out code
|
||||||
|
- Sets up Docker and Pack CLI
|
||||||
|
- Configures Docker socket (handles rootless Docker)
|
||||||
|
- Builds image using Pack with `--docker-host` flag
|
||||||
|
- Tags and optionally pushes to registry
|
||||||
|
|
||||||
|
2. **Deploy Phase:**
|
||||||
|
- Transfers deployment files to production server
|
||||||
|
- Transfers image (if not using registry)
|
||||||
|
- Creates `.env.production` on server
|
||||||
|
- Runs deployment script that:
|
||||||
|
- Stops existing container
|
||||||
|
- Mounts Firebase credentials (read-only)
|
||||||
|
- Starts new container
|
||||||
|
- Verifies deployment with health check
|
||||||
|
- Rolls back on failure
|
||||||
|
|
||||||
|
#### Manual Deployment
|
||||||
|
|
||||||
|
To trigger manual deployment:
|
||||||
|
|
||||||
|
1. Go to Gitea repository → Actions → Workflows
|
||||||
|
2. Select "Production Deployment"
|
||||||
|
3. Click "Run workflow"
|
||||||
|
4. Select environment (production/staging)
|
||||||
|
5. Click "Run workflow"
|
||||||
|
|
||||||
|
#### Troubleshooting
|
||||||
|
|
||||||
|
**Build fails with Docker permission error:**
|
||||||
|
- Ensure Docker socket is accessible
|
||||||
|
- Check `PACK_DOCKER_HOST` is set correctly
|
||||||
|
- Verify `--docker-host` flag is being passed to pack
|
||||||
|
|
||||||
|
**Deployment fails with Firebase credentials error:**
|
||||||
|
- Verify credentials file exists on server at specified path
|
||||||
|
- Check file permissions: `chmod 644 firebase-credentials.json`
|
||||||
|
- Ensure SELinux allows access (use `:z` flag in mount)
|
||||||
|
|
||||||
|
**SSH connection fails:**
|
||||||
|
- Verify SSH key is correct
|
||||||
|
- Check known hosts entry
|
||||||
|
- Ensure user has access to deployment directory
|
||||||
|
|
||||||
|
**Health check fails:**
|
||||||
|
- Check container logs: `podman logs jd-book-uploader`
|
||||||
|
- Verify port is accessible
|
||||||
|
- Check firewall rules
|
||||||
|
|
||||||
|
## Related Documentation
|
||||||
|
|
||||||
|
- `../../deployment/docs/pack-docker-permissions-fix.md` - Pack Docker permissions fix
|
||||||
|
- `../../deployment/docs/secrets-management.md` - Secrets management guide
|
||||||
|
|
||||||
75
.gitea/workflows/test.yml
Normal file
75
.gitea/workflows/test.yml
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
name: Run Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- production
|
||||||
|
- develop
|
||||||
|
paths:
|
||||||
|
- 'backend/**'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- production
|
||||||
|
- develop
|
||||||
|
paths:
|
||||||
|
- 'backend/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Run Go Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.25'
|
||||||
|
|
||||||
|
- name: Cache Go modules
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/go/pkg/mod
|
||||||
|
key: ${{ runner.os }}-go-${{ hashFiles('backend/go.sum') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-go-
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
working-directory: backend
|
||||||
|
run: go mod download
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
working-directory: backend
|
||||||
|
run: go test -v -race -coverprofile=coverage.out ./...
|
||||||
|
|
||||||
|
- name: Upload coverage
|
||||||
|
uses: codecov/codecov-action@v4
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
file: ./backend/coverage.out
|
||||||
|
flags: backend
|
||||||
|
name: backend-coverage
|
||||||
|
|
||||||
|
lint:
|
||||||
|
name: Lint Code
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.25'
|
||||||
|
|
||||||
|
- name: Run golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@v4
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
working-directory: backend
|
||||||
|
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -49,3 +49,5 @@ build/
|
|||||||
.env.production
|
.env.production
|
||||||
.env.local
|
.env.local
|
||||||
.env.production.example
|
.env.production.example
|
||||||
|
.gitea/workflows/deploy.yml
|
||||||
|
.gitea/workflows/build.yml
|
||||||
|
|||||||
Reference in New Issue
Block a user