-
Notifications
You must be signed in to change notification settings - Fork 5
154 lines (140 loc) · 5.42 KB
/
Copy pathbuild-and-publish.yaml
File metadata and controls
154 lines (140 loc) · 5.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# This workflow builds and optionally pushes a Docker image to GHCR and Docker Hub
# under multiple repository aliases (auto_docker_proxy and traefik_network_connector).
#
# Triggers:
# 1. Push to 'main' branch (builds and pushes as 'latest')
# 2. Push of tags 'v*.*.*' (builds and pushes as SemVer)
# 3. Pull Requests (build only by default; add label 'ci:push-image' to also push)
#
# Features:
# - Multi-platform build
# - Multi-registry push (GHCR & Docker Hub)
# - GitHub Actions cache
# - Cosign OIDC signing for main/tag pushes
name: Build and Push Docker (Multi-Repo Alias)
on:
push:
branches:
- main
tags:
- 'v*.*.*' # Trigger on version tags like v1.0.0
pull_request:
types: [opened, synchronize, reopened, labeled]
jobs:
build-push-sign:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write # Required for OIDC signing
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Determine push strategy
id: strategy
env:
EVENT_NAME: ${{ github.event_name }}
PR_LABELS: ${{ toJSON(github.event.pull_request.labels.*.name) }}
shell: bash
run: |
if [[ "$EVENT_NAME" == "push" ]]; then
echo "Push event: build and push."
echo "should_push=true" >> "$GITHUB_OUTPUT"
elif [[ "$EVENT_NAME" == "pull_request" ]]; then
# Push only if the 'ci:push-image' label is present on the PR
HAS_LABEL=$(echo "$PR_LABELS" | grep -c '"ci:push-image"' || true)
if [[ "$HAS_LABEL" -gt 0 ]]; then
echo "PR has 'ci:push-image' label: build and push."
echo "should_push=true" >> "$GITHUB_OUTPUT"
else
echo "PR without 'ci:push-image' label: build only."
echo "should_push=false" >> "$GITHUB_OUTPUT"
fi
else
echo "should_push=false" >> "$GITHUB_OUTPUT"
fi
- name: Log in to GitHub Container Registry
if: steps.strategy.outputs.should_push == 'true'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to Docker Hub
if: steps.strategy.outputs.should_push == 'true'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Docker metadata (multi-repo)
id: meta
uses: docker/metadata-action@v5
with:
# Define all four image names. The generated tags will be applied to each of them.
images: |
ghcr.io/obeone/auto_docker_proxy
docker.io/obeoneorg/auto_docker_proxy
ghcr.io/obeone/traefik_network_connector
docker.io/obeoneorg/traefik_network_connector
tags: |
# For pushes to the 'main' branch, tag the image as 'latest'.
type=ref,event=branch,enable=${{ github.ref_name == 'main' }},prefix=,suffix=latest
# For 'v*.*.*' tags, generate SemVer tags (e.g., v1.2.3, v1.2, v1).
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
# For 'pull_request' events, tag the image as 'pr-XXX' (where XXX is the PR number).
type=ref,event=pr
- name: Build (and push if applicable)
id: build-and-push
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: ${{ steps.strategy.outputs.should_push == 'true' }}
platforms: |
linux/amd64
linux/arm64
linux/i386
linux/armhf
linux/armel
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
# Pass the clean version (e.g., 1.0.0) extracted from metadata to the Dockerfile.
VERSION=${{ steps.meta.outputs.version }}
- name: Set up cosign
if: steps.strategy.outputs.should_push == 'true' && github.event_name == 'push'
uses: sigstore/cosign-installer@v3
- name: Sign the container image with cosign
# Only signs official images built from 'main' branch pushes or tag pushes.
if: >-
${{
steps.strategy.outputs.should_push == 'true' &&
github.event_name == 'push' &&
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
}}
env:
COSIGN_EXPERIMENTAL: true
DIGEST: ${{ steps.build-and-push.outputs.digest }}
shell: bash
run: |
if [ -z "${DIGEST}" ]; then
echo "Digest is empty, aborting image signing."
exit 1
fi
echo "Signing digest: ${DIGEST}"
IMAGES=(
"ghcr.io/obeone/auto_docker_proxy"
"docker.io/obeoneorg/auto_docker_proxy"
"ghcr.io/obeone/traefik_network_connector"
"docker.io/obeoneorg/traefik_network_connector"
)
for image in "${IMAGES[@]}"; do
echo "Signing ${image}@${DIGEST}"
cosign sign --yes "${image}@${DIGEST}"
done