Moving to github

This commit is contained in:
2026-03-28 19:24:29 -04:00
commit 036fa7ab33
302 changed files with 17838 additions and 0 deletions

96
.github/DEVELOPMENT.md vendored Normal file
View File

@@ -0,0 +1,96 @@
# Development Setup
## Environment Management
This project uses **Nix with direnv** for reproducible development environments.
### What You Get Automatically
When you `cd` into the project directory, direnv automatically provides:
- Ruby 3.3
- Go Task (task runner)
- Docker & Docker Compose
- PostgreSQL 16 client
- Build tools (gcc, make, pkg-config)
- Required libraries (libyaml, libffi, openssl, zlib)
### First Time Setup
1. **Install Nix** (if not already installed)
```bash
sh <(curl -L https://nixos.org/nix/install) --daemon
```
2. **Install direnv** (if not already installed)
```bash
# macOS
brew install direnv
# Or via Nix
nix-env -iA nixpkgs.direnv
```
3. **Configure your shell** (add to `~/.bashrc` or `~/.zshrc`)
```bash
eval "$(direnv hook bash)" # for bash
eval "$(direnv hook zsh)" # for zsh
```
4. **Allow direnv in project**
```bash
cd turbovault-web
direnv allow
```
That's it! All dependencies are now available.
## Quick Start
```bash
# Setup everything
task setup
# Start development
task server
# See all available commands
task
```
## Available Tasks
Run `task` or `task --list` to see all available commands.
Key tasks:
- `task setup` - Complete initial setup
- `task server` - Start Rails server
- `task test` - Run tests
- `task db:reset` - Reset database
- `task docker:logs` - View PostgreSQL logs
## Nix Configuration
The `shell.nix` file defines all dependencies. If you need to add more tools:
1. Edit `shell.nix`
2. Reload: `direnv reload`
## Troubleshooting
### direnv not loading
```bash
direnv allow
```
### Missing dependencies
```bash
# Reload Nix shell
direnv reload
# Or exit and re-enter directory
cd .. && cd turbovault-web
```
### Update Nix packages
Edit the nixpkgs URL in `shell.nix` to a newer version if needed.

231
.github/SECRETS_SETUP.md vendored Normal file
View File

