Skip to main content

Overview

This guide walks through adding a new service to the platform. You’ll create the application code, Dockerfile, Kubernetes manifests, and CI/CD configuration.

Create the Service

1

Create the service directory

mkdir -p services/my-new-service
cd services/my-new-service
2

Add your application code

Create your application. For example, a Go service:
go mod init my-new-service
mkdir cmd
Create cmd/main.go:
package main

import (
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("ok"))
    })

    log.Println("Starting server on :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}
3

Create a Dockerfile

Create Dockerfile:
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o server ./cmd

FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /app/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]
4

Create mise.toml for service configuration

Create mise.toml:
[env]
# Replace with your AWS account ID and region
IMAGE_REPO = "<ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/services/my-new-service"
SERVICE_RELEASE_TAG = "services/my-new-service"

[tasks]
run = "go run ./cmd"
build-image = "docker build ."
5

Test locally

# Run the service
mise run run

# In another terminal, test it
curl http://localhost:8080/health

Create ECR Repository

Add the new repository to the ECR configuration:
1

Add repository to the list

Edit terraform/live/shared/<REGION>/ecr-repositories/main.tf and add your service to the local.repos list:
locals {
  region = var.aws_region
  repos = [
    "services/container-only-dummy",
    "services/go-backend",
    "services/go-backend/migrations",
    "services/go-backend-no-migrations",
    "services/my-new-service"  # Add this
  ]
}
2

Apply the Terraform change

Commit and open a PR. The Terramate workflow will run a preview, and once merged, the ECR repository will be created.Alternatively, apply directly:
cd terraform
terramate run --tags ecr -- terraform apply

Create Kubernetes Manifests

Choose your preferred templating approach. The kit demonstrates three options.

Add mise Tasks for Rendering

Create kubernetes/src/services/my-new-service/mise.toml:
[tasks.render-cluster]
description = "Render manifests for a specific cluster"
usage = "arg '<cluster>' help='Target cluster (staging, production)'"
run = '''
#!/usr/bin/env bash
set -euo pipefail

CLUSTER="${usage_cluster}"
OUTPUT_DIR="$(git rev-parse --show-toplevel)/kubernetes/rendered/${CLUSTER}/services/my-new-service"

mise run //tools:render:prep-output-dir "$OUTPUT_DIR"

helm template my-new-service . \
  --namespace my-new-service \
  --values values.yaml \
  --values "values.${CLUSTER}.yaml" \
  | mise run //tools:render:split-k8s-docs "$OUTPUT_DIR"
'''

Register with ArgoCD

Add the service to the ArgoCD services app-of-apps:
1

Add to services values

Edit kubernetes/src/argocd/services/values.yaml:
applications:
  go-backend:
    enabled: true
  go-backend-helm:
    enabled: true
  my-new-service:
    enabled: true  # Add this
2

Render ArgoCD manifests

mise run //kubernetes/src/argocd:render-all "<CLUSTER>" # Adds the ArgoCD Application to the app-of-apps
mise run //kubernetes/src/services:render-all "<CLUSTER>" # Renders the service manifests

Add to CI/CD

1

Add path filter

Edit .github/utils/file-filters.yaml:
services/my-new-service:
  - 'services/my-new-service/**'
2

Add to workflow inputs

Edit .github/workflows/ci-build-push.yml:
inputs:
  service:
    options:
      - services/go-backend
      - services/my-new-service  # Add this
Also update .github/workflows/gitops-update-manifests.yml.

Test Locally

1

Add to Tilt

Edit kubernetes/src/services/Tiltfile to include your new service:
# Add your service
load_dynamic('./my-new-service/Tiltfile')
Create kubernetes/src/services/my-new-service/Tiltfile following the pattern of existing services.
2

Start Tilt

cd local
mise run tilt-up
3

Verify the service

Access via the sslip.io URL or port-forward:
kubectl port-forward svc/my-new-service -n my-new-service 8080:80
curl http://localhost:8080/health

Deploy to Staging

1

Commit and push

git add .
git commit -m "feat: add my-new-service"
git push origin main
2

Monitor the deployment

  1. Watch the CI workflow build the image
  2. Watch the GitOps workflow update manifests
  3. Check ArgoCD for the new Application

Next Steps