Use shared runner image build action
This commit is contained in:
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@@ -0,0 +1,2 @@
|
||||
**
|
||||
!requirements.lock
|
||||
@@ -5,7 +5,8 @@ on:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- runner-image/**
|
||||
- requirements.lock
|
||||
- .dockerignore
|
||||
- .gitea/workflows/build-runner-image.yml
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -13,7 +14,7 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: mahgit.ir/meghdadfadaee/daily-blackout-check-base:node-20-bookworm
|
||||
image: mahgit.ir/meghdadfadaee/build-runner-image-base:node-20-bookworm
|
||||
credentials:
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
@@ -21,54 +22,15 @@ jobs:
|
||||
- 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"
|
||||
uses: https://mahgit.ir/MeghdadFadaee/build-runner-image-action@v1
|
||||
with:
|
||||
registry: mahgit.ir
|
||||
image: mahgit.ir/meghdadfadaee/daily-blackout-check-runner
|
||||
source-url: https://mahgit.ir/MeghdadFadaee/daily-blackout-check
|
||||
registry-username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
registry-token: ${{ secrets.REGISTRY_TOKEN }}
|
||||
verify-commands: |
|
||||
docker run --rm "$IMAGE_REF" python -c "import dotenv, jdatetime, requests"
|
||||
docker run --rm "$IMAGE_REF" pytest --version
|
||||
docker run --rm "$IMAGE_REF" ruff --version
|
||||
|
||||
37
README.md
37
README.md
@@ -77,7 +77,7 @@ The Node base image is also mirrored in Gitea, so image builds do not contact
|
||||
Docker Hub:
|
||||
|
||||
```text
|
||||
mahgit.ir/meghdadfadaee/daily-blackout-check-base:node-20-bookworm
|
||||
mahgit.ir/meghdadfadaee/build-runner-image-base:node-20-bookworm
|
||||
```
|
||||
|
||||
### Registry credentials
|
||||
@@ -113,27 +113,32 @@ 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.
|
||||
preferably repository-level runner. The build workflow runs only for changes to
|
||||
the root image lock, `.dockerignore`, or its own workflow on `main`; it never
|
||||
runs for pull requests.
|
||||
|
||||
### Image publishing flow
|
||||
|
||||
The **Build runner image** workflow:
|
||||
|
||||
1. Starts in the Gitea-hosted `daily-blackout-check-base:node-20-bookworm`
|
||||
image 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.
|
||||
1. Starts in the shared Gitea-hosted `build-runner-image-base:node-20-bookworm`
|
||||
image.
|
||||
2. Calls the shared Gitea action
|
||||
`MeghdadFadaee/build-runner-image-action@v1` to install the Docker client,
|
||||
authenticate, build, verify, and publish.
|
||||
3. Uses the action's shared Dockerfile with the root `requirements.lock`.
|
||||
`.dockerignore` restricts the build context to that lock, so `.env`, source,
|
||||
and outage state are never sent to Docker.
|
||||
4. Runs import, pytest, and Ruff smoke checks inside the candidate image.
|
||||
5. Pushes an immutable 12-character Git revision tag and 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, PyPI, Gitea, and access
|
||||
to the Docker socket. Normal test and hourly runs only need Gitea, `gitea.com`,
|
||||
SAAPA, and EitaaYar. The mirrored Node image is intentionally static; refresh it
|
||||
from the upstream `node:20-bookworm` image when adopting Node security updates.
|
||||
It runs automatically when `requirements.lock`, `.dockerignore`, or its workflow
|
||||
changes on `main`, and can also be started manually. Image builds require Debian
|
||||
mirrors, PyPI, Gitea, and access to the Docker socket. Normal test and hourly
|
||||
runs only need Gitea, `gitea.com`, SAAPA, and EitaaYar. The mirrored Node image
|
||||
is intentionally static; refresh it from the upstream `node:20-bookworm` image
|
||||
when adopting Node security updates.
|
||||
|
||||
Deployment order:
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
FROM mahgit.ir/meghdadfadaee/daily-blackout-check-base:node-20-bookworm
|
||||
|
||||
RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
git \
|
||||
python3 \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
tzdata && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY requirements.lock /tmp/requirements.lock
|
||||
|
||||
RUN python3 -m venv /opt/blackout-venv && \
|
||||
/opt/blackout-venv/bin/pip install --no-cache-dir -r /tmp/requirements.lock && \
|
||||
/opt/blackout-venv/bin/python -c "import dotenv, jdatetime, requests" && \
|
||||
/opt/blackout-venv/bin/pytest --version && \
|
||||
/opt/blackout-venv/bin/ruff --version && \
|
||||
rm /tmp/requirements.lock
|
||||
|
||||
ENV PATH="/opt/blackout-venv/bin:$PATH" \
|
||||
PYTHONDONTWRITEBYTECODE="1" \
|
||||
PYTHONUNBUFFERED="1"
|
||||
|
||||
CMD ["bash"]
|
||||
Reference in New Issue
Block a user