-
Notifications
You must be signed in to change notification settings - Fork 5
/
action.yml
203 lines (180 loc) · 7.46 KB
/
action.yml
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
name: Conditional Container Builder with Fallback
description: Build if trigger conditions are met, else use fallback image
branding:
icon: package
color: blue
inputs:
### Required
package:
description: Package name; e.g. backend, frontend
required: true
tag:
description: Default tag; e.g. pr#, test, prod
required: true
### Typical / recommended
tag_fallback:
description: Where to pull default images from; e.g. prod, test
triggers:
description: Paths used to trigger a build; e.g. ('./backend/' './frontend/)
build_context:
description: Build context, not required for self-contained package/default directory
build_file:
description: Dockerfile with path, not required for self-contained package/default directory
keep_versions:
description: Number of versions to keep; omit to skip
### Usually a bad idea / not recommended
build_args:
description: A list of build-time variables, generally not advisable
value: "BUILDKIT_INLINE_CACHE=1"
diff_branch:
description: Branch to diff against
default: ${{ github.event.repository.default_branch }}
keep_regex:
description: Regex for tags to skip when keep_versions is provided; defaults to test and prod
default: "^(prod|test|latest)$"
repository:
description: Non-default repo to clone
default: ${{ github.repository }}
token:
description: Specify token (GH or PAT), instead of inheriting one from the calling workflow
default: ${{ github.token }}
outputs:
digest:
description: 'Digest of the built image; e.g. sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
value: ${{ steps.digest_new.outputs.digest }}
digest_old:
description: 'Digest of the previous image, if one existed'
value: ${{ steps.digest_old.outputs.digest }}
triggered:
description: Did a deployment trigger? [true|false]
value: ${{ steps.diff.outputs.triggered }}
runs:
using: composite
steps:
# Cleanup if inputs.keep_versions provided
- name: GHCR Cleanup
if: ${{ inputs.keep_versions }}
uses: actions/[email protected]
with:
package-name: "${{ github.event.repository.name }}/${{ inputs.package }}"
package-type: "container"
min-versions-to-keep: ${{ inputs.keep_versions }}
ignore-versions: "${{ inputs.keep_regex }}"
# Process variables and inputs
- id: vars
shell: bash
run: |
# Inputs and variables
# Use package folder as build_context unless an override has been provided
if [ -z ${{ inputs.build_context }} ]; then
BUILD_CONTEXT=${{ inputs.package }}
else
BUILD_CONTEXT=${{ inputs.build_context }}
fi
echo "build_context=${BUILD_CONTEXT}" >> $GITHUB_OUTPUT
# Use BUILD_CONTEXT/Dockerfile as build_file unless an override has been provided
if [ -z ${{ inputs.build_file }} ]; then
BUILD_FILE=${BUILD_CONTEXT}/Dockerfile
else
BUILD_FILE=${{ inputs.build_file }}
fi
echo "build_file=${BUILD_FILE}" >> $GITHUB_OUTPUT
# Bug - Docker build hates images with capital letters
TAGS=$( echo "ghcr.io/${{ github.repository }}/${{ inputs.package }}:${{ inputs.tag }}" | tr '[:upper:]' '[:lower:]' )
echo "tags=${TAGS//[$'\r\n ']}" >> $GITHUB_OUTPUT
# Send triggers to diff action
- id: diff
uses: bcgov-nr/[email protected]
with:
triggers: ${{ inputs.triggers }}
diff_branch: ${{ inputs.diff_branch }}
# Check if a build is required (steps.build.outputs.triggered=true|false)
- name: Check for builds
env:
URL_FALLBACK: ghcr.io/${{ inputs.repository }}/${{ inputs.package }}:${{ inputs.tag_fallback }}
id: build
shell: bash
run: |
# Check for builds
echo "triggered=true" >> $GITHUB_OUTPUT
if [ "${{ steps.diff.outputs.triggered }}" == "true" ]; then
echo "Build triggered. Used bcgov-nr/action-diff-triggers."
elif [ "${{ inputs.repository }}" != "${{ github.repository }}" ]; then
echo "Build triggered. Override repository provided."
elif [ -z "${{ inputs.tag_fallback }}" ]; then
echo "Build triggered. No tag_fallback provided."
elif [[ ! $(docker manifest inspect ${URL_FALLBACK}) ]]; then
echo "Build triggered. Fallback tag (tag_fallback) not usable."
else
echo "Container build not required"
echo "triggered=false" >> $GITHUB_OUTPUT
fi
# If a build is not required, reuse a previous image
- name: Recycle/retag Previous Images
uses: shrink/actions-docker-registry-tag@v4
if: steps.build.outputs.triggered != 'true'
with:
registry: ghcr.io
repository: ${{ inputs.repository }}/${{ inputs.package }}
target: ${{ inputs.tag_fallback }}
tags: ${{ inputs.tag }}
# If a build is required and replaces a previous image, save its SHA
- name: Check for a previous SHA
id: digest_old
shell: bash
run: |
DIGEST=$((docker manifest inspect ${{ steps.vars.outputs.tags }} || echo )| jq -r '.manifests[0].digest')
echo "digest=${DIGEST}" >> $GITHUB_OUTPUT
# If a build is required, then checkout, login, build and push!
- uses: actions/checkout@v4
with:
repository: ${{ inputs.repository }}
- name: Add build envars to Dockerfile
if: steps.build.outputs.triggered == 'true'
env:
dockerfile: ${{ steps.vars.outputs.build_file }}
shell: bash
run: |
# Add build envars to Dockerfile
echo "ENV BUILDER_IMAGE=ghcr.io/${{ github.repository }}/${{ inputs.package }}:${{ inputs.tag }}" >> ${{ env.dockerfile }}
echo "ENV BUILDER_PACKAGE=${{ inputs.package }}" >> ${{ env.dockerfile }}
echo "ENV BUILDER_REPO=${{ github.repository }}" >> ${{ env.dockerfile }}
echo "ENV BUILDER_TAG=${{ inputs.tag }}" >> ${{ env.dockerfile }}
- name: Set up Docker Buildx
if: steps.build.outputs.triggered == 'true'
uses: docker/setup-buildx-action@v3
- name: Log in to the Container registry
if: steps.build.outputs.triggered == 'true'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ inputs.token }}
- name: Build and push ${{ inputs.package }} Docker image
if: steps.build.outputs.triggered == 'true'
uses: docker/build-push-action@v6
with:
context: ${{ steps.vars.outputs.build_context }}
file: ${{ steps.vars.outputs.build_file }}
push: true
tags: ${{ steps.vars.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: ${{ inputs.build_args }}
# Action repo needs to be present for cleanup/tests
- name: Checkout local repo to make sure action.yml is present
if: ${{ github.repository }} != ${{ inputs.repository }}
uses: actions/checkout@v4
# Get the digest of the built image
- name: Return digest of the built image
id: digest_new
shell: bash
run: |
DIGEST=$(docker manifest inspect ${{ steps.vars.outputs.tags }} | jq -r '.manifests[0].digest')
echo "digest=${DIGEST}" >> $GITHUB_OUTPUT
- shell: bash
run: |
# Summary
echo "digest_new: ${{ steps.digest_new.outputs.digest }}"
echo "digest_old: ${{ steps.digest_old.outputs.digest }}"
echo "triggered: ${{ steps.diff.outputs.triggered }}"