Skip to content

Repository files navigation

gitdevops

gitdevops is a study project for practicing Rust backend development, database migrations, containers, Kubernetes, and GitOps delivery.

The project is intentionally small: one Actix API, SeaORM migrations, local Docker Compose infrastructure, and k3s deployments managed with Helm, Argo CD, Kargo, and CloudNativePG.

Study Goals

  • Build a Rust monorepo with Cargo workspaces.
  • Create an Actix Web API with health endpoints, product CRUD, and Swagger UI.
  • Manage PostgreSQL schema changes with SeaORM migrations.
  • Run local development infrastructure with Docker Compose.
  • Publish a Docker image to Docker Hub with GitHub Actions.
  • Deploy the app to k3s using Helm and Argo CD.
  • Manage PostgreSQL in Kubernetes with CloudNativePG.
  • Practice GitOps delivery with Argo CD and Kargo.

Repository Layout

apps/api/ Rust Actix Web API
migrations/ SeaORM migration workspace
infrastructure/argocd/ Argo CD AppProject and ApplicationSet
infrastructure/helm/gitdevops/ Helm chart and environment values
infrastructure/kargo/ Kargo Project, Warehouse, and Stage
infrastructure/k3s/operators/ k3s operator manifests
docker-compose.yaml Local development stack
Dockerfile Production image build

Rust Workspace

The root Cargo.toml defines a workspace with two members:

apps/api
migrations

Useful commands:

cargo fmt --all
cargo clippy --locked --workspace --all-targets --all-features -- -D warnings
cargo check --locked --workspace
cargo test --locked --workspace
cargo build --release --locked --workspace

API

The API uses Actix Web and exposes:

GET /health
GET /health/ready
GET /docs/
GET /api-docs/openapi.json

The readiness endpoint checks both database connections:

DATABASE_URL write connection
DATABASE_READ_URL read connection

Public product endpoints:

GET /products
GET /products/{id}
POST /products
PUT /products/{id}
DELETE /products/{id}

Product request body:

{
"name": "Keyboard",
"description": "Mechanical keyboard",
"price_cents": 19900
}

Migrations

Migrations are a separate workspace member under migrations/.

Run migrations locally against the configured database:

cargo run --locked -p migrations -- up

The final schema contains the products table:

products

The latest migration creates products and drops old user or users tables if they exist.

Local Docker Compose

Copy and edit the local environment file if needed:

cp .env.example .env

Start the local stack:

docker compose up --build

Docker Compose runs:

postgres-write primary PostgreSQL instance
postgres-read-1 read replica
postgres-read-2 read replica
migrations runs /app/migrations up
api runs the Actix API

Local database service aliases mirror k3s:

postgres-rw write endpoint
postgres-ro read endpoint

Docker Image

The image is published to Docker Hub:

docker.io/nathan3boss/gitdevops

GitHub Actions expects these repository secrets:

DOCKERHUB_USERNAME
DOCKERHUB_TOKEN

k3s Deployment

The app deploy manifests are generated from a Helm chart:

infrastructure/helm/gitdevops

PostgreSQL uses CloudNativePG with three instances:

1 primary writer
2 read replicas per environment

Each environment has its own namespace, CloudNativePG Cluster, Services, Secrets, and PVCs:

gitdevops-sit
gitdevops-hlg
gitdevops-prd

That means SIT, HLG, and PRD do not share database volumes.

Install the platform controllers before applying the GitOps resources:

kubectl apply --server-side -k infrastructure/k3s/operators/argocd
kubectl rollout status deployment/argocd-server -n argocd
kubectl apply --server-side -k infrastructure/k3s/operators/cloudnative-pg
kubectl rollout status deployment/cnpg-controller-manager -n cnpg-system
kubectl apply -k infrastructure/k3s/operators/cert-manager
kubectl rollout status deployment/cert-manager -n cert-manager
kubectl rollout status deployment/cert-manager-cainjector -n cert-manager
kubectl rollout status deployment/cert-manager-webhook -n cert-manager
# Install Kargo with Helm. See infrastructure/k3s/helm/kargo/README.md.
kubectl apply -k infrastructure/argocd
kubectl apply -k infrastructure/kargo

Access Argo CD and Kargo with port-forwarding:

kubectl port-forward svc/argocd-server -n argocd 8080:443
kubectl port-forward svc/kargo-api -n kargo 8081:443

Open:

https://localhost:8080
https://localhost:8081

If a previous failed apply created a migration job first, reset it in the affected environment namespace:

kubectl delete job gitdevops-migrations -n gitdevops-sit --ignore-not-found

Useful checks:

kubectl get applications -n argocd
kubectl get applicationsets -n argocd
kubectl get all -n gitdevops-sit
kubectl get cluster -n gitdevops-sit
kubectl logs -n gitdevops-sit job/gitdevops-migrations
kubectl logs -n gitdevops-sit deploy/gitdevops

GitOps

Argo CD application manifests live in:

infrastructure/argocd

Kargo promotion manifests live in:

infrastructure/kargo

The app Helm chart lives in:

infrastructure/helm/gitdevops

Environment values live in:

infrastructure/helm/gitdevops/values-sit.yaml
infrastructure/helm/gitdevops/values-hlg.yaml
infrastructure/helm/gitdevops/values-prd.yaml

Argo CD uses an ApplicationSet to generate one Application per environment. Kargo tracks the Docker image through a declarative Warehouse and promotes Freight through sit -> hlg -> prd stages.

About

A study project exploring containers, K3s, Argo CD, Kargo, and GitOps

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages