Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Build and Push CI Deployment Cleanup Docker Image

on:
push:
tags: [ 'ci-deployment-cleanup-v*' ]
workflow_dispatch:

env:
REGISTRY: ghcr.io
IMAGE_NAME: swissdatasciencecenter/renku-ci-cleanup

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract version from tag
id: version
run: |
VERSION=$(echo "${{ github.ref_name }}" | sed 's/ci-deployment-cleanup-v//')
echo "version=$VERSION" >> $GITHUB_OUTPUT

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{version}},value=${{ steps.version.outputs.version }}
type=sha

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ci-deployment-cleanup/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
56 changes: 56 additions & 0 deletions .github/workflows/helm-chart.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Package and Push Helm Chart

on:
push:
tags: [ 'ci-deployment-cleanup-v*' ]
workflow_dispatch:

env:
REGISTRY: ghcr.io

jobs:
helm-chart:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install Helm
uses: azure/setup-helm@v4
with:
version: '3.14.0'

- name: Log in to Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Determine app version
id: version
run: |
VERSION=$(echo "${{ github.ref_name }}" | sed 's/ci-deployment-cleanup-v//')
echo "appVersion=$VERSION" >> $GITHUB_OUTPUT

- name: Update Chart.yaml with app version
run: |
cd ci-deployment-cleanup/helm-chart
sed -i "s/appVersion: .*/appVersion: \"${{ steps.version.outputs.appVersion }}\"/" Chart.yaml

- name: Lint Helm chart
run: |
cd ci-deployment-cleanup
helm lint helm-chart/

- name: Package and push Helm chart
run: |
cd ci-deployment-cleanup
helm package helm-chart/
helm push *.tgz oci://${{ env.REGISTRY }}/swissdatasciencecenter/helm-charts
26 changes: 26 additions & 0 deletions .github/workflows/lint-cleanup-script.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Lint cleanup.sh script

on:
push:
paths:
- 'ci-deployment-cleanup/helm-chart/cleanup.sh'
pull_request:
paths:
- 'ci-deployment-cleanup/helm-chart/cleanup.sh'

permissions:
contents: read

jobs:
shellcheck:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Run ShellCheck
uses: ludeeus/action-shellcheck@master
with:
scandir: './ci-deployment-cleanup/helm-chart'
format: gcc
severity: error
52 changes: 52 additions & 0 deletions ci-deployment-cleanup/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
FROM golang:1.24-alpine AS builder

RUN apk add --no-cache make bash

WORKDIR /app

# Copy renku-dev-utils files
COPY . .

# Build the rdu binary
RUN make rdu

FROM alpine:3.18

RUN apk add --no-cache \
bash \
curl \
ca-certificates \
jq \
openssl \
&& ARCH=$(case $(uname -m) in x86_64) echo amd64;; aarch64) echo arm64;; *) echo amd64;; esac) \
&& curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${ARCH}/kubectl" \
&& chmod +x kubectl \
&& mv kubectl /usr/local/bin/

RUN curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 \
&& chmod 700 get_helm.sh \
&& ./get_helm.sh \
&& rm get_helm.sh

# Copy the rdu binary from builder stage
COPY --from=builder /app/build/renku-dev-utils /usr/local/bin/rdu

# Make rdu executable
RUN chmod +x /usr/local/bin/rdu

# Create a non-root user
RUN addgroup -g 1000 appuser && \
adduser -u 1000 -G appuser -s /bin/bash -D appuser

# Switch to non-root user
USER appuser

# Set working directory
WORKDIR /home/appuser

# Verify installations
RUN rdu version || echo "rdu installed" && \
kubectl version --client && \
helm version

CMD ["/bin/bash"]
51 changes: 51 additions & 0 deletions ci-deployment-cleanup/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Renku CI Deployment Cleanup

A Kubernetes-based CI deployment cleanup system that uses a Helm chart to deploy automated cleanup of old Renku CI deployments. This system runs as a CronJob that leverages the `rdu` tool for comprehensive cleanup.

## Installation

Install the Helm chart:
```bash
helm install renku-ci-cleanup ./helm-chart
```

## Exemption

Namespaces can be exempted from cleanup by adding the label `renku.io/cleanup-exempt: "true"` to the namespace.

## How It Works

1. The CronJob runs on the specified schedule (default: every 6 hours)
2. It queries Kubernetes for ALL namespaces in the cluster
3. For each namespace found:
- Checks if the namespace has the exemption label (if so, skips it)
- Checks if the namespace name matches any of the configured patterns (if enforcement is enabled)
- Calculates the age based on the namespace creation timestamp
- Checks GitHub PR status for PR-based cleanup (if enabled)
- If the namespace is older than the configured threshold AND matches the naming patterns AND is not exempt, it uses `rdu cleanup-deployment` to:
- Delete all sessions
- Uninstall all Helm releases
- Delete all jobs and PVCs
- Delete the entire namespace
4. Logging shows what actions were taken, including exemption and pattern matching results

## Key Configuration

The main configuration options in `values.yaml`:

- `cleanup.maxAge`: Maximum age in hours before cleanup (default: 720 hours / 30 days)
- `cleanup.dryRun`: Enable dry-run mode (default: false)
- `cleanup.namespacePatterns`: List of regex patterns for namespace names
- `cleanup.enforceNamePatterns`: Enable strict pattern matching (default: true)
- `cleanup.prCleanup.enabled`: Enable GitHub PR-based cleanup (default: false)
- `cronJob.schedule`: Cron schedule (default: "0 */6 * * *" - every 6 hours)

## PR-Based Cleanup

The system supports GitHub PR-based cleanup that can automatically clean up namespaces when their associated pull requests are closed or merged. This feature requires:

- `cleanup.prCleanup.enabled: true`
- GitHub API token configured
- Repository mappings in `cleanup.prCleanup.repositories`

Example configuration maps namespace patterns to GitHub repositories and PR numbers.
18 changes: 18 additions & 0 deletions ci-deployment-cleanup/helm-chart/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: v2
name: renku-ci-cleanup
description: A Helm chart for cleaning up old Renku CI deployments
type: application
version: 1.0.0
appVersion: "1.0.0"
keywords:
- renku
- ci
- cleanup
- deployment
home: https://github.com/SwissDataScienceCenter/renku-dev-utils
sources:
- https://github.com/SwissDataScienceCenter/renku-dev-utils
maintainers:
- name: Renku Team
email: hello@renku.io
url: https://renkulab.io
Loading