Publish runner image to Gitea Container Registry
This commit is contained in:
73
.gitea/workflows/build-runner-image.yml
Normal file
73
.gitea/workflows/build-runner-image.yml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
name: Build runner image
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- runner-image/**
|
||||||
|
- .gitea/workflows/build-runner-image.yml
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: node:20-bookworm
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
steps:
|
||||||
|
- name: Check out repository
|
||||||
|
uses: https://gitea.com/actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Docker client
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
for attempt in 1 2 3; do
|
||||||
|
if apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
||||||
|
--no-install-recommends docker.io; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$attempt" -eq 3 ]; then
|
||||||
|
echo "Unable to install the Docker client after 3 attempts"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep "$((attempt * 5))"
|
||||||
|
done
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
docker version --format 'Docker client {{.Client.Version}}, server {{.Server.Version}}'
|
||||||
|
|
||||||
|
- name: Build, verify, and publish image
|
||||||
|
env:
|
||||||
|
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
||||||
|
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
registry="mahgit.ir"
|
||||||
|
image="$registry/meghdadfadaee/daily-blackout-check-runner"
|
||||||
|
revision="$(git rev-parse --short=12 HEAD)"
|
||||||
|
candidate="$image:$revision"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
docker logout "$registry" >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
printf '%s' "$REGISTRY_TOKEN" | docker login "$registry" \
|
||||||
|
--username "$REGISTRY_USERNAME" \
|
||||||
|
--password-stdin
|
||||||
|
|
||||||
|
docker build \
|
||||||
|
--pull \
|
||||||
|
--label "org.opencontainers.image.revision=$revision" \
|
||||||
|
--label "org.opencontainers.image.source=https://mahgit.ir/MeghdadFadaee/daily-blackout-check" \
|
||||||
|
--tag "$candidate" \
|
||||||
|
runner-image
|
||||||
|
|
||||||
|
docker run --rm "$candidate" python -c "import dotenv, jdatetime, requests"
|
||||||
|
docker run --rm "$candidate" pytest --version
|
||||||
|
docker run --rm "$candidate" ruff --version
|
||||||
|
|
||||||
|
docker push "$candidate"
|
||||||
|
docker tag "$candidate" "$image:latest"
|
||||||
|
docker push "$image:latest"
|
||||||
@@ -9,7 +9,10 @@ jobs:
|
|||||||
check:
|
check:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: daily-blackout-check-runner:latest
|
image: mahgit.ir/meghdadfadaee/daily-blackout-check-runner:latest
|
||||||
|
credentials:
|
||||||
|
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||||
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
env:
|
env:
|
||||||
PYTHONPATH: src
|
PYTHONPATH: src
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -11,7 +11,10 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: daily-blackout-check-runner:latest
|
image: mahgit.ir/meghdadfadaee/daily-blackout-check-runner:latest
|
||||||
|
credentials:
|
||||||
|
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||||
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
env:
|
env:
|
||||||
PYTHONPATH: src
|
PYTHONPATH: src
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
95
README.md
95
README.md
@@ -62,37 +62,77 @@ Shell and Gitea-provided variables take precedence over `.env`.
|
|||||||
## Gitea deployment
|
## Gitea deployment
|
||||||
|
|
||||||
This repository targets Gitea 1.25.x and a Docker-based runner advertising the
|
This repository targets Gitea 1.25.x and a Docker-based runner advertising the
|
||||||
`ubuntu-latest` label. Both workflows run inside the locally built
|
`ubuntu-latest` label. The test and hourly workflows pull this private image from
|
||||||
`daily-blackout-check-runner:latest` image. It contains Node for the checkout
|
the Gitea Container Registry:
|
||||||
action plus Python, Git, timezone data, application dependencies, pytest, and
|
|
||||||
Ruff. Scheduled jobs therefore do not install Python or download Python packages.
|
|
||||||
|
|
||||||
Build the image on the Docker host used by `act_runner`:
|
```text
|
||||||
|
mahgit.ir/meghdadfadaee/daily-blackout-check-runner:latest
|
||||||
```sh
|
|
||||||
cd /path/to/daily-blackout-check
|
|
||||||
docker build \
|
|
||||||
--tag daily-blackout-check-runner:latest \
|
|
||||||
runner-image
|
|
||||||
docker image inspect daily-blackout-check-runner:latest >/dev/null
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Only `runner-image/` is sent as the Docker build context, so local secrets and
|
It contains Node for the checkout action plus Python, Git, timezone data,
|
||||||
outage state never enter the build context or image.
|
application dependencies, pytest, and Ruff. Scheduled jobs therefore do not
|
||||||
|
install Python or download Python packages.
|
||||||
|
|
||||||
The image is local rather than registry-hosted, matching the deployment pattern
|
### Registry credentials
|
||||||
used by `mahak-api-docs`. Build it on every runner host that can claim this job.
|
|
||||||
Rebuild it whenever `runner-image/Dockerfile`, `runner-image/requirements.lock`,
|
Create a Gitea personal access token for `MeghdadFadaee` with package permission
|
||||||
or dependency declarations in `pyproject.toml` change. The image build requires
|
set to **Read and Write**. Add these repository Actions secrets:
|
||||||
Docker Hub and PyPI access; normal workflow runs only need the Gitea instance,
|
|
||||||
|
| Secret | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| `REGISTRY_USERNAME` | Gitea username that owns the package |
|
||||||
|
| `REGISTRY_TOKEN` | Personal access token with package Read and Write permission |
|
||||||
|
| `BARGHEMAN_TOKEN` | SAAPA bearer token |
|
||||||
|
| `EITAAYAR_TOKEN` | EitaaYar bot token |
|
||||||
|
| `CHAT_ID` | Destination chat ID |
|
||||||
|
| `BILL_IDS` | Comma-separated bill IDs |
|
||||||
|
|
||||||
|
The registry token is used to publish the image and as `container.credentials`
|
||||||
|
when Gitea Runner pulls the private image before starting a job.
|
||||||
|
|
||||||
|
### Runner configuration
|
||||||
|
|
||||||
|
The image-build workflow needs access to the Docker daemon used by `act_runner`.
|
||||||
|
In the runner's generated `config.yaml`, update the existing `container` section:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
container:
|
||||||
|
force_pull: true
|
||||||
|
valid_volumes:
|
||||||
|
- /var/run/docker.sock
|
||||||
|
```
|
||||||
|
|
||||||
|
The runner container itself must already mount the same socket, as in the normal
|
||||||
|
Docker-based `act_runner` setup. Restart the runner after changing its config.
|
||||||
|
|
||||||
|
Docker socket access is equivalent to control of the Docker host. Use a trusted,
|
||||||
|
preferably repository-level runner. The build workflow runs only for changes on
|
||||||
|
`main` under `runner-image/` or its own workflow file; it never runs for pull
|
||||||
|
requests.
|
||||||
|
|
||||||
|
### Image publishing flow
|
||||||
|
|
||||||
|
The **Build runner image** workflow:
|
||||||
|
|
||||||
|
1. Starts in `node:20-bookworm` and installs the Docker client.
|
||||||
|
2. Builds using only `runner-image/` as context, so `.env` and outage state are
|
||||||
|
never included.
|
||||||
|
3. Runs import, pytest, and Ruff smoke checks inside the candidate image.
|
||||||
|
4. Pushes an immutable tag using the first 12 characters of the Git commit.
|
||||||
|
5. Updates `latest` only after the candidate passes verification.
|
||||||
|
|
||||||
|
It runs automatically when `runner-image/**` changes on `main` and can also be
|
||||||
|
started manually. Image builds require Debian mirrors, Docker Hub, PyPI, Gitea,
|
||||||
|
and access to the Docker socket. Normal test and hourly runs only need Gitea,
|
||||||
`gitea.com`, SAAPA, and EitaaYar.
|
`gitea.com`, SAAPA, and EitaaYar.
|
||||||
|
|
||||||
1. Build `daily-blackout-check-runner:latest` on the runner's Docker host.
|
Deployment order:
|
||||||
2. Enable Actions in the repository settings.
|
|
||||||
3. Confirm an online Docker runner advertises `ubuntu-latest`.
|
1. Enable Packages and Actions for the repository/owner.
|
||||||
4. Add these repository Actions secrets:
|
2. Configure the runner socket permission and restart it.
|
||||||
`BARGHEMAN_TOKEN`, `EITAAYAR_TOKEN`, `CHAT_ID`, and `BILL_IDS`.
|
3. Add all repository Actions secrets listed above.
|
||||||
5. Run the test workflow manually.
|
4. Run **Build runner image** manually and confirm both registry tags appear.
|
||||||
|
5. Run **Test blackout notifier** manually.
|
||||||
6. Run **Hourly blackout check** manually once and inspect the notification and
|
6. Run **Hourly blackout check** manually once and inspect the notification and
|
||||||
resulting state commit.
|
resulting state commit.
|
||||||
7. Leave the `@hourly` schedule enabled.
|
7. Leave the `@hourly` schedule enabled.
|
||||||
@@ -104,11 +144,6 @@ Its checkout credential must retain the default ability to push to the current
|
|||||||
repository. Scheduled jobs should not be manually overlapped; in the rare event
|
repository. Scheduled jobs should not be manually overlapped; in the rare event
|
||||||
of a push race, the job fails and unsaved notices may be repeated on the next run.
|
of a push race, the job fails and unsaved notices may be repeated on the next run.
|
||||||
|
|
||||||
If a workflow tries to pull the local image instead of using it, ensure the image
|
|
||||||
exists in the same Docker daemon used by `act_runner` and set
|
|
||||||
`container.force_pull: false` in the runner's generated `config.yaml`, then
|
|
||||||
restart the runner.
|
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
Reference in New Issue
Block a user