Skip to content

Latest commit

 

History

History
178 lines (130 loc) · 5.04 KB

File metadata and controls

178 lines (130 loc) · 5.04 KB

Dev Workflow

This document describes the local development workflow used to test the full release pipeline end-to-end before pushing a real Git tag to GitHub.

The goal is to:

  • reuse the same GitHub Actions release workflow used in production
  • build container images locally with act
  • load them into a local kind cluster
  • deploy the service using Helm templating only (no Helm state, no releases)

Start a kind cluster

This step creates a local Kubernetes cluster using kind.

Skip this section if you already have a kind cluster up and running.

The cluster exposes a few container ports to the host to make local development and testing easier.

kind get kubeconfig >/dev/null 2>&1 || \
    cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30081
    hostPort: 30081
    listenAddress: "127.0.0.1"
    protocol: TCP
  - containerPort: 30082
    hostPort: 30082
    listenAddress: "127.0.0.1"
    protocol: TCP
  - containerPort: 30084
    hostPort: 30084
    listenAddress: "127.0.0.1"
    protocol: TCP
  - containerPort: 5432
    hostPort: 30083
    listenAddress: "127.0.0.1"
    protocol: TCP
EOF

## Running the GitHub release pipeline locally

Before running the release workflow, we compute a few environment variables and persist them into a .env.dev file.

This file acts as a single source of truth for:

  • the image tag
  • the image repository
  • the kind cluster name

It can be reused by subsequent steps and other scripts.

TAG="${1:-0.0.8}"
CLUSTER_NAME="kind"
NAMESPACE="eventstack-system"
REPO="ghcr.io/$(git config --get remote.origin.url | sed -E 's#.*[:/](.*)/(.*)\.git#\1/\2#')"
IMAGE="${REPO}:${TAG}"

cat > .env.dev <<EOF
# Generated by local release test script
# $(date -u)

TAG=${TAG}
CLUSTER_NAME=${CLUSTER_NAME}
NAMESPACE=${NAMESPACE}
REPO=${REPO}
IMAGE=${IMAGE}
EOF

Build the release image via act (no push)

In this step we use act to execute the same GitHub Actions workflow used in production to build the release image.

Key points:

  • the workflow is triggered as if a Git tag was pushed
  • the image is built locally
  • the image is not pushed to GHCR

This allows us to validate the release pipeline without touching any remote registry.

export $(grep -v '^#' .env | xargs)

act push \
  -W .github/workflows/release-image.yml \
  --env GITHUB_REF=refs/tags/${TAG} \
  --env DOCKER_PUSH=false \
  --env LOCAL_KIND=true

Load images into kind

Images built by act exist only in the local Docker daemon.

Since kind runs Kubernetes nodes inside Docker containers, the images must be explicitly loaded into the kind cluster so that Pods can start without pulling from a remote registry.

Both the versioned tag and the latest tag are loaded to match different deployment configurations.

export $(grep -v '^#' .env | xargs)

kind load docker-image "${IMAGE}" "${REPO}:latest" --name "${CLUSTER_NAME}"

Database credentials

This chart expects an existing Kubernetes Secret containing the database credentials.

Required secret

The secret must exist before installing the chart.

Note: In production, you should avoid using inline secrets directly in commands.

Instead, consider using environment files, external secret management, or Helm overrides.

export $(grep -v '^#' .env | xargs)

# Ensure namespace exists
kubectl get namespace ${NAMESPACE} >/dev/null 2>&1 || kubectl create namespace ${NAMESPACE}

# Create or update DB secret
kubectl create secret generic eventrouter-db \
  --from-literal=DB_USER="test" --from-literal=DB_PASS="test" \
  --namespace ${NAMESPACE} \
  --dry-run=client -o yaml | kubectl apply -f -
  • eventrouter-db → must match .Values.secret.name in the Helm chart
  • --namespace demo-system → must match .Values.namespace

Recommended for production

  • Store credentials in a .env file:
  • Create the secret from the file:
export $(grep -v '^#' .env | xargs)

kubectl create secret generic eventrouter-db \
  --from-env-file=dev.env \
  --namespace ${NAMESPACE}

This avoids exposing secrets directly on the command line.

Deploy the service using the production Helm Chart (templating only)

The service is deployed using the same Helm chart used in production, but only via templating.

Helm is used exclusively to:

  • render Kubernetes manifests
  • inject environment-specific values

No helm install or helm upgrade is performed.

All resources are applied using kubectl apply, keeping full control over the manifests and avoiding Helm state in the cluster.

export $(grep -v '^#' .env | xargs)

helm template deviser ./chart \
  -n ${NAMESPACE} \
  --set image.repository=${REPO} \
  --set image.tag=${TAG} \
  --set image.pullPolicy=Never \
  -f "./chart/values.dev.yaml" | kubectl apply -f -