init
This commit is contained in:
148
.gitea/workflows/build.yaml
Normal file
148
.gitea/workflows/build.yaml
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
name: 🏗️ Build Container Image
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
# --- Required ---
|
||||||
|
image_name:
|
||||||
|
description: 'Image name without registry/org (e.g. ansible-act-runner)'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
dockerfile_path:
|
||||||
|
description: 'Path to Dockerfile relative to repo root (e.g. docker/Dockerfile)'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
context_path:
|
||||||
|
description: 'Build context directory relative to repo root (e.g. docker/)'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
# --- Optional overrides ---
|
||||||
|
registry:
|
||||||
|
description: 'Registry to push to (default: gitea.mod.home)'
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: 'gitea.mod.home'
|
||||||
|
image_org:
|
||||||
|
description: 'Registry org/namespace (default: calling repo owner)'
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
extra_tag:
|
||||||
|
description: 'Additional tag besides latest and SHA (e.g. stable)'
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
no_cache:
|
||||||
|
description: 'Disable build cache'
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
|
secrets:
|
||||||
|
TOKEN:
|
||||||
|
required: true
|
||||||
|
# Optional — override default REGISTRY_USER/REGISTRY_PASSWORD
|
||||||
|
REGISTRY_USER_OVERRIDE:
|
||||||
|
required: false
|
||||||
|
REGISTRY_PASSWORD_OVERRIDE:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
# Runs directly on runner host (docker:host)
|
||||||
|
# Kaniko executor available via tools volume (initContainer in deployment)
|
||||||
|
runs-on: docker
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: 🔎 Checkout
|
||||||
|
run: |
|
||||||
|
git clone \
|
||||||
|
--depth 1 \
|
||||||
|
--branch "${{ gitea.ref_name }}" \
|
||||||
|
"http://${{ secrets.TOKEN }}@gitea.mod.home/${{ gitea.repository_owner }}/${{ gitea.event.repository.name }}.git" \
|
||||||
|
/workspace
|
||||||
|
|
||||||
|
- name: 🏷️ Resolve Image Destination
|
||||||
|
id: meta
|
||||||
|
run: |
|
||||||
|
# Registry
|
||||||
|
REGISTRY="${{ inputs.registry }}"
|
||||||
|
|
||||||
|
# Org: use override if provided, otherwise calling repo owner
|
||||||
|
ORG="${{ inputs.image_org }}"
|
||||||
|
if [ -z "${ORG}" ]; then
|
||||||
|
ORG="${{ gitea.repository_owner }}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Credentials: use override if provided, otherwise defaults
|
||||||
|
USER="${{ secrets.REGISTRY_USER_OVERRIDE }}"
|
||||||
|
if [ -z "${USER}" ]; then
|
||||||
|
USER="${{ secrets.REGISTRY_USER }}"
|
||||||
|
fi
|
||||||
|
PASS="${{ secrets.REGISTRY_PASSWORD_OVERRIDE }}"
|
||||||
|
if [ -z "${PASS}" ]; then
|
||||||
|
PASS="${{ secrets.REGISTRY_PASSWORD }}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
IMAGE="${REGISTRY}/${ORG}/${{ inputs.image_name }}"
|
||||||
|
SHORT_SHA="${{ gitea.sha }}"
|
||||||
|
SHORT_SHA="${SHORT_SHA:0:8}"
|
||||||
|
|
||||||
|
echo "image=${IMAGE}" >> $GITHUB_OUTPUT
|
||||||
|
echo "tag_latest=${IMAGE}:latest" >> $GITHUB_OUTPUT
|
||||||
|
echo "tag_sha=${IMAGE}:${SHORT_SHA}" >> $GITHUB_OUTPUT
|
||||||
|
echo "short_sha=${SHORT_SHA}" >> $GITHUB_OUTPUT
|
||||||
|
echo "registry=${REGISTRY}" >> $GITHUB_OUTPUT
|
||||||
|
echo "user=${USER}" >> $GITHUB_OUTPUT
|
||||||
|
echo "pass=${PASS}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: 🔑 Create Kaniko Registry Config
|
||||||
|
run: |
|
||||||
|
mkdir -p /kaniko/.docker
|
||||||
|
AUTH=$(echo -n "${{ steps.meta.outputs.user }}:${{ steps.meta.outputs.pass }}" | base64)
|
||||||
|
cat > /kaniko/.docker/config.json << EOF
|
||||||
|
{
|
||||||
|
"auths": {
|
||||||
|
"${{ steps.meta.outputs.registry }}": {
|
||||||
|
"auth": "${AUTH}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: 🔨 Build + Push Image
|
||||||
|
run: |
|
||||||
|
# Build extra destinations
|
||||||
|
DESTINATIONS="--destination ${{ steps.meta.outputs.tag_latest }} \
|
||||||
|
--destination ${{ steps.meta.outputs.tag_sha }}"
|
||||||
|
|
||||||
|
if [ -n "${{ inputs.extra_tag }}" ]; then
|
||||||
|
DESTINATIONS="${DESTINATIONS} --destination ${{ steps.meta.outputs.image }}:${{ inputs.extra_tag }}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
NO_CACHE=""
|
||||||
|
if [ "${{ inputs.no_cache }}" = "true" ]; then
|
||||||
|
NO_CACHE="--no-push-cache --cache=false"
|
||||||
|
fi
|
||||||
|
|
||||||
|
/kaniko/executor \
|
||||||
|
--context=dir:///workspace/${{ inputs.context_path }} \
|
||||||
|
--dockerfile=/workspace/${{ inputs.dockerfile_path }} \
|
||||||
|
${DESTINATIONS} \
|
||||||
|
${NO_CACHE} \
|
||||||
|
--insecure \
|
||||||
|
--skip-tls-verify \
|
||||||
|
--compressed-caching=false
|
||||||
|
|
||||||
|
- name: 📨 Telegram Notification
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
STATUS="${{ job.status }}"
|
||||||
|
IMAGE="${{ steps.meta.outputs.tag_latest }}"
|
||||||
|
SHA="${{ steps.meta.outputs.short_sha }}"
|
||||||
|
TEXT="🏗️ Image Build: ${IMAGE}%0ASHA: ${SHA}%0AStatus: ${STATUS}"
|
||||||
|
curl -s -X POST \
|
||||||
|
"https://api.telegram.org/bot${{ secrets.TELEGRAM_BOT_TOKEN }}/sendMessage" \
|
||||||
|
-d "chat_id=${{ secrets.TELEGRAM_CHAT_ID }}" \
|
||||||
|
-d "text=${TEXT}"
|
||||||
173
README.md
173
README.md
@@ -1,2 +1,175 @@
|
|||||||
# image-builder
|
# image-builder
|
||||||
|
|
||||||
|
Reusable Gitea Actions workflow for building and pushing container images using
|
||||||
|
[Kaniko](https://github.com/GoogleContainerTools/kaniko). No Docker daemon
|
||||||
|
required — Kaniko runs directly on the runner host and handles both build and
|
||||||
|
push in a single step.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
```
|
||||||
|
Calling repo (e.g. ansible/ansible-runner)
|
||||||
|
→ workflow_call → docker/image-builder
|
||||||
|
→ Kaniko builds Dockerfile
|
||||||
|
→ Pushes to gitea.mod.home/<calling_org>/<image_name>:latest
|
||||||
|
→ Pushes to gitea.mod.home/<calling_org>/<image_name>:<sha>
|
||||||
|
```
|
||||||
|
|
||||||
|
Kaniko is available on the runner host via the `tools` EmptyDir volume,
|
||||||
|
populated by the `install-build-tools` initContainer in the act runner
|
||||||
|
deployment.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Minimal — push to Gitea Registry
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# .gitea/workflows/build-myimage.yaml in your repo
|
||||||
|
name: 🏗️ Build My Image
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- 'docker/Dockerfile'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
uses: docker/image-builder/.gitea/workflows/build.yaml@main
|
||||||
|
with:
|
||||||
|
image_name: my-image # → gitea.mod.home/<your_org>/my-image
|
||||||
|
dockerfile_path: docker/Dockerfile
|
||||||
|
context_path: docker/
|
||||||
|
secrets:
|
||||||
|
TOKEN: ${{ secrets.TOKEN }}
|
||||||
|
```
|
||||||
|
|
||||||
|
### With extra tag
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
uses: docker/image-builder/.gitea/workflows/build.yaml@main
|
||||||
|
with:
|
||||||
|
image_name: my-image
|
||||||
|
dockerfile_path: docker/Dockerfile
|
||||||
|
context_path: docker/
|
||||||
|
extra_tag: stable
|
||||||
|
secrets:
|
||||||
|
TOKEN: ${{ secrets.TOKEN }}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Push to Docker Hub
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
uses: docker/image-builder/.gitea/workflows/build.yaml@main
|
||||||
|
with:
|
||||||
|
image_name: myuser/my-image
|
||||||
|
registry: registry-1.docker.io
|
||||||
|
dockerfile_path: docker/Dockerfile
|
||||||
|
context_path: docker/
|
||||||
|
secrets:
|
||||||
|
TOKEN: ${{ secrets.TOKEN }}
|
||||||
|
REGISTRY_USER_OVERRIDE: ${{ secrets.DOCKERHUB_USER }}
|
||||||
|
REGISTRY_PASSWORD_OVERRIDE: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Force rebuild without cache
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
with:
|
||||||
|
image_name: my-image
|
||||||
|
dockerfile_path: docker/Dockerfile
|
||||||
|
context_path: docker/
|
||||||
|
no_cache: true
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
| Input | Required | Default | Description |
|
||||||
|
|-------|----------|---------|-------------|
|
||||||
|
| `image_name` | ✅ | — | Image name without registry/org |
|
||||||
|
| `dockerfile_path` | ✅ | — | Path to Dockerfile relative to repo root |
|
||||||
|
| `context_path` | ✅ | — | Build context directory relative to repo root |
|
||||||
|
| `registry` | ❌ | `gitea.mod.home` | Target registry |
|
||||||
|
| `image_org` | ❌ | calling repo owner | Registry org/namespace |
|
||||||
|
| `extra_tag` | ❌ | `''` | Additional tag besides `latest` and SHA |
|
||||||
|
| `no_cache` | ❌ | `false` | Disable Kaniko build cache |
|
||||||
|
|
||||||
|
## Secrets
|
||||||
|
|
||||||
|
| Secret | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `TOKEN` | ✅ | Gitea access token for checkout |
|
||||||
|
| `REGISTRY_USER_OVERRIDE` | ❌ | Override registry username |
|
||||||
|
| `REGISTRY_PASSWORD_OVERRIDE` | ❌ | Override registry password |
|
||||||
|
|
||||||
|
Secrets `REGISTRY_USER` and `REGISTRY_PASSWORD` must be set at the
|
||||||
|
**`docker` org level** in Gitea. All other repos inherit them automatically.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Required Secrets (docker Org)
|
||||||
|
|
||||||
|
Set these in Gitea → `docker` org → Settings → Secrets:
|
||||||
|
|
||||||
|
| Secret | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `REGISTRY_USER` | Gitea username for container registry login |
|
||||||
|
| `REGISTRY_PASSWORD` | Gitea access token with `package:write` scope |
|
||||||
|
| `TELEGRAM_BOT_TOKEN` | Telegram bot token for build notifications |
|
||||||
|
| `TELEGRAM_CHAT_ID` | Telegram chat ID for build notifications |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Runner Requirements
|
||||||
|
|
||||||
|
The act runner deployment must have the `install-build-tools` initContainer
|
||||||
|
which copies the Kaniko executor binary into the `tools` EmptyDir volume:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
initContainers:
|
||||||
|
- name: install-build-tools
|
||||||
|
image: gcr.io/kaniko-project/executor:latest
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -c
|
||||||
|
- cp /kaniko/executor /tools/executor && chmod +x /tools/executor
|
||||||
|
volumeMounts:
|
||||||
|
- name: tools
|
||||||
|
mountPath: /tools
|
||||||
|
```
|
||||||
|
|
||||||
|
The runner must have the `docker` label registered:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# configmap.yaml
|
||||||
|
labels:
|
||||||
|
- "docker:host"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Image Naming Convention
|
||||||
|
|
||||||
|
| Calling repo | image_name | Result |
|
||||||
|
|-------------|------------|--------|
|
||||||
|
| `ansible/ansible-runner` | `ansible-act-runner` | `gitea.mod.home/ansible/ansible-act-runner:latest` |
|
||||||
|
| `ansible/ansible-runner` | `ubuntu-act-runner` | `gitea.mod.home/ansible/ubuntu-act-runner:latest` |
|
||||||
|
| any repo | `myimage` with `image_org: shared` | `gitea.mod.home/shared/myimage:latest` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
|
||||||
|
- [ ] TLS for Gitea registry — remove `--insecure` flag once cert-manager CA is in place
|
||||||
|
- [ ] Multi-arch builds via Kaniko cross-compilation
|
||||||
|
|||||||
Reference in New Issue
Block a user