@@ -0,0 +1,231 @@
# GitHub Secrets Setup
This guide explains how to configure GitHub Secrets for the CI/CD workflows.
## Default: GitHub Container Registry
**Good news!** The default workflow uses GitHub Container Registry (ghcr.io), which requires **no secrets** to set up. It uses the built-in `GITHUB_TOKEN` automatically.
Just push a tag and it works:
```bash
git tag v1.0.0
git push origin v1.0.0
```
Your image will be at: `ghcr.io/YOUR_USERNAME/turbovault:v1.0.0`
## Optional: Use a Different Registry
If you want to use a different registry (Docker Hub, private registry, etc.), you'll need to modify the workflow and add secrets.
### Example: Docker Hub
Edit `.github/workflows/build-and-push.yml`:
```yaml
env:
REGISTRY: docker.io
IMAGE_NAME: your-username/turbovault
```
Add secrets:
- `DOCKERHUB_USERNAME` - Your Docker Hub username
- `DOCKERHUB_TOKEN` - Access token from Docker Hub
Update login step:
```yaml
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
```
### Example: Private Registry
Edit `.github/workflows/build-and-push.yml`:
```yaml
env:
REGISTRY: registry.example.com
IMAGE_NAME: turbovault
```
Add secrets:
- `REGISTRY_USERNAME` - Registry username
- `REGISTRY_PASSWORD` - Registry password/token
Update login step:
```yaml
- name: Log in to Registry
uses: docker/login-action@v3
with:
registry: ${{ secrets.REGISTRY_URL }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
```
## Verify Setup
### Test the Workflow
**Option A: Create a tag (triggers automatically)**
```bash
git tag v1.0.0
git push origin v1.0.0
```
The workflow will automatically build and push to GitHub Container Registry.
**Option B: Manual trigger**
1. Go to **Actions** tab
2. Click **Build and Push Docker Image**
3. Click **Run workflow**
4. Enter tag: `test`
5. Click **Run workflow**
6. Watch the build progress
### View Your Images
**GitHub Container Registry:**
1. Go to your GitHub profile
2. Click **Packages** tab
3. You'll see `turbovault` package
4. Images are at: `ghcr.io/YOUR_USERNAME/turbovault:TAG`
## Troubleshooting
### Error: "denied: permission_denied"
**Cause:** GitHub Container Registry permissions issue
**Fix:**
1. Make sure your repository has `packages: write` permission
2. The workflow already has this set:
```yaml
permissions:
contents: read
packages: write
```
### Error: "unable to login to registry"
**Cause:** Using custom registry without proper credentials
**Fix:**
1. Verify secrets are set correctly
2. Test locally:
```bash
docker login your-registry.com
```
3. Update workflow with correct registry URL and credentials
### Workflow doesn't trigger
**Cause:** Wrong tag format
**Fix:**
- Workflow triggers on tags like `v1.0.0`, `v2.1.0`
- Must start with `v`
- Or use manual trigger (workflow_dispatch)
### Image not appearing in packages
**Cause:** First time pushing to ghcr.io
**Fix:**
1. Go to your GitHub profile → Packages
2. Find `turbovault` package
3. Click **Package settings**
4. Make it public (if desired):
- Change visibility to **Public**
5. Link to repository for better discoverability
## Security Best Practices
### ✅ DO:
- Use access tokens (not passwords)
- Set minimum required permissions
- Rotate tokens regularly
- Use organization secrets for team projects
- Use GitHub Container Registry (free, built-in, secure)
### ❌ DON'T:
- Commit secrets to repository
- Share tokens publicly
- Use personal passwords
- Give tokens more permissions than needed
## Advanced: Environment Secrets
For multiple environments (staging, production):
1. Create **Environments** in GitHub:
- Settings → Environments → New environment
- Name: `production`
2. Add environment-specific secrets:
- `PRODUCTION_GITEA_TOKEN`
- `STAGING_GITEA_TOKEN`
3. Update workflow to use environment:
```yaml
jobs:
build:
environment: production
steps:
- run: echo "${{ secrets.PRODUCTION_GITEA_TOKEN }}"
```
## Workflow Files
Your repository includes these workflows:
### `.github/workflows/build-and-push.yml`
- **Triggers:** Git tags (v*) or manual
- **Purpose:** Build Docker image and push to GitHub Container Registry
- **Required secrets:** None (uses built-in `GITHUB_TOKEN`)
### `.github/workflows/ci.yml`
- **Triggers:** Push to main/develop, Pull Requests
- **Purpose:** Run tests, linting, security scans
- **Required secrets:** None (RAILS_MASTER_KEY optional)
## Getting Started Checklist
### Using GitHub Container Registry (Default - No Setup Required!)
- [ ] Push code to GitHub
- [ ] Create a tag: `git tag v1.0.0 && git push origin v1.0.0`
- [ ] Watch Actions tab for the build
- [ ] View image in GitHub Packages
- [ ] Update k8s deployment with new image
- [ ] Deploy to Kubernetes
### Using Custom Registry (Optional)
- [ ] Create registry access token
- [ ] Add registry secrets to GitHub
- [ ] Modify `.github/workflows/build-and-push.yml`
- [ ] Test workflow manually
- [ ] Verify image appears in your registry
- [ ] Deploy to Kubernetes
## Support
If you encounter issues:
1. Check the Actions logs: `https://github.com/YOUR_USERNAME/turbovault/actions`
2. Read the error messages carefully
3. For custom registries, test login locally first
4. Open an issue if you're stuck
---
**Next Steps:** Create a tag to trigger your first build:
```bash
git tag v1.0.0
git push origin v1.0.0
```
Then check the **Actions** tab and **Packages** tab to see your image! 🚀

185
.github/WHAT_TO_COMMIT.md vendored Normal file
View File

