diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e7300d23..91c99ea7 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,11 +3,14 @@ # When adding a new Helm chart that depends on the Replicated SDK, # add a corresponding entry here so Dependabot keeps it up to date. # +# NOTE: Dependabot requires unique (ecosystem, directory) pairs, so we +# use a single entry with groups to separate Replicated SDK updates from +# everything else. Both follow a weekly cadence as a result. +# version: 2 updates: - # Track the Replicated SDK on a weekly cadence - package-ecosystem: "helm" - directories: &helm-dirs + directories: - "/applications/fake-services/app" - "/applications/mlflow/charts/mlflow" - "/applications/n8n/charts/n8n" @@ -17,21 +20,10 @@ updates: - "/applications/wg-easy/charts/wg-easy" schedule: interval: "weekly" - allow: - - dependency-name: "replicated" groups: replicated-sdk: patterns: - "replicated" - - # Track all other Helm dependencies on a monthly cadence - - package-ecosystem: "helm" - directories: *helm-dirs - schedule: - interval: "monthly" - ignore: - - dependency-name: "replicated" - groups: all-other-deps: - patterns: - - "*" + exclude-patterns: + - "replicated" diff --git a/.github/workflows/flagd-ci.yml b/.github/workflows/flagd-ci.yml index babf63a9..5d7e0605 100644 --- a/.github/workflows/flagd-ci.yml +++ b/.github/workflows/flagd-ci.yml @@ -55,10 +55,18 @@ jobs: fi echo "Checksum changed: $CHECKSUM_BEFORE -> $CHECKSUM_AFTER" + check-secret: + runs-on: ubuntu-22.04 + outputs: + has-token: ${{ steps.check.outputs.has-token }} + steps: + - id: check + run: echo "has-token=${{ secrets.REPLICATED_PLATFORM_EXAMPLES_TOKEN != '' }}" >> "$GITHUB_OUTPUT" + helm-install-test: runs-on: ubuntu-22.04 - needs: [lint-and-template] - if: ${{ secrets.REPLICATED_PLATFORM_EXAMPLES_TOKEN != '' }} + needs: [lint-and-template, check-secret] + if: needs.check-secret.outputs.has-token == 'true' defaults: run: working-directory: applications/flagd diff --git a/.github/workflows/gitlab-ci.yml b/.github/workflows/gitlab-ci.yml new file mode 100644 index 00000000..fbd90333 --- /dev/null +++ b/.github/workflows/gitlab-ci.yml @@ -0,0 +1,134 @@ +name: GitLab CI + +# Security note: GITLAB_REPLICATED_API_TOKEN must be from a dedicated service account, +# NOT a personal token. Create one at: vendor.replicated.com > +# Account Settings > Service Accounts. + +on: + pull_request: + paths: + - 'applications/gitlab/charts/**' + - 'applications/gitlab/kots/**' + - 'applications/gitlab/tests/**' + - 'applications/gitlab/Makefile' + - '.github/workflows/gitlab-ci.yml' + push: + branches: + - main + paths: + - 'applications/gitlab/charts/**' + - 'applications/gitlab/kots/**' + - 'applications/gitlab/tests/**' + - 'applications/gitlab/Makefile' + - '.github/workflows/gitlab-ci.yml' + +env: + APP_SLUG: gitlab-pika + +jobs: + lint-and-template: + runs-on: ubuntu-22.04 + defaults: + run: + working-directory: applications/gitlab + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Helm + uses: azure/setup-helm@v4.3.0 + with: + version: v3.13.3 + + - name: Add Helm repositories + run: make add-helm-repositories + + - name: Update dependencies + run: make update-dependencies + + - name: Helm lint + run: helm lint ./charts/gitlab + + - name: Helm template + run: helm template gitlab ./charts/gitlab -f tests/helm/ci-values.yaml > /dev/null + + create-release: + if: github.event_name == 'pull_request' + runs-on: ubuntu-22.04 + needs: [lint-and-template] + defaults: + run: + working-directory: applications/gitlab + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Helm + uses: azure/setup-helm@v4.3.0 + with: + version: v3.13.3 + + - name: Set release version + id: set-release-version + run: | + git_hash=$(git rev-parse --short HEAD) + version="0.1.0-pr.${{ github.event.pull_request.number }}.${git_hash}" + echo "VERSION=${version}" >> $GITHUB_ENV + + - name: Add Helm repositories + run: make add-helm-repositories + + - name: Package Helm chart into kots/ + run: helm package ./charts/gitlab --version ${{ env.VERSION }} -u -d kots/ + + - name: Create Replicated release on Unstable + uses: replicatedhq/compatibility-actions/create-release@v1 + with: + app-slug: ${{ env.APP_SLUG }} + api-token: ${{ secrets.GITLAB_REPLICATED_API_TOKEN }} + yaml-dir: applications/gitlab/kots + version: ${{ env.VERSION }} + promote-channel: Unstable + + promote-stable: + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + runs-on: ubuntu-22.04 + needs: [lint-and-template] + defaults: + run: + working-directory: applications/gitlab + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Helm + uses: azure/setup-helm@v4.3.0 + with: + version: v3.13.3 + + - name: Set release version + id: set-release-version + run: | + git_hash=$(git rev-parse --short HEAD) + date_version=$(date -u '+%Y.%-m.%-d-%H%M%S') + version="${date_version}-${git_hash}" + echo "VERSION=${version}" >> $GITHUB_ENV + + - name: Add Helm repositories + run: make add-helm-repositories + + - name: Package Helm chart into kots/ + run: helm package ./charts/gitlab --version ${{ env.VERSION }} -u -d kots/ + + - name: Create release and promote to Stable + uses: replicatedhq/compatibility-actions/create-release@v1 + with: + app-slug: ${{ env.APP_SLUG }} + api-token: ${{ secrets.GITLAB_REPLICATED_API_TOKEN }} + yaml-dir: applications/gitlab/kots + version: ${{ env.VERSION }} + promote-channel: Stable diff --git a/applications/gitlab/.cluster-id b/applications/gitlab/.cluster-id new file mode 100644 index 00000000..9365f796 --- /dev/null +++ b/applications/gitlab/.cluster-id @@ -0,0 +1 @@ +44637dd1 diff --git a/applications/gitlab/.envrc.example b/applications/gitlab/.envrc.example new file mode 100644 index 00000000..657ff58a --- /dev/null +++ b/applications/gitlab/.envrc.example @@ -0,0 +1,23 @@ +# Copy this file to .envrc and fill in your values, then run `direnv allow`. +# .envrc is git-ignored so your credentials stay local. +# +# Install direnv: https://direnv.net/docs/installation.html + +# Your Replicated Vendor Portal API token. +# Create one at: vendor.replicated.com > Account Settings > API Tokens +# For CI, use a dedicated service account token instead of a personal token. +export REPLICATED_API_TOKEN= + +# Your Replicated app slug (shown in the Vendor Portal URL and app settings). +# Example: my-app-slug +export REPLICATED_APP= + +# (Optional) License ID for testing the customer Helm install flow. +# This is the `installationId` field from `replicated customer create --output json`, +# NOT the top-level `id` field. Used with `helm registry login` and +# `--set global.replicated.licenseID=` during CMX validation. +export REPLICATED_LICENSE_ID= + +# (Optional) Customer email associated with the license above. +# Used as the username for `helm registry login registry.replicated.com`. +export REPLICATED_CUSTOMER_EMAIL= diff --git a/applications/gitlab/.gitignore b/applications/gitlab/.gitignore new file mode 100644 index 00000000..a3573c31 --- /dev/null +++ b/applications/gitlab/.gitignore @@ -0,0 +1 @@ +kots/*.tgz diff --git a/applications/gitlab/Makefile b/applications/gitlab/Makefile new file mode 100644 index 00000000..08ded6de --- /dev/null +++ b/applications/gitlab/Makefile @@ -0,0 +1,114 @@ +.PHONY: add-helm-repositories update-dependencies lint package release \ + cluster-create cluster-delete setup-deps teardown-deps install uninstall + +PG_PASSWORD ?= gitlab-pg-pass +REDIS_PASSWORD ?= gitlab-redis-pass + +CHART_DIR := charts/gitlab +CLUSTER_NAME ?= gitlab-cmx +CMX_DISTRIBUTION ?= k3s +CMX_VERSION ?= 1.32 +CMX_INSTANCE ?= r1.xlarge +CMX_DISK ?= 100 +CMX_TTL ?= 4h +CLUSTER_ID_FILE := .cluster-id + +add-helm-repositories: + helm repo add gitlab https://charts.gitlab.io/ + helm repo update + +update-dependencies: + helm dependency update $(CHART_DIR) + +lint: + helm lint $(CHART_DIR) + helm template gitlab $(CHART_DIR) -f tests/helm/ci-values.yaml > /dev/null + +package: update-dependencies + helm package $(CHART_DIR) -d kots/ + +release: package + REPLICATED_API_TOKEN=$(REPLICATED_API_TOKEN) replicated release create \ + --app $(REPLICATED_APP) \ + --yaml-dir kots \ + --promote Unstable \ + --release-notes "Release via Makefile" + +# CMX cluster management +cluster-create: + @echo "Creating CMX cluster '$(CLUSTER_NAME)'..." + replicated cluster create \ + --distribution $(CMX_DISTRIBUTION) \ + --version $(CMX_VERSION) \ + --instance-type $(CMX_INSTANCE) \ + --disk $(CMX_DISK) \ + --ttl $(CMX_TTL) \ + --name $(CLUSTER_NAME) \ + --wait 10m \ + --output json | jq -r '.id' > $(CLUSTER_ID_FILE) + replicated cluster kubeconfig $$(cat $(CLUSTER_ID_FILE)) + @echo "Cluster ready. ID: $$(cat $(CLUSTER_ID_FILE))" + +cluster-delete: + @test -f $(CLUSTER_ID_FILE) || (echo "No $(CLUSTER_ID_FILE) found. Run 'make cluster-create' first."; exit 1) + replicated cluster rm $$(cat $(CLUSTER_ID_FILE)) + rm -f $(CLUSTER_ID_FILE) + +# In-cluster PostgreSQL and Redis for CMX testing (not for production) +setup-deps: + helm repo add bitnami https://charts.bitnami.com/bitnami + helm repo update + kubectl create namespace gitlab --dry-run=client -o yaml | kubectl apply -f - + helm upgrade --install postgresql bitnami/postgresql \ + --namespace gitlab \ + --set fullnameOverride=external-postgresql \ + --set auth.username=gitlab \ + --set auth.password=$(PG_PASSWORD) \ + --set auth.database=gitlabhq_production \ + --set primary.resourcesPreset=none \ + --set primary.resources.requests.memory=1Gi \ + --set primary.resources.limits.memory=2Gi \ + --wait + helm upgrade --install redis bitnami/redis \ + --namespace gitlab \ + --set fullnameOverride=external-redis \ + --set architecture=standalone \ + --set auth.password=$(REDIS_PASSWORD) \ + --wait + kubectl create secret generic gitlab-external-pg-password \ + --from-literal=password=$(PG_PASSWORD) \ + --namespace gitlab \ + --dry-run=client -o yaml | kubectl apply -f - + kubectl create secret generic gitlab-external-redis-password \ + --from-literal=redis-password=$(REDIS_PASSWORD) \ + --namespace gitlab \ + --dry-run=client -o yaml | kubectl apply -f - + @echo "Granting superuser to gitlab DB user so migrations can CREATE EXTENSION..." + kubectl exec -n gitlab pod/external-postgresql-0 -- \ + env PGPASSWORD=$$(kubectl get secret external-postgresql -n gitlab \ + -o jsonpath='{.data.postgres-password}' | base64 -d) \ + psql -U postgres -c "ALTER USER gitlab SUPERUSER;" + +teardown-deps: + helm uninstall postgresql --namespace gitlab --ignore-not-found + helm uninstall redis --namespace gitlab --ignore-not-found + +# Helm install / uninstall (customer flow via Replicated OCI registry) +install: + @test -n "$(REPLICATED_CUSTOMER_EMAIL)" || (echo "REPLICATED_CUSTOMER_EMAIL is not set"; exit 1) + @test -n "$(REPLICATED_LICENSE_ID)" || (echo "REPLICATED_LICENSE_ID is not set"; exit 1) + helm registry login registry.replicated.com \ + --username $(REPLICATED_CUSTOMER_EMAIL) \ + --password $(REPLICATED_LICENSE_ID) + helm install gitlab \ + oci://registry.replicated.com/$(REPLICATED_APP)/unstable/gitlab \ + --namespace gitlab \ + --create-namespace \ + --set global.replicated.licenseID=$(REPLICATED_LICENSE_ID) \ + -f tests/helm/cmx-deploy-values.yaml \ + --timeout 20m \ + --wait + +uninstall: + helm uninstall gitlab --namespace gitlab + kubectl delete namespace gitlab --ignore-not-found diff --git a/applications/gitlab/README.md b/applications/gitlab/README.md new file mode 100644 index 00000000..5f7e6898 --- /dev/null +++ b/applications/gitlab/README.md @@ -0,0 +1,321 @@ +# GitLab Platform Example + +This example demonstrates how to deploy [GitLab](https://gitlab.com) — The One DevSecOps Platform — using Replicated's [Embedded Cluster](https://docs.replicated.com/vendor/embedded-overview) and [Compatibility Matrix](https://docs.replicated.com/vendor/testing-about). + +## Architecture Overview + +GitLab is a complex, multi-component application. This example uses the [official GitLab Helm chart](https://docs.gitlab.com/charts/) wrapped with the Replicated SDK. + +### Components + +| Component | Purpose | Default | +|-----------|---------|---------| +| GitLab Webservice | Web UI and API | Bundled | +| GitLab Sidekiq | Background jobs | Bundled | +| GitLab KAS | Kubernetes Agent Server | Bundled | +| GitLab Shell | SSH access | Bundled | +| PostgreSQL | Primary database | Bundled (eval) | +| Redis | Cache, sessions, queues | Bundled (eval) | +| MinIO | Object storage | Bundled (eval) | +| Registry | Container registry | Bundled | +| NGINX Ingress | Ingress controller | Via EC extension | +| cert-manager | TLS certificates | Via EC extension | + +### Production Considerations + +> **WARNING**: The bundled PostgreSQL, Redis, and MinIO are **deprecated** and will be +> removed in GitLab 19.0. For production deployments, use external services. + +**Production requirements:** +- External PostgreSQL 16+ with extensions: `amcheck`, `pg_trgm`, `btree_gist` +- External Redis/Valkey (HA configuration recommended) +- External S3-compatible object storage (many buckets required) +- Minimum 2 nodes: 8 vCPU total, 30 GB RAM +- **Gitaly cannot run in Kubernetes** for production — must use VMs/bare metal + +**Evaluation minimum:** 4 vCPU, 12 GB RAM, 100 GB disk + +## Prerequisites + +1. [Replicated Vendor Portal Account](https://vendor.replicated.com/signup) +2. [Replicated CLI](https://docs.replicated.com/reference/replicated-cli-installing) +3. CMX Credits (minimum: `r1.large` or equivalent) +4. Environment variables set (see [direnv setup](#environment-setup-direnv) below) + +## Environment Setup (direnv) + +Copy the example env file, fill in your values, then allow direnv to load it: + +```bash +cp .envrc.example .envrc +# Edit .envrc with your REPLICATED_API_TOKEN and REPLICATED_APP +direnv allow +``` + +`.envrc` is git-ignored. If you don't use direnv, export the variables manually: + +```bash +export REPLICATED_API_TOKEN= +export REPLICATED_APP= +``` + +Install direnv: https://direnv.net/docs/installation.html + +## Quick Start + +### 1. Add Helm repositories and update dependencies + +```bash +cd applications/gitlab +make add-helm-repositories +make update-dependencies +``` + +### 2. Lint the chart + +```bash +helm lint charts/gitlab +helm template gitlab charts/gitlab -f tests/helm/ci-values.yaml > /dev/null +``` + +Or via `make lint`. + +### 3. Create a release and promote to Unstable + +Package the chart and push a release to the [Replicated Vendor Portal](https://vendor.replicated.com): + +```bash +helm package charts/gitlab -d kots/ + +replicated release create \ + --app $REPLICATED_APP \ + --yaml-dir kots \ + --promote Unstable \ + --release-notes "Initial release" +``` + +Or via `make release`. + +### 4. Create a customer and set license env vars + +```bash +replicated customer create \ + --app $REPLICATED_APP \ + --name my-customer \ + --channel Unstable \ + --type dev \ + --email customer@example.com \ + --expires-in 72h \ + --output json +``` + +Note the `installationId` from the output — this is the license ID used for +registry authentication. Add it to your `.envrc`: + +```bash +export REPLICATED_LICENSE_ID= +export REPLICATED_CUSTOMER_EMAIL=customer@example.com +direnv allow +``` + +### 5. Create a CMX cluster + +Use the [Replicated Compatibility Matrix](https://docs.replicated.com/vendor/testing-about) to provision a cluster: + +```bash +replicated cluster create \ + --distribution k3s \ + --version 1.32 \ + --instance-type r1.xlarge \ + --disk 100 \ + --ttl 4h \ + --name gitlab-cmx \ + --wait 10m \ + --output json | jq -r '.id' > .cluster-id + +replicated cluster kubeconfig $(cat .cluster-id) +kubectl cluster-info # verify connectivity +``` + +Or via `make cluster-create` (uses the same commands with overridable defaults). + +### 6. Deploy in-cluster PostgreSQL and Redis + +`tests/helm/cmx-deploy-values.yaml` requires external PostgreSQL and Redis — the GitLab chart's bundled Bitnami images were removed from Docker Hub. Deploy them into the cluster using the Bitnami Helm charts before installing GitLab: + +```bash +helm repo add bitnami https://charts.bitnami.com/bitnami +helm repo update + +# Deploy PostgreSQL 16 with the service name GitLab expects +helm upgrade --install postgresql bitnami/postgresql \ + --namespace gitlab \ + --create-namespace \ + --set fullnameOverride=external-postgresql \ + --set auth.username=gitlab \ + --set auth.password=gitlab-pg-pass \ + --set auth.database=gitlabhq_production \ + --set primary.resourcesPreset=none \ + --set primary.resources.requests.memory=1Gi \ + --set primary.resources.limits.memory=2Gi \ + --wait + +# Deploy Redis 7 (standalone) +# The Bitnami chart always creates the service as -master, +# which matches the redis.host value in cmx-deploy-values.yaml (external-redis-master) +helm upgrade --install redis bitnami/redis \ + --namespace gitlab \ + --set fullnameOverride=external-redis \ + --set architecture=standalone \ + --set auth.password=gitlab-redis-pass \ + --wait + +# Create the secrets GitLab reads for credentials +kubectl create secret generic gitlab-external-pg-password \ + --from-literal=password=gitlab-pg-pass \ + --namespace gitlab + +kubectl create secret generic gitlab-external-redis-password \ + --from-literal=redis-password=gitlab-redis-pass \ + --namespace gitlab + +# Grant superuser to the gitlab DB user so migrations can CREATE EXTENSION +# (pg_trgm, btree_gist, amcheck — required by GitLab migrations) +# The Bitnami chart creates a non-superuser by default; the postgres superuser +# password is stored in the chart-generated secret. +kubectl exec -n gitlab pod/external-postgresql-0 -- \ + env PGPASSWORD=$(kubectl get secret external-postgresql -n gitlab \ + -o jsonpath='{.data.postgres-password}' | base64 -d) \ + psql -U postgres -c "ALTER USER gitlab SUPERUSER;" +``` + +> - `fullnameOverride` ensures the Kubernetes service names match `psql.host` and `redis.host` in `cmx-deploy-values.yaml`. +> - The superuser grant is required because GitLab migrations run `CREATE EXTENSION` statements, which require superuser in PostgreSQL. + +Or via `make setup-deps` (uses the same commands; override passwords with `PG_PASSWORD` and `REDIS_PASSWORD`). + +### 7. Install GitLab + +Authenticate to the Replicated OCI registry and install: + +```bash +helm registry login registry.replicated.com \ + --username $REPLICATED_CUSTOMER_EMAIL \ + --password $REPLICATED_LICENSE_ID + +helm install gitlab \ + oci://registry.replicated.com/$REPLICATED_APP/unstable/gitlab \ + --namespace gitlab \ + --create-namespace \ + --set global.replicated.licenseID=$REPLICATED_LICENSE_ID \ + -f tests/helm/cmx-deploy-values.yaml \ + --timeout 20m \ + --wait +``` + +Or via `make install`. + +### 8. Access the GitLab UI + +The chart deploys an nginx ingress controller with `gitlab.example.com` as the domain (see `tests/helm/cmx-deploy-values.yaml`). Port-forward the ingress controller and add a local hosts entry to access it: + +```bash +# Add a hosts entry (requires sudo) +echo "127.0.0.1 gitlab.example.com" | sudo tee -a /etc/hosts + +# Port-forward the nginx ingress controller +kubectl port-forward svc/gitlab-nginx-ingress-controller 8080:80 -n gitlab +``` + +Open http://gitlab.example.com:8080 in your browser. + +To get the initial root password: + +```bash +kubectl get secret gitlab-gitlab-initial-root-password -n gitlab \ + -o jsonpath='{.data.password}' | base64 --decode +``` + +Sign in as `root` with that password. + +### 9. Clean up + +```bash +helm uninstall gitlab --namespace gitlab +helm uninstall postgresql --namespace gitlab +helm uninstall redis --namespace gitlab +kubectl delete namespace gitlab --ignore-not-found + +replicated cluster rm $(cat .cluster-id) +rm .cluster-id +``` + +Or via `make uninstall && make teardown-deps && make cluster-delete`. + +### Deploy with Embedded Cluster + +Create a customer and download a license, then: + +```bash +replicated cluster create \ + --distribution embedded-cluster \ + --instance-type r1.xlarge \ + --disk 100 \ + --license-id \ + --ttl 4h \ + --name gitlab-test + +replicated cluster shell +# Inside the shell: +kubectl port-forward svc/kotsadm 3000:3000 -n kotsadm +``` + +Navigate to `http://localhost:3000` and configure GitLab via the KOTS admin console. + +**Important notes:** +- The registry password is the `installationId` (license ID), NOT the customer `id`. +- The OCI URL format is `oci://registry.replicated.com///`. +- The GitLab chart's bundled Bitnami PostgreSQL/Redis images have been removed from + Docker Hub. You must provide external PostgreSQL 16+ and Redis 7+ services. + See `tests/helm/cmx-deploy-values.yaml` for an example configuration. + +## Directory Structure + +``` +applications/gitlab/ +├── charts/ +│ └── gitlab/ +│ ├── Chart.yaml # Wrapper chart with SDK + upstream gitlab subchart +│ ├── Chart.lock # Locked dependency versions +│ ├── values.yaml # Default values with global.replicated block +│ ├── replicated-app.yaml # Replicated Application CRD +│ └── templates/ # Custom templates (empty — uses subchart) +├── kots/ +│ ├── kots-app.yaml # KOTS Application manifest +│ ├── kots-config.yaml # User-facing configuration options +│ ├── gitlab-chart.yaml # HelmChart mapping config → helm values +│ ├── ec.yaml # Embedded Cluster extensions +│ └── k8s-app.yaml # Kubernetes Application CRD +├── tests/ +│ └── helm/ +│ ├── ci-values.yaml # Minimal values for CI lint/template checks +│ └── cmx-deploy-values.yaml # Values for CMX cluster deployment (external PG + Redis) +├── Makefile +└── README.md +``` + +## Known Limitations + +See [ONBOARDING-GAPS.md](../../ONBOARDING-GAPS.md) for gaps and friction discovered during onboarding. + +- **CMX validation passed**: Helm CLI customer install validated via OCI registry on k3s 1.32 (r1.xlarge). All pods healthy. Replicated SDK running. +- **Bundled Bitnami images removed**: The GitLab chart's bundled PostgreSQL and Redis depend on Bitnami Docker Hub images that have been removed. You MUST provide external PostgreSQL and Redis. See `tests/helm/cmx-deploy-values.yaml`. +- **Gitaly in K8s**: The bundled evaluation mode runs Gitaly in Kubernetes, which is not supported for production. A cloud-native hybrid architecture (stateless K8s + external stateful services) is recommended for production. +- **Resource requirements**: GitLab is significantly more resource-intensive than other examples in this repo. Minimum eval cluster: 4 vCPU, 12 GB RAM. + +## References + +- [GitLab Helm chart docs](https://docs.gitlab.com/charts/) +- [GitLab chart repository](https://gitlab.com/gitlab-org/charts/gitlab) +- [Replicated SDK docs](https://docs.replicated.com/vendor/replicated-sdk-installing) +- [Embedded Cluster docs](https://docs.replicated.com/vendor/embedded-overview) diff --git a/applications/gitlab/charts/gitlab/.gitignore b/applications/gitlab/charts/gitlab/.gitignore new file mode 100644 index 00000000..aef3bcd7 --- /dev/null +++ b/applications/gitlab/charts/gitlab/.gitignore @@ -0,0 +1,2 @@ +# Helm dependency tarballs — fetched at build time via helm dependency update +charts/*.tgz diff --git a/applications/gitlab/charts/gitlab/Chart.lock b/applications/gitlab/charts/gitlab/Chart.lock new file mode 100644 index 00000000..b7db91b2 --- /dev/null +++ b/applications/gitlab/charts/gitlab/Chart.lock @@ -0,0 +1,9 @@ +dependencies: +- name: gitlab + repository: https://charts.gitlab.io/ + version: 9.0.2 +- name: replicated + repository: oci://registry.replicated.com/library + version: 1.18.0 +digest: sha256:461d0fe54f5029c9137a81a2ca273f15011615eb03d14615292cc8dcb1ab669d +generated: "2026-03-22T14:36:32.670592-04:00" diff --git a/applications/gitlab/charts/gitlab/Chart.yaml b/applications/gitlab/charts/gitlab/Chart.yaml new file mode 100644 index 00000000..b9613d84 --- /dev/null +++ b/applications/gitlab/charts/gitlab/Chart.yaml @@ -0,0 +1,26 @@ +apiVersion: v2 +name: gitlab +description: GitLab - The One DevSecOps Platform +type: application +version: 0.1.0 +appVersion: "18.0.0" +icon: https://about.gitlab.com/images/press/logo/svg/gitlab-logo-500.svg +keywords: + - gitlab + - devops + - ci/cd + - git + - code review + - issue tracker +sources: + - https://gitlab.com/gitlab-org/charts/gitlab +home: https://gitlab.com +dependencies: + - name: gitlab + version: "9.0.2" + repository: "https://charts.gitlab.io/" + condition: gitlab.enabled + - name: replicated + repository: oci://registry.replicated.com/library + version: "1.18.0" + condition: replicated.enabled diff --git a/applications/gitlab/charts/gitlab/replicated-app.yaml b/applications/gitlab/charts/gitlab/replicated-app.yaml new file mode 100644 index 00000000..f6b4240e --- /dev/null +++ b/applications/gitlab/charts/gitlab/replicated-app.yaml @@ -0,0 +1,7 @@ +apiVersion: kots.io/v1beta1 +kind: Application +metadata: + name: gitlab-pika +spec: + title: GitLab + icon: "https://about.gitlab.com/images/press/logo/svg/gitlab-logo-500.svg" diff --git a/applications/gitlab/charts/gitlab/templates/.gitkeep b/applications/gitlab/charts/gitlab/templates/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/applications/gitlab/charts/gitlab/values.yaml b/applications/gitlab/charts/gitlab/values.yaml new file mode 100644 index 00000000..28a8c732 --- /dev/null +++ b/applications/gitlab/charts/gitlab/values.yaml @@ -0,0 +1,104 @@ +# GitLab Helm Chart Values +# This wraps the upstream GitLab chart with Replicated SDK integration. +# See https://docs.gitlab.com/charts/ for full documentation. + +# -- Enable/disable the upstream GitLab chart +gitlab: + enabled: true + + # Global configuration for the upstream chart + global: + # -- Domain configuration + hosts: + # -- The base domain for GitLab. All subdomains will be derived from this. + domain: "" + # -- External IP address for ingress + externalIP: "" + + # -- GitLab edition: 'ce' (Community) or 'ee' (Enterprise) + edition: ce + + # -- Ingress configuration + ingress: + configureCertmanager: true + class: nginx + + # -- PostgreSQL configuration + # Uses external-postgresql service (official postgres:16 image) + # For production: replace host with your external PostgreSQL endpoint + psql: + host: external-postgresql + port: 5432 + database: gitlabhq_production + username: gitlab + password: + secret: gitlab-external-pg-password + key: password + + # -- Redis configuration + # Uses external-redis service (official redis:7 image) + # For production: replace host with your external Redis endpoint + redis: + host: external-redis + port: 6379 + auth: + enabled: true + secret: gitlab-external-redis-password + key: redis-password + + # -- Object storage (MinIO or S3-compatible) + # When using bundled MinIO (eval), leave object_store disabled. + # For production, enable and provide an external S3-compatible connection secret. + appConfig: + object_store: + enabled: false + proxy_download: true + + # -- Bundled MinIO (for evaluation only) + # Note: minio.enabled was removed; the correct location is global.minio.enabled + minio: + enabled: true + + # -- Initial root password (auto-generated if not set) + # Stored in secret: -gitlab-initial-root-password + # key: password + + # -- Bundled PostgreSQL (disabled — use external-postgresql service or cloudnative-pg) + # Set to false to use external PostgreSQL configured via global.psql.* + postgresql: + install: false + + # -- Bundled Redis (disabled — use external-redis service or valkey) + # Set to false to use external Redis configured via global.redis.* + redis: + install: false + + # -- Bundled NGINX ingress controller + nginx-ingress: + enabled: true + + # -- Bundled cert-manager + certmanager: + install: true + installCRDs: false + + # -- cert-manager ClusterIssuer (required even when certmanager.install: false) + certmanager-issuer: + email: example@example.com + + # -- Bundled Prometheus (for evaluation only) + prometheus: + install: true + + # -- Bundled registry + registry: + enabled: true + + # -- GitLab Runner (disabled by default - deploy separately) + gitlab-runner: + install: false + +# -- Replicated SDK configuration (added by install-sdk step) +replicated: + enabled: true + diff --git a/applications/gitlab/kots/ec.yaml b/applications/gitlab/kots/ec.yaml new file mode 100644 index 00000000..587cd7a5 --- /dev/null +++ b/applications/gitlab/kots/ec.yaml @@ -0,0 +1,44 @@ +apiVersion: embeddedcluster.replicated.com/v1beta1 +kind: Config +spec: + version: 2.13.3+k8s-1.33 + extensions: + helm: + repositories: + - name: ingress-nginx + url: https://kubernetes.github.io/ingress-nginx + - name: jetstack + url: https://charts.jetstack.io + - name: cnpg + url: https://cloudnative-pg.github.io/charts + charts: + # NGINX Ingress — GitLab chart requires nginx ingress by default + - name: ingress-nginx + chartname: ingress-nginx/ingress-nginx + namespace: ingress-nginx + version: "4.14.1" + values: | + controller: + service: + type: NodePort + nodePorts: + http: 80 + https: 443 + + # cert-manager — GitLab chart uses cert-manager for TLS + - name: cert-manager + chartname: jetstack/cert-manager + namespace: cert-manager + version: "v1.19.1" + values: | + crds: + enabled: true + prometheus: + enabled: false + + # CloudNativePG — for external PostgreSQL option (production pattern) + # Note: GitLab requires PostgreSQL 16+ with extensions: amcheck, pg_trgm, btree_gist + - name: cloudnative-pg + chartname: cnpg/cloudnative-pg + namespace: cnpg + version: "0.27.0" diff --git a/applications/gitlab/kots/gitlab-chart.yaml b/applications/gitlab/kots/gitlab-chart.yaml new file mode 100644 index 00000000..0ee181b4 --- /dev/null +++ b/applications/gitlab/kots/gitlab-chart.yaml @@ -0,0 +1,111 @@ +apiVersion: kots.io/v1beta2 +kind: HelmChart +metadata: + name: gitlab +spec: + chart: + name: gitlab + chartVersion: 0.1.0 + + values: + gitlab: + enabled: true + + global: + hosts: + domain: repl{{ ConfigOption "gitlab_domain" }} + edition: repl{{ ConfigOption "gitlab_edition" }} + + ingress: + configureCertmanager: repl{{ ConfigOptionEquals "tls_enabled" "1" }} + class: nginx + tls: + enabled: repl{{ ConfigOptionEquals "tls_enabled" "1" }} + + psql: + database: repl{{ ConfigOption "postgres_db" }} + username: repl{{ ConfigOption "postgres_user" }} + password: + secret: gitlab-postgresql-password + key: postgresql-password + + redis: + auth: + enabled: true + + registry: + enabled: true + + gitlab-runner: + install: false + + replicated: + enabled: true + + optionalValues: + # External PostgreSQL + - when: 'repl{{ ConfigOptionEquals "internal_postgres_enabled" "0" }}' + recursiveMerge: true + values: + gitlab: + postgresql: + install: false + global: + psql: + host: repl{{ ConfigOption "postgres_host" }} + port: repl{{ ConfigOption "postgres_port" }} + + # Bundled PostgreSQL + - when: 'repl{{ ConfigOptionEquals "internal_postgres_enabled" "1" }}' + recursiveMerge: true + values: + gitlab: + postgresql: + install: true + + # External Redis + - when: 'repl{{ ConfigOptionEquals "internal_redis_enabled" "0" }}' + recursiveMerge: true + values: + gitlab: + redis: + install: false + global: + redis: + host: repl{{ ConfigOption "redis_host" }} + + # Bundled Redis + - when: 'repl{{ ConfigOptionEquals "internal_redis_enabled" "1" }}' + recursiveMerge: true + values: + gitlab: + redis: + install: true + + # External object storage + - when: 'repl{{ ConfigOptionEquals "internal_minio_enabled" "0" }}' + recursiveMerge: true + values: + gitlab: + minio: + enabled: false + global: + appConfig: + object_store: + enabled: true + connection: + secret: repl{{ ConfigOption "object_store_connection_secret" }} + key: connection + + # Bundled MinIO + - when: 'repl{{ ConfigOptionEquals "internal_minio_enabled" "1" }}' + recursiveMerge: true + values: + gitlab: + minio: + enabled: true + + helmUpgradeFlags: + - --timeout + - 20m + - --cleanup-on-fail diff --git a/applications/gitlab/kots/k8s-app.yaml b/applications/gitlab/kots/k8s-app.yaml new file mode 100644 index 00000000..39db0bcd --- /dev/null +++ b/applications/gitlab/kots/k8s-app.yaml @@ -0,0 +1,8 @@ +apiVersion: app.k8s.io/v1beta1 +kind: Application +metadata: + name: "gitlab-pika" +spec: + descriptor: + version: "0.1.0" + description: "GitLab - The One DevSecOps Platform" diff --git a/applications/gitlab/kots/kots-app.yaml b/applications/gitlab/kots/kots-app.yaml new file mode 100644 index 00000000..f9eb9364 --- /dev/null +++ b/applications/gitlab/kots/kots-app.yaml @@ -0,0 +1,13 @@ +apiVersion: kots.io/v1beta1 +kind: Application +metadata: + name: gitlab-pika +spec: + title: GitLab + icon: "https://about.gitlab.com/images/press/logo/svg/gitlab-logo-500.svg" + allowRollback: false + statusInformers: + - deployment/gitlab-webservice-default + - deployment/gitlab-sidekiq-all-in-1-v2 + - deployment/gitlab-kas + - statefulset/gitlab-redis-master diff --git a/applications/gitlab/kots/kots-config.yaml b/applications/gitlab/kots/kots-config.yaml new file mode 100644 index 00000000..d4c5bbe9 --- /dev/null +++ b/applications/gitlab/kots/kots-config.yaml @@ -0,0 +1,155 @@ +apiVersion: kots.io/v1beta1 +kind: Config +metadata: + name: config +spec: + groups: + + # Domain & Access + - name: domain_settings + title: Domain Settings + items: + - name: gitlab_domain + title: GitLab Domain + type: text + required: true + description: The base domain for GitLab (e.g. gitlab.example.com). All subdomains (registry, minio, kas) are derived from this. + - name: gitlab_edition + title: GitLab Edition + type: select_one + default: ce + required: true + description: Community Edition (CE) is free and open source. Enterprise Edition (EE) requires a license. + items: + - name: ce + title: Community Edition (CE) + - name: ee + title: Enterprise Edition (EE) + + # PostgreSQL settings + - name: postgres_settings + title: PostgreSQL Database + description: "WARNING: Bundled PostgreSQL is for evaluation only and will be removed in GitLab 19.0. Use external PostgreSQL 16+ for production." + items: + - name: internal_postgres_enabled + title: Use Bundled PostgreSQL (Eval Only) + type: bool + default: "1" + required: true + description: Deploy bundled PostgreSQL. Deprecated — will be removed in GitLab 19.0. For production, disable and provide external PostgreSQL 16+. + - name: postgres_host + title: External PostgreSQL Host + type: text + required: true + description: Host for external PostgreSQL server (PostgreSQL 16+ required). + when: 'repl{{ ConfigOptionEquals "internal_postgres_enabled" "0" }}' + - name: postgres_port + title: PostgreSQL Port + type: text + default: "5432" + required: true + when: 'repl{{ ConfigOptionEquals "internal_postgres_enabled" "0" }}' + - name: postgres_db + title: PostgreSQL Database Name + type: text + default: gitlabhq_production + required: true + - name: postgres_user + title: PostgreSQL Username + type: text + default: gitlab + required: true + - name: postgres_password + title: PostgreSQL Password + type: password + required: true + secret: true + + # Redis settings + - name: redis_settings + title: Redis / Valkey Cache + description: "WARNING: Bundled Redis is for evaluation only and will be removed in GitLab 19.0. Use external Redis or Valkey for production." + items: + - name: internal_redis_enabled + title: Use Bundled Redis (Eval Only) + type: bool + default: "1" + required: true + description: Deploy bundled Redis. Deprecated — will be removed in GitLab 19.0. For production, disable and provide external Redis/Valkey. + - name: redis_host + title: External Redis Host + type: text + required: true + when: 'repl{{ ConfigOptionEquals "internal_redis_enabled" "0" }}' + - name: redis_password + title: Redis Password + type: password + required: false + secret: true + when: 'repl{{ ConfigOptionEquals "internal_redis_enabled" "0" }}' + + # Object Storage + - name: object_storage_settings + title: Object Storage + description: GitLab requires S3-compatible object storage for artifacts, LFS, packages, uploads, and more. + items: + - name: internal_minio_enabled + title: Use Bundled MinIO (Eval Only) + type: bool + default: "1" + required: true + description: Deploy bundled MinIO for object storage. For production, use external S3-compatible storage. + - name: object_store_connection_secret + title: Object Storage Connection Secret Name + type: text + required: true + when: 'repl{{ ConfigOptionEquals "internal_minio_enabled" "0" }}' + description: Name of the Kubernetes secret containing the S3 connection configuration. + + # TLS / Ingress + - name: ingress_settings + title: Ingress & TLS + items: + - name: tls_enabled + title: Enable TLS + type: bool + default: "1" + description: Enable HTTPS via cert-manager. Requires a valid domain with DNS configured. + - name: certmanager_issuer_email + title: cert-manager ACME Email + type: text + required: false + when: 'repl{{ ConfigOptionEquals "tls_enabled" "1" }}' + description: Email address for Let's Encrypt certificate notifications. + + # SMTP (optional) + - name: smtp_settings + title: Email (SMTP) + items: + - name: smtp_enabled + title: Enable SMTP + type: bool + default: "0" + - name: smtp_host + title: SMTP Host + type: text + when: 'repl{{ ConfigOptionEquals "smtp_enabled" "1" }}' + - name: smtp_port + title: SMTP Port + type: text + default: "587" + when: 'repl{{ ConfigOptionEquals "smtp_enabled" "1" }}' + - name: smtp_user + title: SMTP Username + type: text + when: 'repl{{ ConfigOptionEquals "smtp_enabled" "1" }}' + - name: smtp_password + title: SMTP Password + type: password + secret: true + when: 'repl{{ ConfigOptionEquals "smtp_enabled" "1" }}' + - name: smtp_from + title: Email From Address + type: text + default: gitlab@example.com + when: 'repl{{ ConfigOptionEquals "smtp_enabled" "1" }}' diff --git a/applications/gitlab/kots/kots-preflight.yaml b/applications/gitlab/kots/kots-preflight.yaml new file mode 100644 index 00000000..27796148 --- /dev/null +++ b/applications/gitlab/kots/kots-preflight.yaml @@ -0,0 +1,53 @@ +apiVersion: troubleshoot.sh/v1beta2 +kind: Preflight +metadata: + name: gitlab +spec: + collectors: + - clusterInfo: {} + - clusterResources: {} + analyzers: + - clusterVersion: + outcomes: + - fail: + when: "< 1.26.0" + message: GitLab requires Kubernetes 1.26.0 or later. + uri: https://www.kubernetes.io + - warn: + when: "< 1.30.0" + message: Your cluster meets the minimum version of Kubernetes, but we recommend 1.30.0 or later. + uri: https://kubernetes.io + - pass: + message: Your cluster meets the recommended and required versions of Kubernetes. + + - nodeResources: + checkName: Total CPU Cores (minimum 4 for evaluation) + outcomes: + - fail: + when: "sum(cpuCapacity) < 4" + message: GitLab requires at least 4 CPU cores for evaluation. Production deployments need 8+ cores. + - warn: + when: "sum(cpuCapacity) < 8" + message: GitLab is running with fewer than 8 CPU cores. This is acceptable for evaluation but not recommended for production. + - pass: + message: Cluster has sufficient CPU cores for GitLab. + + - nodeResources: + checkName: Total Memory (minimum 12Gi for evaluation) + outcomes: + - fail: + when: "sum(memoryCapacity) < 12Gi" + message: GitLab requires at least 12Gi of RAM for evaluation. Production deployments need 30Gi+. + - warn: + when: "sum(memoryCapacity) < 30Gi" + message: GitLab is running with less than 30Gi of RAM. This is acceptable for evaluation but not recommended for production. + - pass: + message: Cluster has sufficient memory for GitLab. + + - storageClass: + checkName: Default storage class + outcomes: + - fail: + message: No default storage class found. GitLab requires persistent storage for PostgreSQL, Redis, and object storage. + - pass: + message: Default storage class is available. diff --git a/applications/gitlab/kots/kots-secrets.yaml b/applications/gitlab/kots/kots-secrets.yaml new file mode 100644 index 00000000..229a9a5b --- /dev/null +++ b/applications/gitlab/kots/kots-secrets.yaml @@ -0,0 +1,18 @@ +--- +# Secret for PostgreSQL password — referenced by the GitLab chart +apiVersion: v1 +kind: Secret +metadata: + name: gitlab-postgresql-password +type: Opaque +stringData: + postgresql-password: 'repl{{ ConfigOption "postgres_password" }}' +--- +# Secret for Redis password — referenced by the GitLab chart +apiVersion: v1 +kind: Secret +metadata: + name: gitlab-redis-password +type: Opaque +stringData: + redis-password: 'repl{{ ConfigOption "redis_password" }}' diff --git a/applications/gitlab/kots/kots-support-bundle.yaml b/applications/gitlab/kots/kots-support-bundle.yaml new file mode 100644 index 00000000..5825f533 --- /dev/null +++ b/applications/gitlab/kots/kots-support-bundle.yaml @@ -0,0 +1,48 @@ +apiVersion: troubleshoot.sh/v1beta2 +kind: SupportBundle +metadata: + name: gitlab +spec: + collectors: + - clusterInfo: {} + - clusterResources: {} + - logs: + selector: + - app=webservice + - release=gitlab + namespace: '{{repl Namespace }}' + limits: + maxAge: 720h + maxLines: 10000 + - logs: + selector: + - app=sidekiq + - release=gitlab + namespace: '{{repl Namespace }}' + limits: + maxAge: 720h + maxLines: 10000 + - logs: + selector: + - app=kas + - release=gitlab + namespace: '{{repl Namespace }}' + limits: + maxAge: 720h + maxLines: 10000 + - logs: + selector: + - app=redis-master + - release=gitlab + namespace: '{{repl Namespace }}' + limits: + maxAge: 720h + maxLines: 5000 + - logs: + selector: + - app=postgresql + - release=gitlab + namespace: '{{repl Namespace }}' + limits: + maxAge: 720h + maxLines: 5000 diff --git a/applications/gitlab/launch-gaps.md b/applications/gitlab/launch-gaps.md new file mode 100644 index 00000000..5f0ee8b5 --- /dev/null +++ b/applications/gitlab/launch-gaps.md @@ -0,0 +1,64 @@ +# GitLab Launch Gaps + +Gaps and friction discovered during the first end-to-end launch of this example. +Used to improve the agent instructions that built this application. + +--- + +## GAP-001: Quickstart missing cluster provisioning step + +**What happened:** Running `helm install` failed immediately with "cluster unreachable" because the quickstart assumed a cluster already existed. No step covered creating one. + +**Fix applied:** Added step 5 to the README quickstart with the full `replicated cluster create` command and `replicated cluster kubeconfig` to update kubeconfig. Added `make cluster-create` / `make cluster-delete` targets. + +**Agent instruction gap:** The agent should include a cluster provisioning step whenever a CMX-based install flow is documented. The quickstart must be runnable end-to-end from a clean state. + +--- + +## GAP-002: Quickstart hid CLI commands behind `make` targets + +**What happened:** Initial quickstart steps for install and cluster creation only showed `make install` and `make cluster-create`, giving users no visibility into the underlying `replicated` and `helm` commands. + +**Fix applied:** Rewrote steps to show the full CLI commands first, with `make` mentioned as a shortcut alongside them. + +**Agent instruction gap:** Quickstart steps should always show the underlying CLI commands explicitly. `make` targets are for convenience, not as the primary instruction. The README is documentation first. + +--- + +## GAP-003: External PostgreSQL and Redis not provisioned before GitLab install + +**What happened:** `helm install gitlab` failed with "Progress deadline exceeded" on every workload deployment. Root cause: `cmx-deploy-values.yaml` requires `external-postgresql` and `external-redis` Kubernetes services to exist before install, but no step in the quickstart covered deploying them. The prerequisites were documented only in a comment block inside `cmx-deploy-values.yaml`, not surfaced in the README. + +**Fix applied:** Added step 6 to the README with full `helm install bitnami/postgresql` and `helm install bitnami/redis` commands (using `fullnameOverride` to match the expected service names), plus `kubectl create secret` commands. Added `make setup-deps` / `make teardown-deps` targets. + +**Agent instruction gap:** When a values file has required prerequisites (external services, secrets), those must be explicit steps in the quickstart — not just comments in the values file. The agent should surface any `# Required:` / `# Prerequisites:` comments from values files as numbered steps in the README. + +--- + +## GAP-004: Bitnami PostgreSQL user lacks superuser — GitLab migrations fail + +**What happened:** `helm install gitlab` failed on the migrations job (`gitlab-migrations` Job, status: Failed). GitLab's migration runner executes `CREATE EXTENSION` for `pg_trgm`, `btree_gist`, and `amcheck`, which requires PostgreSQL superuser privileges. The Bitnami PostgreSQL chart creates the application user (`gitlab`) as a non-superuser by default, so migrations abort immediately. + +**Fix applied:** Added a `kubectl exec` step to `setup-deps` (and the README) that runs `ALTER USER gitlab SUPERUSER` against the postgres superuser after the chart deploys. The postgres superuser password is read from the chart-generated secret `external-postgresql`. + +**Agent instruction gap:** When deploying PostgreSQL via the Bitnami chart for GitLab specifically, the application DB user must be granted superuser. This is a non-obvious GitLab requirement (documented in GitLab's own installation guide but not surfaced in chart values or error messages). The agent should know to include this step whenever setting up GitLab with an external Bitnami PostgreSQL instance. + +--- + +## GAP-005: Bitnami Redis service name always includes `-master` suffix + +**What happened:** KAS (and likely sidekiq/webservice) crashed with `redis client: dial tcp: lookup external-redis on ...: no such host`. The `cmx-deploy-values.yaml` had `redis.host: external-redis`, but the Bitnami Redis chart always names its primary service `-master` (i.e., `external-redis-master`), even in standalone mode. + +**Fix applied:** Updated `cmx-deploy-values.yaml` `redis.host` from `external-redis` to `external-redis-master`. Added a comment explaining the naming behavior. + +**Agent instruction gap:** When using the Bitnami Redis chart, the service name for the master is always `-master` or `-master` — never just the base name. Any values file referencing a Bitnami Redis host must use the `-master` suffix. + +--- + +## GAP-006: Bitnami PostgreSQL OOMKilled during GitLab schema load + +**What happened:** The migrations job crashed PostgreSQL mid-schema-load with exit code 137 (OOMKilled). GitLab's `structure.sql` is ~32k lines and is loaded in a single transaction, which requires significant PostgreSQL working memory. The Bitnami chart's default `resourcesPreset` allocates too little memory for this workload. + +**Fix applied:** Added `--set primary.resourcesPreset=none --set primary.resources.requests.memory=1Gi --set primary.resources.limits.memory=2Gi` to the PostgreSQL install in both the Makefile and README. + +**Agent instruction gap:** The Bitnami PostgreSQL chart default resource preset is insufficient for GitLab. When documenting a GitLab + Bitnami PostgreSQL setup, always set explicit memory limits of at least 1Gi request / 2Gi limit on the primary. diff --git a/applications/gitlab/tests/helm/ci-values.yaml b/applications/gitlab/tests/helm/ci-values.yaml new file mode 100644 index 00000000..630a7d46 --- /dev/null +++ b/applications/gitlab/tests/helm/ci-values.yaml @@ -0,0 +1,74 @@ +# CI values for GitLab chart — lint/template validation ONLY (not for deployment). +# WARNING: This file references external PostgreSQL and Redis services that must +# exist before deployment. For actual cluster deployment, use cmx-deploy-values.yaml +# and provision external PostgreSQL 16+ and Redis 7+ first. +# The GitLab chart's bundled Bitnami images have been removed from Docker Hub. + +gitlab: + enabled: true + + global: + hosts: + domain: gitlab.example.com + externalIP: 10.0.0.1 + + edition: ce + + ingress: + configureCertmanager: false + class: nginx + tls: + enabled: false + + # External PostgreSQL and Redis (no bundled deps — bitnami images removed from Docker Hub) + psql: + host: external-postgresql + port: 5432 + database: gitlabhq_production + username: gitlab + password: + secret: gitlab-external-pg-password + key: password + redis: + host: external-redis + port: 6379 + auth: + enabled: true + secret: gitlab-external-redis-password + key: redis-password + + # Disable bundled PostgreSQL and Redis + postgresql: + install: false + redis: + install: false + nginx-ingress: + enabled: true + certmanager: + install: false + certmanager-issuer: + email: ci@example.com + prometheus: + install: false + registry: + enabled: true + gitlab-runner: + install: false + + # Reduce resource requirements for CI + gitlab: + webservice: + replicaCount: 1 + resources: + requests: + cpu: 100m + memory: 512Mi + sidekiq: + replicaCount: 1 + resources: + requests: + cpu: 50m + memory: 300Mi + +replicated: + enabled: true diff --git a/applications/gitlab/tests/helm/cmx-deploy-values.yaml b/applications/gitlab/tests/helm/cmx-deploy-values.yaml new file mode 100644 index 00000000..f4428be9 --- /dev/null +++ b/applications/gitlab/tests/helm/cmx-deploy-values.yaml @@ -0,0 +1,88 @@ +# CMX deployment values for GitLab chart — actual cluster deployment. +# +# The GitLab chart's bundled Bitnami PostgreSQL and Redis images have been +# removed from Docker Hub. This file configures external PostgreSQL and Redis +# services that you must provision separately before installing GitLab. +# +# Prerequisites: +# 1. PostgreSQL 16+ with extensions: pg_trgm, btree_gist +# 2. Redis 7+ +# 3. Kubernetes secrets for database credentials (see below) +# +# Required secrets (create before helm install): +# kubectl create secret generic gitlab-external-pg-password \ +# --from-literal=password= -n gitlab +# kubectl create secret generic gitlab-external-redis-password \ +# --from-literal=redis-password= -n gitlab +# +# Validated: 2026-03-30 on k3s 1.32, r1.xlarge, OCI registry install. + +gitlab: + enabled: true + + global: + hosts: + domain: gitlab.example.com + externalIP: 10.0.0.1 + + edition: ce + + ingress: + configureCertmanager: false + class: nginx + tls: + enabled: false + + # External PostgreSQL — replace host with your PostgreSQL service + psql: + host: external-postgresql + port: 5432 + database: gitlabhq_production + username: gitlab + password: + secret: gitlab-external-pg-password + key: password + + # External Redis — replace host with your Redis service + # Note: Bitnami Redis chart always names the master service -master + redis: + host: external-redis-master + port: 6379 + auth: + enabled: true + secret: gitlab-external-redis-password + key: redis-password + + # Disable bundled PostgreSQL and Redis (bitnami images removed from Docker Hub) + postgresql: + install: false + redis: + install: false + nginx-ingress: + enabled: true + certmanager: + install: false + prometheus: + install: false + registry: + enabled: true + gitlab-runner: + install: false + + # Reduce resource requirements for evaluation + gitlab: + webservice: + replicaCount: 1 + resources: + requests: + cpu: 100m + memory: 512Mi + sidekiq: + replicaCount: 1 + resources: + requests: + cpu: 50m + memory: 300Mi + +replicated: + enabled: true