Skip to content

Commit 722b9fa

Browse files
authored
Merge pull request #418 from grml/docker-image
Build Docker images and publish to GitHub Package Registry
2 parents 34a8811 + 18bd18a commit 722b9fa

File tree

3 files changed

+324
-0
lines changed

3 files changed

+324
-0
lines changed

.github/workflows/docker.yml

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
name: Build and Push Docker Image
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
pull_request:
7+
branches: [ master ]
8+
9+
env:
10+
REGISTRY: ghcr.io
11+
IMAGE_NAME: ${{ github.repository }}
12+
13+
jobs:
14+
build-and-push:
15+
strategy:
16+
matrix:
17+
platform:
18+
- runner: ubuntu-latest
19+
arch: amd64
20+
- runner: ubuntu-24.04-arm
21+
arch: arm64
22+
runs-on: ${{ matrix.platform.runner }}
23+
permissions:
24+
contents: read
25+
packages: write
26+
27+
steps:
28+
- name: Checkout repository
29+
uses: actions/checkout@v4
30+
31+
- name: Set up Docker Buildx
32+
uses: docker/setup-buildx-action@v3
33+
34+
- name: Log in to Container Registry
35+
uses: docker/login-action@v3
36+
with:
37+
registry: ${{ env.REGISTRY }}
38+
username: ${{ github.actor }}
39+
password: ${{ secrets.GITHUB_TOKEN }}
40+
41+
- name: Determine version
42+
id: version
43+
run: |
44+
# Check if this is a tag build
45+
if [[ $GITHUB_REF == refs/tags/v* ]]; then
46+
VERSION=${GITHUB_REF#refs/tags/v}
47+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
48+
else
49+
# Get last tag and commit hash
50+
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "0.0.0")
51+
COMMIT_HASH=$(git rev-parse --short HEAD)
52+
VERSION="${LAST_TAG}+git${COMMIT_HASH}"
53+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
54+
fi
55+
echo "Git commit: $GITHUB_SHA"
56+
echo "Version: $VERSION"
57+
58+
- name: Build Debian package for dependency extraction
59+
id: deps
60+
run: |
61+
sudo apt-get update
62+
sudo apt-get install -y build-essential devscripts equivs
63+
64+
# Use mk-build-deps to install build dependencies
65+
sudo mk-build-deps -ir -t 'apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends -y' debian/control
66+
67+
# Build source package and extract to /tmp
68+
cd /tmp
69+
dpkg-source -b "$GITHUB_WORKSPACE"
70+
dpkg-source -x ./*.dsc builddir
71+
cd builddir
72+
73+
# Build binary package
74+
dpkg-buildpackage -b --no-sign
75+
76+
# Extract dependencies from built package
77+
DEPENDS=$(dpkg-deb -f ../grml-live_*.deb Depends)
78+
RECOMMENDS=$(dpkg-deb -f ../grml-live_*.deb Recommends || echo "")
79+
80+
echo "depends=$DEPENDS" >> "$GITHUB_OUTPUT"
81+
echo "recommends=$RECOMMENDS" >> "$GITHUB_OUTPUT"
82+
echo "Dependencies: $DEPENDS"
83+
echo "Recommends: $RECOMMENDS"
84+
85+
- name: Extract metadata
86+
id: meta
87+
uses: docker/metadata-action@v5
88+
with:
89+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
90+
tags: |
91+
type=ref,event=branch,suffix=-${{ matrix.platform.arch }}
92+
type=ref,event=pr,suffix=-${{ matrix.platform.arch }}
93+
type=raw,value=latest-${{ matrix.platform.arch }},enable={{is_default_branch}}
94+
95+
- name: Build and push Docker image
96+
uses: docker/build-push-action@v5
97+
with:
98+
context: .
99+
file: ./Dockerfile
100+
push: true
101+
tags: ${{ steps.meta.outputs.tags }}
102+
labels: |
103+
${{ steps.meta.outputs.labels }}
104+
org.opencontainers.image.revision=${{ github.sha }}
105+
grml-live.version=${{ steps.version.outputs.version }}
106+
build-args: |
107+
GRML_LIVE_VERSION=${{ steps.version.outputs.version }}
108+
GIT_COMMIT=${{ github.sha }}
109+
DEPENDS=${{ steps.deps.outputs.depends }}
110+
RECOMMENDS=${{ steps.deps.outputs.recommends }}
111+
cache-from: type=gha
112+
cache-to: type=gha,mode=max
113+
platforms: linux/${{ matrix.platform.arch }}
114+
115+
create-manifest:
116+
runs-on: ubuntu-latest
117+
needs: build-and-push
118+
permissions:
119+
contents: read
120+
packages: write
121+
122+
steps:
123+
- name: Log in to Container Registry
124+
uses: docker/login-action@v3
125+
with:
126+
registry: ${{ env.REGISTRY }}
127+
username: ${{ github.actor }}
128+
password: ${{ secrets.GITHUB_TOKEN }}
129+
130+
- name: Create multi-platform manifest
131+
env:
132+
REGISTRY: ${{ env.REGISTRY }}
133+
IMAGE_NAME: ${{ env.IMAGE_NAME }}
134+
run: |
135+
# Determine image tags without architecture suffix
136+
if [[ $GITHUB_REF == refs/tags/v* ]]; then
137+
TAG="${GITHUB_REF#refs/tags/v}"
138+
docker buildx imagetools create \
139+
--tag "$REGISTRY/$IMAGE_NAME:$TAG" \
140+
"$REGISTRY/$IMAGE_NAME:$TAG-amd64" \
141+
"$REGISTRY/$IMAGE_NAME:$TAG-arm64"
142+
elif [[ $GITHUB_REF == refs/heads/master ]]; then
143+
docker buildx imagetools create \
144+
--tag "$REGISTRY/$IMAGE_NAME:latest" \
145+
"$REGISTRY/$IMAGE_NAME:latest-amd64" \
146+
"$REGISTRY/$IMAGE_NAME:latest-arm64"
147+
elif [[ $GITHUB_REF == refs/pull/* ]]; then
148+
PR_NUMBER=$(echo "$GITHUB_REF" | sed 's|refs/pull/||' | sed 's|/merge||')
149+
docker buildx imagetools create \
150+
--tag "$REGISTRY/$IMAGE_NAME:pr-$PR_NUMBER" \
151+
"$REGISTRY/$IMAGE_NAME:pr-$PR_NUMBER-amd64" \
152+
"$REGISTRY/$IMAGE_NAME:pr-$PR_NUMBER-arm64"
153+
else
154+
BRANCH_NAME="${GITHUB_REF#refs/heads/}"
155+
docker buildx imagetools create \
156+
--tag "$REGISTRY/$IMAGE_NAME:$BRANCH_NAME" \
157+
"$REGISTRY/$IMAGE_NAME:$BRANCH_NAME-amd64" \
158+
"$REGISTRY/$IMAGE_NAME:$BRANCH_NAME-arm64"
159+
fi
160+
161+
162+
comment-pr:
163+
runs-on: ubuntu-latest
164+
if: github.event_name == 'pull_request'
165+
needs: create-manifest
166+
permissions:
167+
contents: read
168+
pull-requests: write
169+
170+
steps:
171+
- name: Comment PR with docker pull command
172+
run: |
173+
# Check if comment already exists
174+
EXISTING_COMMENT=$(gh api repos/${{ github.repository }}/issues/${{ github.event.number }}/comments --jq '.[] | select(.body | contains("Docker image for this PR is available")) | .id' || echo "")
175+
176+
if [ -z "$EXISTING_COMMENT" ]; then
177+
gh api repos/${{ github.repository }}/issues/${{ github.event.number }}/comments \
178+
--method POST \
179+
--field body='🐳 Docker image for this PR is available:
180+
181+
```bash
182+
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:pr-${{ github.event.number }}
183+
```'
184+
else
185+
echo "Comment already exists, skipping"
186+
fi
187+
env:
188+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
189+
190+
cleanup-pr-images:
191+
runs-on: ubuntu-latest
192+
if: github.event_name == 'pull_request' && (github.event.action == 'closed' || github.event.action == 'merged')
193+
permissions:
194+
packages: write
195+
196+
steps:
197+
- name: Log in to Container Registry
198+
uses: docker/login-action@v3
199+
with:
200+
registry: ${{ env.REGISTRY }}
201+
username: ${{ github.actor }}
202+
password: ${{ secrets.GITHUB_TOKEN }}
203+
204+
- name: Delete PR image
205+
run: |
206+
# Delete the PR-specific image when PR is closed/merged
207+
gh api --method DELETE \
208+
"/orgs/${{ github.repository_owner }}/packages/container/${{ github.event.repository.name }}/versions" \
209+
-f name="pr-${{ github.event.number }}" || true
210+
env:
211+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Dockerfile

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
FROM debian:trixie
2+
3+
# Build arguments for version, git commit, and dependencies
4+
ARG GRML_LIVE_VERSION
5+
ARG GIT_COMMIT
6+
ARG DEPENDS
7+
ARG RECOMMENDS
8+
9+
RUN apt-get update && \
10+
PACKAGES="$DEPENDS${RECOMMENDS:+, $RECOMMENDS}, netbase, git, python3-yaml" && \
11+
apt-get satisfy -y "$PACKAGES" && \
12+
rm -rf /var/lib/apt/lists/*
13+
14+
# Copy grml-live checkout to /opt/grml-live
15+
COPY . /opt/grml-live
16+
17+
# Create directory for optional grml-live-grml checkout
18+
RUN mkdir -p /opt/grml-live-grml
19+
20+
# Update version in grml-live script
21+
RUN if [ -n "$GRML_LIVE_VERSION" ]; then \
22+
sed -i "/^GRML_LIVE_VERSION=/c\\GRML_LIVE_VERSION='$GRML_LIVE_VERSION'" /opt/grml-live/grml-live; \
23+
fi
24+
25+
# Add git commit and version as labels
26+
LABEL org.opencontainers.image.revision="$GIT_COMMIT" \
27+
grml-live.version="$GRML_LIVE_VERSION"
28+
29+
# Copy entrypoint script
30+
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
31+
RUN chmod +x /usr/local/bin/entrypoint.sh
32+
33+
# Set working directory
34+
WORKDIR /workspace
35+
36+
# Set entrypoint
37+
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
38+
CMD ["help"]

entrypoint.sh

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Set default grml-live path
6+
GRML_LIVE_PATH="/opt/grml-live"
7+
8+
# Add grml-live to PATH
9+
export PATH="$GRML_LIVE_PATH:$PATH"
10+
11+
# Check if user provided custom grml-live-grml checkout
12+
if [ -d "/opt/grml-live-grml" ] && [ "$(ls -A /opt/grml-live-grml 2>/dev/null)" ]; then
13+
echo "Using custom grml-live-grml checkout from /opt/grml-live-grml"
14+
export GRML_LIVE_GRML_PATH="/opt/grml-live-grml"
15+
fi
16+
17+
# Function to show help
18+
show_help() {
19+
cat << EOF
20+
grml-live Docker Container
21+
22+
Usage:
23+
docker run [docker-options] <image> <command> [args...]
24+
25+
Commands:
26+
grml-live [args...] Run grml-live with specified arguments
27+
build [args...] Run build-driver/build with specified arguments
28+
help Show this help message
29+
30+
Examples:
31+
# Run grml-live (mount output directory)
32+
docker run --rm -v "\$PWD:/workspace" \\
33+
<image> grml-live -f GRMLBASE -o /workspace/output
34+
35+
# Run build-driver (mount workspace for config and output)
36+
docker run --rm -v "\$PWD:/workspace" \\
37+
<image> build daily /workspace/config/daily full arm64 testing
38+
39+
# Mount custom grml-live checkout
40+
docker run --rm -v "\$PWD:/workspace" \\
41+
-v /path/to/grml-live:/opt/grml-live \\
42+
<image> grml-live [args...]
43+
44+
# Mount custom grml-live-grml checkout
45+
docker run --rm -v "\$PWD:/workspace" \\
46+
-v /path/to/grml-live:/opt/grml-live \\
47+
-v /path/to/grml-live-grml:/opt/grml-live-grml \\
48+
<image> grml-live [args...]
49+
50+
EOF
51+
}
52+
53+
# Parse the first argument and execute accordingly
54+
case "$1" in
55+
"grml-live")
56+
shift
57+
exec grml-live "$@"
58+
;;
59+
"build")
60+
shift
61+
exec "$GRML_LIVE_PATH/build-driver/build" "/opt/grml-live" "$@"
62+
;;
63+
"help"|"--help"|"-h")
64+
show_help
65+
;;
66+
"")
67+
show_help
68+
;;
69+
*)
70+
echo "Unknown command: $1"
71+
echo ""
72+
show_help
73+
exit 1
74+
;;
75+
esac

0 commit comments

Comments
 (0)