@@ -0,0 +1,185 @@
# What to Commit to GitHub (Open Source)
Quick reference for what should and shouldn't be committed to the public GitHub repository.
## ✅ Safe to Commit
### Source Code
- ✅ All Ruby files (`app/`, `lib/`, `config/`)
-`Gemfile` and `Gemfile.lock`
- ✅ Controllers, models, views
- ✅ Migrations (don't contain secrets)
- ✅ Seeds (use fake/example data only)
### Configuration
-`config/database.yml` (uses ENV vars)
-`config/routes.rb`
-`config/environments/*.rb`
-`.env.example` (template only)
-`Dockerfile`
-`docker-compose.yml` (development version)
### Kubernetes
-`k8s/deployment.yaml` (with placeholder image)
-`k8s/service.yaml`
-`k8s/ingress.yaml`
-`k8s/configmap.yaml` (example values)
-`k8s/namespace.yaml`
-`k8s/migrate-job.yaml`
-`k8s/*.yaml.example` (all templates)
-`k8s/README.md`
-`k8s/GITEA_SETUP.md`
### GitHub Actions
-`.github/workflows/*.yml`
-`.github/SECRETS_SETUP.md`
-`.github/WHAT_TO_COMMIT.md` (this file!)
### Documentation
-`README.md`
-`LICENSE`
-`DEPLOYMENT.md`
-`API_DOCUMENTATION.md`
- ✅ All other `.md` files
### Assets
- ✅ JavaScript controllers
- ✅ CSS/Tailwind files
- ✅ Images, icons
### Testing
-`test/` directory
- ✅ Test fixtures
-`.rubocop.yml`
## ❌ Never Commit (Already Gitignored)
### Secrets & Credentials
-`.env` (actual environment variables)
-`k8s/secrets.yaml` (actual Kubernetes secrets)
-`config/master.key`
-`config/credentials/*.key`
- ❌ Any file containing passwords, tokens, or API keys
### Generated Files
-`log/*.log`
-`tmp/**`
-`public/assets/**` (compiled assets)
-`node_modules/`
-`coverage/`
-`.byebug_history`
### Database
-`*.sqlite3`
- ❌ Database dumps
-`dump.rdb`
### Local Environment
-`.DS_Store`
-`.idea/` (IDE files)
-`.vscode/`
-`*.swp`, `*.swo`
### Docker
-`docker-compose.override.yml` (local overrides)
## 🔍 Current .gitignore
Your `.gitignore` file already covers all sensitive files:
```gitignore
/.env
/.env.local
/config/master.key
k8s/secrets.yaml
k8s/sealed-secrets.yaml
```
These patterns prevent accidental commits of secrets.
## 🛡️ Double Check Before Pushing
Before pushing to GitHub, always verify:
```bash
# Check what will be committed
git status
# Review changes
git diff
# Ensure no secrets
grep -r "password\|token\|secret\|key" --include="*.rb" --include="*.yml" | grep -v ".example"
```
## ⚠️ If You Accidentally Commit a Secret
1. **Immediately revoke the secret** (regenerate token, change password)
2. Remove from git history:
```bash
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch path/to/file' \
--prune-empty --tag-name-filter cat -- --all
```
3. Force push: `git push origin main --force`
4. Rotate all credentials
5. Consider the secret compromised
Better: Use [BFG Repo-Cleaner](https://rtyley.github.io/bfg-repo-cleaner/) or GitHub's secret scanning.
## 📦 What Gets Built vs What Gets Committed
### Committed to GitHub (Source)
```
Source Code (.rb, .js, .css)
Configuration Templates (.example files)
Kubernetes Manifests (with placeholders)
Documentation (.md files)
```
### Built by GitHub Actions (Artifacts)
```
Source Code
Docker Build
Docker Image
Pushed to Gitea Registry (PRIVATE)
Deployed to Kubernetes
```
## 🔄 Workflow
1. **Code** → Push to GitHub (public)
2. **GitHub Actions** → Build Docker image
3. **GitHub Actions** → Push to Gitea (private)
4. **Kubernetes** → Pull from Gitea
5. **Deploy** → Run your app
## ✨ Summary
| Item | GitHub | Gitea | k8s |
|------|--------|-------|-----|
| Source Code | ✅ Public | 🔄 Mirror | ❌ |
| Docker Images | ❌ | ✅ Private | 🔽 Pull |
| Secrets | ❌ | ❌ | ✅ Encrypted |
| Documentation | ✅ Public | 🔄 Mirror | ❌ |
| k8s Manifests | ✅ Templates | ❌ | ✅ Applied |
## Questions?
- "Can I commit database.yml?" → ✅ Yes (if it uses ENV vars, not hardcoded passwords)
- "Can I commit Dockerfile?" → ✅ Yes (it's build instructions, not secrets)
- "Can I commit my .env?" → ❌ NO! Use .env.example
- "Can I commit k8s/secrets.yaml?" → ❌ NO! Use secrets.yaml.example
- "Should I commit migrations?" → ✅ Yes
- "Should I commit seeds.rb?" → ✅ Yes (but use fake data, not real user data)
---
**Remember:** When in doubt, don't commit. You can always add files later, but removing secrets from history is painful.

12
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
version: 2
updates:
- package-ecosystem: bundler
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 10
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 10

78
.github/workflows/build-and-push.yml vendored Normal file
View File

@@ -0,0 +1,78 @@
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"

100
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,100 @@
name: CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
jobs:
lint:
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 (linting)
run: bundle exec rubocop --parallel
continue-on-error: true # Don't fail build on style issues
- name: Run Brakeman (security scan)
run: bundle exec brakeman -q --no-pager
continue-on-error: true
test:
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 coverage
if: always()
run: echo "✅ Tests completed"
build-test:
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"