initial commit
This commit is contained in:
@@ -0,0 +1,54 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Gitea Actions workflow (active for THIS repository).
|
||||||
|
# Builds examples/Dockerfile and pushes it to Harbor as a smoke test of the
|
||||||
|
# k3s runner + DinD + Harbor pipeline.
|
||||||
|
#
|
||||||
|
# Required repo/org Actions secrets:
|
||||||
|
# HARBOR_REGISTRY, HARBOR_USERNAME, HARBOR_PASSWORD
|
||||||
|
# Optional repo/org Actions variable:
|
||||||
|
# HARBOR_PROJECT (default: "library")
|
||||||
|
# =============================================================================
|
||||||
|
name: build-and-push
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
env:
|
||||||
|
HARBOR_PROJECT: ${{ vars.HARBOR_PROJECT || 'library' }}
|
||||||
|
IMAGE_NAME: build-on-k3s-sample
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Compute image tags
|
||||||
|
id: meta
|
||||||
|
run: |
|
||||||
|
IMAGE="${{ secrets.HARBOR_REGISTRY }}/${HARBOR_PROJECT}/${IMAGE_NAME}"
|
||||||
|
echo "image=${IMAGE}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "sha=${GITHUB_SHA::12}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Log in to Harbor
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ secrets.HARBOR_REGISTRY }}
|
||||||
|
username: ${{ secrets.HARBOR_USERNAME }}
|
||||||
|
password: ${{ secrets.HARBOR_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: ./examples
|
||||||
|
file: ./examples/Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ steps.meta.outputs.image }}:latest
|
||||||
|
${{ steps.meta.outputs.image }}:${{ steps.meta.outputs.sha }}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# Never commit filled-in secrets — only the *.example templates are tracked.
|
||||||
|
k3s/10-runner-secret.yaml
|
||||||
|
k3s/40-harbor-secret.yaml
|
||||||
|
*.secret.yaml
|
||||||
|
|
||||||
|
# Local kube configs
|
||||||
|
kubeconfig
|
||||||
|
*.kubeconfig
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
# Build Docker images on k3s with Gitea Actions → push to Harbor
|
||||||
|
|
||||||
|
This repository contains a complete, reproducible configuration that lets you:
|
||||||
|
|
||||||
|
1. Run a **Gitea Actions runner** (`act_runner`) **on a k3s node**.
|
||||||
|
2. Build **Docker/OCI container images** inside the CI pipeline using a
|
||||||
|
**Docker-in-Docker (DinD)** sidecar (so plain `docker build` / `docker push` work).
|
||||||
|
3. **Push the built images to a Harbor** registry.
|
||||||
|
|
||||||
|
The whole pipeline is driven by **Gitea Actions** (Gitea's built-in, GitHub-Actions-compatible
|
||||||
|
CI/CD), so no external CI system (Jenkins/Drone/etc.) is required.
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────┐ registers ┌─────────────────────────────────────┐
|
||||||
|
│ Gitea │◄────────────────│ act_runner (Deployment on k3s) │
|
||||||
|
│ (Actions) │ job dispatch │ ┌───────────────┐ ┌──────────────┐ │
|
||||||
|
│ │────────────────►│ │ act_runner │ │ dockerd │ │
|
||||||
|
└──────────────┘ │ │ container │─►│ (DinD side- │ │
|
||||||
|
▲ │ └───────────────┘ │ car, │ │
|
||||||
|
│ git push │ docker build │ privileged)│ │
|
||||||
|
┌────┴─────┐ │ docker push └──────────────┘ │
|
||||||
|
│ developer│ └───────────────────────────┬─────────┘
|
||||||
|
└──────────┘ │ push image
|
||||||
|
▼
|
||||||
|
┌──────────────────┐
|
||||||
|
│ Harbor registry │
|
||||||
|
└──────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Repository layout
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| [k3s/00-namespace.yaml](k3s/00-namespace.yaml) | Dedicated `gitea-runner` namespace. |
|
||||||
|
| [k3s/10-runner-secret.yaml.example](k3s/10-runner-secret.yaml.example) | Gitea registration token secret (copy & fill in). |
|
||||||
|
| [k3s/20-runner-config.yaml](k3s/20-runner-config.yaml) | `act_runner` config (`config.yaml`) as a ConfigMap. |
|
||||||
|
| [k3s/30-runner-deployment.yaml](k3s/30-runner-deployment.yaml) | The `act_runner` + DinD Deployment. |
|
||||||
|
| [k3s/40-harbor-secret.yaml.example](k3s/40-harbor-secret.yaml.example) | Optional cluster-side Harbor pull secret. |
|
||||||
|
| [workflows/build-and-push.yaml](workflows/build-and-push.yaml) | Example Gitea Actions workflow (put in your app repo). |
|
||||||
|
| [examples/Dockerfile](examples/Dockerfile) | Minimal sample image to build. |
|
||||||
|
| [scripts/deploy.sh](scripts/deploy.sh) | Helper to apply all manifests. |
|
||||||
|
| [.gitea/workflows/build-and-push.yaml](.gitea/workflows/build-and-push.yaml) | Same workflow, pre-placed so *this* repo self-builds. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
* A running **k3s** cluster and `kubectl` access to it (`~/.kube/config` or `/etc/rancher/k3s/k3s.yaml`).
|
||||||
|
* A reachable **Gitea** instance (>= 1.20) with **Actions enabled**
|
||||||
|
(`[actions] ENABLED = true` in Gitea's `app.ini`).
|
||||||
|
* A running **Harbor** registry and a **robot account** (recommended) with `push` permission
|
||||||
|
on the target project.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 1 — Enable Gitea Actions (on the Gitea server)
|
||||||
|
|
||||||
|
In Gitea's `app.ini`:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[actions]
|
||||||
|
ENABLED = true
|
||||||
|
```
|
||||||
|
|
||||||
|
Restart Gitea. Then get a **runner registration token**:
|
||||||
|
|
||||||
|
* **Instance level:** *Site Administration → Actions → Runners → Create new Runner* → copy the token.
|
||||||
|
* **Org/Repo level:** *Settings → Actions → Runners → Create new Runner*.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 2 — Create the runner registration secret
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp k3s/10-runner-secret.yaml.example k3s/10-runner-secret.yaml
|
||||||
|
# edit k3s/10-runner-secret.yaml and paste your GITEA_INSTANCE_URL + token
|
||||||
|
kubectl apply -f k3s/10-runner-secret.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 3 — Deploy the runner on k3s
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/deploy.sh
|
||||||
|
# or manually:
|
||||||
|
kubectl apply -f k3s/00-namespace.yaml
|
||||||
|
kubectl apply -f k3s/20-runner-config.yaml
|
||||||
|
kubectl apply -f k3s/30-runner-deployment.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify the runner appears **online** in Gitea (*Actions → Runners*) and that both containers are ready:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n gitea-runner rollout status deploy/act-runner
|
||||||
|
kubectl -n gitea-runner get pods
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 4 — Configure Harbor credentials for the pipeline
|
||||||
|
|
||||||
|
In your **Gitea repository** (or org) → *Settings → Actions → Secrets*, add:
|
||||||
|
|
||||||
|
| Secret name | Value |
|
||||||
|
|-------------|-------|
|
||||||
|
| `HARBOR_REGISTRY` | e.g. `harbor.example.com` |
|
||||||
|
| `HARBOR_USERNAME` | Harbor user / robot account, e.g. `robot$ci` |
|
||||||
|
| `HARBOR_PASSWORD` | the robot account token / password |
|
||||||
|
|
||||||
|
> Using a **Harbor robot account** (Project → Robot Accounts) instead of a personal
|
||||||
|
> login is strongly recommended.
|
||||||
|
|
||||||
|
## Step 5 — Add the workflow to your app repo
|
||||||
|
|
||||||
|
Copy [workflows/build-and-push.yaml](workflows/build-and-push.yaml) into your application repository at
|
||||||
|
`.gitea/workflows/build-and-push.yaml`, commit, and push. Gitea will dispatch the job to your
|
||||||
|
k3s runner, which builds the image via DinD and pushes it to Harbor.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How image building works (no Docker on k3s needed)
|
||||||
|
|
||||||
|
k3s uses **containerd**, not Docker, and has no image-build capability. This setup therefore runs a
|
||||||
|
**dockerd DinD sidecar** next to `act_runner`. The runner container talks to it over
|
||||||
|
`tcp://localhost:2376` (TLS), so inside jobs the standard `docker` CLI works transparently —
|
||||||
|
`docker build`, `docker login`, `docker push` all behave like on a normal Docker host.
|
||||||
|
|
||||||
|
If you prefer a **rootless / non-privileged** approach (Kaniko or Buildah), see the
|
||||||
|
"Alternative: rootless builds" section at the bottom of
|
||||||
|
[workflows/build-and-push.yaml](workflows/build-and-push.yaml).
|
||||||
|
|
||||||
|
## Security notes
|
||||||
|
|
||||||
|
* The DinD sidecar requires `privileged: true`. Keep this runner in its own namespace and,
|
||||||
|
ideally, on a dedicated node (see the `nodeSelector`/`tolerations` comments in the Deployment).
|
||||||
|
* Prefer Harbor **robot accounts** with the least privilege (push to one project only).
|
||||||
|
* Store all credentials as Kubernetes/Gitea secrets — never commit the filled-in
|
||||||
|
`*.yaml` (non-`.example`) files. See [.gitignore](.gitignore).
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Minimal sample image used to smoke-test the build-and-push pipeline.
|
||||||
|
FROM alpine:3.20
|
||||||
|
|
||||||
|
RUN apk add --no-cache ca-certificates
|
||||||
|
|
||||||
|
CMD ["sh", "-c", "echo 'Built on k3s via Gitea Actions and pushed to Harbor.'"]
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: gitea-runner
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: gitea-act-runner
|
||||||
|
app.kubernetes.io/part-of: ci-cd
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Gitea act_runner registration secret.
|
||||||
|
#
|
||||||
|
# 1. Copy this file: cp 10-runner-secret.yaml.example 10-runner-secret.yaml
|
||||||
|
# 2. Fill in the two stringData values below.
|
||||||
|
# 3. Apply: kubectl apply -f 10-runner-secret.yaml
|
||||||
|
#
|
||||||
|
# GITEA_INSTANCE_URL : Base URL of your Gitea server (no trailing /actions).
|
||||||
|
# GITEA_RUNNER_REGISTRATION_TOKEN :
|
||||||
|
# Token from Gitea -> (Site Admin | Org | Repo) -> Actions -> Runners
|
||||||
|
# -> "Create new Runner".
|
||||||
|
#
|
||||||
|
# The runner registers itself on first start using these values.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: act-runner-registration
|
||||||
|
namespace: gitea-runner
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
GITEA_INSTANCE_URL: "https://gitea.example.com"
|
||||||
|
GITEA_RUNNER_REGISTRATION_TOKEN: "REPLACE_WITH_REGISTRATION_TOKEN"
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# act_runner configuration, mounted into the runner container as config.yaml.
|
||||||
|
# Docs: https://docs.gitea.com/usage/actions/act-runner
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: act-runner-config
|
||||||
|
namespace: gitea-runner
|
||||||
|
data:
|
||||||
|
config.yaml: |
|
||||||
|
log:
|
||||||
|
level: info
|
||||||
|
|
||||||
|
runner:
|
||||||
|
# Max parallel jobs this runner will execute.
|
||||||
|
capacity: 2
|
||||||
|
timeout: 3h
|
||||||
|
# Labels advertise which job environments this runner provides.
|
||||||
|
# The workflow selects one with `runs-on:`.
|
||||||
|
labels:
|
||||||
|
- "ubuntu-latest:docker://catthehacker/ubuntu:act-22.04"
|
||||||
|
- "ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04"
|
||||||
|
- "dind:docker://catthehacker/ubuntu:act-22.04"
|
||||||
|
|
||||||
|
cache:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
container:
|
||||||
|
# Talk to the DinD sidecar over TCP (TLS) instead of a mounted socket.
|
||||||
|
docker_host: "tcp://localhost:2376"
|
||||||
|
# Job containers join the default docker network created by dockerd.
|
||||||
|
network: "host"
|
||||||
|
# Keep pulled images between jobs to speed builds up.
|
||||||
|
force_pull: false
|
||||||
|
# Give job containers access to the DinD TLS certs.
|
||||||
|
valid_volumes:
|
||||||
|
- "**"
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Gitea act_runner + Docker-in-Docker (DinD) sidecar, running on a k3s node.
|
||||||
|
#
|
||||||
|
# - The `dind` container runs a full dockerd (privileged) and exposes it over
|
||||||
|
# TLS on localhost:2376. Its TLS client certs are shared via an emptyDir.
|
||||||
|
# - The `runner` container registers with Gitea and dispatches each job to the
|
||||||
|
# dockerd inside the same pod, so `docker build` / `docker push` "just work".
|
||||||
|
#
|
||||||
|
# NOTE: DinD requires a privileged container. Keep this in its own namespace
|
||||||
|
# and consider pinning it to a dedicated build node (see nodeSelector).
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: act-runner
|
||||||
|
namespace: gitea-runner
|
||||||
|
labels:
|
||||||
|
app: act-runner
|
||||||
|
spec:
|
||||||
|
# Keep at 1: the registered runner state lives in the runner PVC.
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: act-runner
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: act-runner
|
||||||
|
spec:
|
||||||
|
# --- Optionally pin builds to a dedicated node -------------------------
|
||||||
|
# nodeSelector:
|
||||||
|
# ci-build: "true" # label a node: kubectl label node <node> ci-build=true
|
||||||
|
# tolerations:
|
||||||
|
# - key: "ci-build"
|
||||||
|
# operator: "Exists"
|
||||||
|
# effect: "NoSchedule"
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
containers:
|
||||||
|
# =====================================================================
|
||||||
|
# Docker-in-Docker daemon
|
||||||
|
# =====================================================================
|
||||||
|
- name: dind
|
||||||
|
image: docker:27-dind
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
env:
|
||||||
|
- name: DOCKER_TLS_CERTDIR
|
||||||
|
value: /certs
|
||||||
|
args:
|
||||||
|
- "--host=tcp://0.0.0.0:2376"
|
||||||
|
- "--tlsverify"
|
||||||
|
- "--tlscacert=/certs/ca/cert.pem"
|
||||||
|
- "--tlscert=/certs/server/cert.pem"
|
||||||
|
- "--tlskey=/certs/server/key.pem"
|
||||||
|
volumeMounts:
|
||||||
|
- name: docker-certs
|
||||||
|
mountPath: /certs
|
||||||
|
- name: docker-storage
|
||||||
|
mountPath: /var/lib/docker
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["docker", "-H", "tcp://localhost:2376", "--tlsverify",
|
||||||
|
"--tlscacert=/certs/ca/cert.pem",
|
||||||
|
"--tlscert=/certs/client/cert.pem",
|
||||||
|
"--tlskey=/certs/client/key.pem", "info"]
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
periodSeconds: 10
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: "250m"
|
||||||
|
memory: "512Mi"
|
||||||
|
limits:
|
||||||
|
cpu: "2"
|
||||||
|
memory: "4Gi"
|
||||||
|
|
||||||
|
# =====================================================================
|
||||||
|
# Gitea Actions runner
|
||||||
|
# =====================================================================
|
||||||
|
- name: runner
|
||||||
|
image: gitea/act_runner:0.2.11
|
||||||
|
env:
|
||||||
|
# Registration data (from the Secret).
|
||||||
|
- name: GITEA_INSTANCE_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: act-runner-registration
|
||||||
|
key: GITEA_INSTANCE_URL
|
||||||
|
- name: GITEA_RUNNER_REGISTRATION_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: act-runner-registration
|
||||||
|
key: GITEA_RUNNER_REGISTRATION_TOKEN
|
||||||
|
- name: GITEA_RUNNER_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.name
|
||||||
|
# Point the runner at the DinD daemon over TLS.
|
||||||
|
- name: DOCKER_HOST
|
||||||
|
value: "tcp://localhost:2376"
|
||||||
|
- name: DOCKER_CERT_PATH
|
||||||
|
value: "/certs/client"
|
||||||
|
- name: DOCKER_TLS_VERIFY
|
||||||
|
value: "1"
|
||||||
|
# Path to the mounted act_runner config.
|
||||||
|
- name: CONFIG_FILE
|
||||||
|
value: "/config/config.yaml"
|
||||||
|
volumeMounts:
|
||||||
|
- name: docker-certs
|
||||||
|
mountPath: /certs
|
||||||
|
readOnly: true
|
||||||
|
- name: runner-config
|
||||||
|
mountPath: /config
|
||||||
|
readOnly: true
|
||||||
|
- name: runner-data
|
||||||
|
mountPath: /data
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: "100m"
|
||||||
|
memory: "128Mi"
|
||||||
|
limits:
|
||||||
|
cpu: "1"
|
||||||
|
memory: "1Gi"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
# Shared TLS certs between dockerd and the runner/job containers.
|
||||||
|
- name: docker-certs
|
||||||
|
emptyDir: {}
|
||||||
|
# dockerd image/layer storage (ephemeral; use a PVC for a persistent cache).
|
||||||
|
- name: docker-storage
|
||||||
|
emptyDir: {}
|
||||||
|
- name: runner-config
|
||||||
|
configMap:
|
||||||
|
name: act-runner-config
|
||||||
|
# Persists the runner registration (.runner) across restarts.
|
||||||
|
- name: runner-data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: act-runner-data
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: act-runner-data
|
||||||
|
namespace: gitea-runner
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 2Gi
|
||||||
|
# k3s default storage class (local-path). Change if you use another provisioner.
|
||||||
|
# storageClassName: local-path
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# OPTIONAL: cluster-side Harbor pull secret.
|
||||||
|
#
|
||||||
|
# This is NOT needed for the CI build/push (that uses Gitea Actions secrets).
|
||||||
|
# Create it only if the same k3s cluster must *pull* the private images that the
|
||||||
|
# pipeline pushes to Harbor (e.g. when you later deploy those images here).
|
||||||
|
#
|
||||||
|
# Easiest way to create it (recommended over editing this file by hand):
|
||||||
|
#
|
||||||
|
# kubectl create secret docker-registry harbor-pull \
|
||||||
|
# --namespace <your-app-namespace> \
|
||||||
|
# --docker-server=harbor.example.com \
|
||||||
|
# --docker-username='robot$ci' \
|
||||||
|
# --docker-password='REPLACE_WITH_ROBOT_TOKEN'
|
||||||
|
#
|
||||||
|
# Then reference it from your workloads:
|
||||||
|
# spec.imagePullSecrets: [{ name: harbor-pull }]
|
||||||
|
#
|
||||||
|
# The manifest below is the equivalent declarative form (base64 dockerconfigjson).
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: harbor-pull
|
||||||
|
namespace: default
|
||||||
|
type: kubernetes.io/dockerconfigjson
|
||||||
|
data:
|
||||||
|
# echo -n '{"auths":{"harbor.example.com":{"username":"robot$ci","password":"TOKEN","auth":"<base64 user:pass>"}}}' | base64 -w0
|
||||||
|
.dockerconfigjson: REPLACE_WITH_BASE64_DOCKERCONFIGJSON
|
||||||
Executable
+39
@@ -0,0 +1,39 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Deploy the Gitea act_runner (with DinD) onto k3s.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./scripts/deploy.sh
|
||||||
|
#
|
||||||
|
# Prerequisites:
|
||||||
|
# - kubectl configured against your k3s cluster
|
||||||
|
# (e.g. export KUBECONFIG=/etc/rancher/k3s/k3s.yaml)
|
||||||
|
# - k3s/10-runner-secret.yaml created from the .example and filled in.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
K3S_DIR="${ROOT_DIR}/k3s"
|
||||||
|
|
||||||
|
if [[ ! -f "${K3S_DIR}/10-runner-secret.yaml" ]]; then
|
||||||
|
echo "ERROR: ${K3S_DIR}/10-runner-secret.yaml not found." >&2
|
||||||
|
echo " cp ${K3S_DIR}/10-runner-secret.yaml.example ${K3S_DIR}/10-runner-secret.yaml" >&2
|
||||||
|
echo " then fill in GITEA_INSTANCE_URL and the registration token." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ">> Applying namespace"
|
||||||
|
kubectl apply -f "${K3S_DIR}/00-namespace.yaml"
|
||||||
|
|
||||||
|
echo ">> Applying runner registration secret"
|
||||||
|
kubectl apply -f "${K3S_DIR}/10-runner-secret.yaml"
|
||||||
|
|
||||||
|
echo ">> Applying runner config"
|
||||||
|
kubectl apply -f "${K3S_DIR}/20-runner-config.yaml"
|
||||||
|
|
||||||
|
echo ">> Applying runner deployment"
|
||||||
|
kubectl apply -f "${K3S_DIR}/30-runner-deployment.yaml"
|
||||||
|
|
||||||
|
echo ">> Waiting for rollout"
|
||||||
|
kubectl -n gitea-runner rollout status deploy/act-runner --timeout=180s
|
||||||
|
|
||||||
|
echo ">> Done. Runner pods:"
|
||||||
|
kubectl -n gitea-runner get pods -o wide
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Gitea Actions workflow: build a Docker image and push it to Harbor.
|
||||||
|
#
|
||||||
|
# Place this file in your application repository at:
|
||||||
|
# .gitea/workflows/build-and-push.yaml
|
||||||
|
#
|
||||||
|
# Required repo/org Actions secrets (Settings -> Actions -> Secrets):
|
||||||
|
# HARBOR_REGISTRY e.g. harbor.example.com
|
||||||
|
# HARBOR_USERNAME e.g. robot$ci
|
||||||
|
# HARBOR_PASSWORD the robot account token
|
||||||
|
#
|
||||||
|
# Optional repo/org Actions variables (Settings -> Actions -> Variables):
|
||||||
|
# HARBOR_PROJECT Harbor project name (default: "library")
|
||||||
|
# IMAGE_NAME image name (default: repository name)
|
||||||
|
# =============================================================================
|
||||||
|
name: build-and-push
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
# Uses the label advertised by the act_runner on k3s.
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
env:
|
||||||
|
HARBOR_PROJECT: ${{ vars.HARBOR_PROJECT || 'library' }}
|
||||||
|
IMAGE_NAME: ${{ vars.IMAGE_NAME || gitea.event.repository.name }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Compute image tags
|
||||||
|
id: meta
|
||||||
|
run: |
|
||||||
|
REGISTRY="${{ secrets.HARBOR_REGISTRY }}"
|
||||||
|
IMAGE="${REGISTRY}/${HARBOR_PROJECT}/${IMAGE_NAME}"
|
||||||
|
SHA_TAG="${GITHUB_SHA::12}"
|
||||||
|
echo "image=${IMAGE}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "sha_tag=${SHA_TAG}" >> "$GITHUB_OUTPUT"
|
||||||
|
# Use the git tag as the version when the ref is a tag, else 'latest'.
|
||||||
|
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
|
||||||
|
echo "version=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "version=latest" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Log in to Harbor
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ secrets.HARBOR_REGISTRY }}
|
||||||
|
username: ${{ secrets.HARBOR_USERNAME }}
|
||||||
|
password: ${{ secrets.HARBOR_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ steps.meta.outputs.image }}:${{ steps.meta.outputs.version }}
|
||||||
|
${{ steps.meta.outputs.image }}:${{ steps.meta.outputs.sha_tag }}
|
||||||
|
|
||||||
|
- name: Summary
|
||||||
|
run: |
|
||||||
|
echo "Pushed:"
|
||||||
|
echo " ${{ steps.meta.outputs.image }}:${{ steps.meta.outputs.version }}"
|
||||||
|
echo " ${{ steps.meta.outputs.image }}:${{ steps.meta.outputs.sha_tag }}"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Alternative: rootless builds (no privileged DinD sidecar)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# If you cannot run a privileged DinD sidecar, build with Kaniko instead.
|
||||||
|
# Replace the "Build and push" step (and drop the Buildx/login steps) with a
|
||||||
|
# container step running the Kaniko executor. Kaniko logs in to Harbor via a
|
||||||
|
# generated docker config:
|
||||||
|
#
|
||||||
|
# - name: Build and push with Kaniko
|
||||||
|
# uses: https://github.com/int128/kaniko-action@v1
|
||||||
|
# with:
|
||||||
|
# push: true
|
||||||
|
# tags: ${{ steps.meta.outputs.image }}:${{ steps.meta.outputs.version }}
|
||||||
|
# registry: ${{ secrets.HARBOR_REGISTRY }}
|
||||||
|
# username: ${{ secrets.HARBOR_USERNAME }}
|
||||||
|
# password: ${{ secrets.HARBOR_PASSWORD }}
|
||||||
|
#
|
||||||
|
# In that case the act_runner does not need the DinD sidecar; the Kaniko
|
||||||
|
# executor image performs the build inside the job container.
|
||||||
|
# =============================================================================
|
||||||
Reference in New Issue
Block a user