-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathaction.yml
More file actions
257 lines (215 loc) · 9.92 KB
/
Copy pathaction.yml
File metadata and controls
257 lines (215 loc) · 9.92 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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
name: "push-to-ghcr"
author: "@macbre"
description: "This action simplifies pushes of Docker images ot ghcr.io repository"
# https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#branding
branding:
icon: "arrow-up-circle"
color: "blue"
inputs:
github_token:
description: "Your secrets.GITHUB_TOKEN"
required: true
image_name:
description: "Image name, e.g. my-user-name/my-repo (will be lowercased)"
required: true
dockerfile:
description: "A path to the Dockerfile (if it's not in the repository's root directory)"
required: false
default: "./Dockerfile"
context:
description: "A path to the context in which the build will happen, see https://docs.docker.com/engine/reference/commandline/build/"
required: false
default: "."
repository:
description: "Docker repository to push an image to, defaults to ghcr.io"
required: true
default: "ghcr.io"
docker_io_user:
description: "A username to use when pushing an image to docker.io (defaults to the github.actor)"
required: false
docker_io_token:
description: "Your docker.io token created via https://hub.docker.com/settings/security"
required: false
image_tag:
description: Image tag or tags, e.g. latest or "1.0.0,latest". Only tag names are accepted. Will overwrite the latest tag on a push, and have no effect on a release.
required: false
# https://docs.docker.com/build/guide/build-args/
build_arg:
description: Additional build argument to be passed to the Dockerfile (e.g. NODE_AUTH_TOKEN=s3cr3t)
required: false
default: "FOO=bar"
extra_args:
description: Additional arguments to be passed to "docker build".
required: false
default: ""
# https://docs.docker.com/build/building/multi-platform/
platforms:
description: "Comma-separated list of target platforms for the build (e.g. linux/amd64,linux/arm64). When set, uses docker buildx for multi-platform builds and pushes directly to the registry."
required: false
default: ""
runs:
using: "composite"
steps:
# https://docs.docker.com/build/drivers/docker-container/#qemu
- name: Set up QEMU for multi-platform builds
if: ${{ inputs.platforms != '' }}
uses: docker/setup-qemu-action@v4
# https://docs.docker.com/build/ci/github-actions/multi-platform/
- name: Set up Docker Buildx
if: ${{ inputs.platforms != '' }}
uses: docker/setup-buildx-action@v4
# https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-to-the-container-registry
- name: Log in to the Container registry
shell: bash
env:
GITHUB_TOKEN: ${{ inputs.github_token }}
DOCKER_BUILDKIT: 1
DOCKER_IO_USER: ${{ inputs.docker_io_user }}
DOCKER_IO_TOKEN: ${{ inputs.docker_io_token }}
IMAGE_NAME: ${{ inputs.image_name }}
IMAGE_TAG: ${{ inputs.image_tag }}
run: |
echo "Using $(docker -v)"
echo "::group::Logging into the GitHub Container registry (ghcr.io) ..."
echo "${GITHUB_TOKEN}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
echo "::endgroup::"
echo "::group::Set commit tag and image name"
# github.ref: For workflows triggered by pull_request, this is the pull request merge branch.
# For workflows triggered by release, this is the release tag created.
# https://docs.github.com/en/actions/reference/contexts-reference
echo "Event received: '${{ github.event_name }}' (with a reference '${{ github.ref }}' / tag name '${{ github.event.release.tag_name }}')"
IMAGE_TAGS=()
add_image_tag() {
if [ -z "$1" ]; then
return
fi
if [[ "$1" == *"/"* || "$1" == *":"* ]]; then
echo "::error::The image_tag input accepts tag names only, not full image references: '$1'"
exit 1
fi
for EXISTING_TAG in "${IMAGE_TAGS[@]}"; do
if [ "${EXISTING_TAG}" = "$1" ]; then
return
fi
done
IMAGE_TAGS+=("$1")
}
if [ "${{ github.event_name }}" = "release" ]; then
export COMMIT_TAG="${{ github.event.release.tag_name }}"
export COMMIT_TAG=${COMMIT_TAG//v/}
add_image_tag "${COMMIT_TAG}"
else
if [ -z "${IMAGE_TAG}" ]; then
export COMMIT_TAG=latest
add_image_tag "${COMMIT_TAG}"
else
export IMAGE_TAG_LIST=${IMAGE_TAG//,/ }
for TAG in ${IMAGE_TAG_LIST}; do
add_image_tag "${TAG}"
done
if [ ${#IMAGE_TAGS[@]} -eq 0 ]; then
echo "::error::The image_tag input did not contain any tags."
exit 1
fi
export COMMIT_TAG=${IMAGE_TAGS[0]}
fi
fi
# lowercase the image name, see https://github.com/macbre/push-to-ghcr/issues/12
export IMAGE_NAME=$(echo ${IMAGE_NAME} | tr '[:upper:]' '[:lower:]')
echo "Tagging with ${IMAGE_TAGS[*]}"
echo "::endgroup::"
export BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
export GITHUB_URL=https://github.com/${{ github.repository }}
GHCR_TAG_ARGS=()
DOCKER_IO_TAG_ARGS=()
for TAG in "${IMAGE_TAGS[@]}"; do
GHCR_TAG_ARGS+=(--tag "${{ inputs.repository }}/${IMAGE_NAME}:${TAG}")
if [ -n "${DOCKER_IO_TOKEN}" ]; then
DOCKER_IO_TAG_ARGS+=(--tag "docker.io/${IMAGE_NAME}:${TAG}")
fi
done
# Common build arguments and labels used by both docker build and docker buildx build
COMMON_ARGS=(
--file ${{ inputs.dockerfile }}
--build-arg BUILDKIT_INLINE_CACHE=1
--build-arg BUILD_DATE=${BUILD_DATE}
--build-arg GITHUB_SHA=${GITHUB_SHA}
--build-arg ${{ inputs.build_arg }}
${GHCR_TAG_ARGS[@]}
${DOCKER_IO_TAG_ARGS[@]}
${{ inputs.extra_args }}
--label org.label-schema.build-date=${BUILD_DATE}
--label org.label-schema.vcs-url=${GITHUB_URL}
--label org.label-schema.vcs-ref=${GITHUB_SHA}
--label org.opencontainers.image.created=${BUILD_DATE}
--label org.opencontainers.image.source=${GITHUB_URL}
--label org.opencontainers.image.revision=${GITHUB_SHA}
)
if [ -n "${{ inputs.platforms }}" ]; then
# Multi-platform build: use docker buildx, push directly to registry
# Log into docker.io before build so buildx can push to it inline
if [ -z "${DOCKER_IO_TOKEN}" ]; then
echo "::notice::NOT pushing the Docker image to docker.io ... Provide 'docker_io_token' if needed."
DOCKER_IO_TAGS=()
else
if [ -z ${DOCKER_IO_USER} ]; then
export DOCKER_IO_USER="${{ github.actor }}"
fi
echo "::group::Logging into docker.io as ${DOCKER_IO_USER} ..."
echo "${DOCKER_IO_TOKEN}" | docker login docker.io -u "${DOCKER_IO_USER}" --password-stdin
echo "::endgroup::"
DOCKER_IO_TAGS=(--tag docker.io/${IMAGE_NAME}:${COMMIT_TAG})
fi
echo "::group::Building and pushing multi-platform Docker image: ${{ inputs.repository }}/${IMAGE_NAME}:${COMMIT_TAG} (platforms: ${{ inputs.platforms }}) ..."
set -x
>&0 docker buildx build \
--platform ${{ inputs.platforms }} \
--cache-from ${{ inputs.repository }}/${IMAGE_NAME}:latest \
"${COMMON_ARGS[@]}" \
--tag ${{ inputs.repository }}/${IMAGE_NAME}:${COMMIT_TAG} \
"${DOCKER_IO_TAGS[@]}" \
--push \
${{ inputs.context }}
set +x
echo "::endgroup::"
else
# Single-platform build: use docker build, push separately
echo "::group::Building the Docker image: ${{ inputs.repository }}/${IMAGE_NAME}:${COMMIT_TAG} from ${{ inputs.dockerfile }} in ${{ inputs.context }} context ..."
# https://docs.docker.com/develop/develop-images/build_enhancements/
# https://docs.docker.com/engine/reference/commandline/build/#specifying-external-cache-sources
set -x
>&0 docker build \
--cache-from ${{ inputs.repository }}/${IMAGE_NAME}:latest \
"${COMMON_ARGS[@]}" \
--tag ${{ inputs.repository }}/${IMAGE_NAME}:${COMMIT_TAG} \
--tag docker.io/${IMAGE_NAME}:${COMMIT_TAG} \
${{ inputs.context }}
set +x
echo "::endgroup::"
echo "::group::Inspecting the image ..."
docker images
echo "Labels:"
docker image inspect ${{ inputs.repository }}/${IMAGE_NAME}:${COMMIT_TAG} | jq '.[].Config.Labels'
echo "Env variables:"
docker image inspect ${{ inputs.repository }}/${IMAGE_NAME}:${COMMIT_TAG} | jq '.[].Config.Env'
echo "::endgroup::"
echo "::group::Pushing the Docker image to ${{ inputs.repository }} ..."
for TAG in "${IMAGE_TAGS[@]}"; do
>&0 docker push ${{ inputs.repository }}/${IMAGE_NAME}:${TAG} && echo "Pushed ${{ inputs.repository }}/${IMAGE_NAME}:${TAG}"
done
echo "::endgroup::"
if [ -z "${DOCKER_IO_TOKEN}" ]; then
echo "::notice::NOT pushing the Docker image to docker.io ... Provide 'docker_io_token' if needed."
else
if [ -z ${DOCKER_IO_USER} ]; then
export DOCKER_IO_USER="${{ github.actor }}"
fi
echo "${DOCKER_IO_TOKEN}" | docker login docker.io -u "${DOCKER_IO_USER}" --password-stdin
echo "::group::Pushing the Docker image to docker.io/${IMAGE_NAME} ..."
for TAG in "${IMAGE_TAGS[@]}"; do
>&0 docker push docker.io/${IMAGE_NAME}:${TAG} && echo "Pushed docker.io/${IMAGE_NAME}:${TAG}"
done
echo "::endgroup::"
echo "::endgroup::"
fi
fi