Skip to content

Commit 13915bb

Browse files
authored
feat(docker): allow for docker release builds to be multi-platform (#27055)
1 parent 5951f6c commit 13915bb

File tree

4 files changed

+72
-53
lines changed

4 files changed

+72
-53
lines changed

.github/workflows/docker-release.yml

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Docker Publish Release
22

33
on:
44
release:
5-
types: [published]
5+
types: [published, edited]
66

77
# Can be triggered manually
88
workflow_dispatch:
@@ -43,14 +43,6 @@ jobs:
4343
strategy:
4444
matrix:
4545
build_preset: ["dev", "lean", "py310", "websocket", "dockerize"]
46-
platform: ["linux/amd64", "linux/arm64"]
47-
exclude:
48-
# disabling because slow! no python wheels for arm/py39 and
49-
# QEMU is slow!
50-
- build_preset: "dev"
51-
platform: "linux/arm64"
52-
- build_preset: "lean"
53-
platform: "linux/arm64"
5446
fail-fast: false
5547
steps:
5648
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
@@ -88,8 +80,10 @@ jobs:
8880
EVENT="release"
8981
fi
9082
pip install click
83+
# Make a multi-platform image
9184
./scripts/build_docker.py \
9285
${{ matrix.build_preset }} \
9386
"$EVENT" \
94-
--build_context_ref "$RELEASE" \
95-
--platform ${{ matrix.platform }} $FORCE_LATEST
87+
--build_context_ref "$RELEASE" $FORCE_LATEST \
88+
--platform "linux/arm64" \
89+
--platform "linux/amd64"

.github/workflows/ephemeral-env.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,9 @@ jobs:
143143
env:
144144
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
145145
ECR_REPOSITORY: superset-ci
146-
SHA: ${{ steps.get-sha.outputs.sha }}
147146
IMAGE_TAG: apache/superset:${{ steps.get-sha.outputs.sha }}-ci
148147
run: |
149-
docker tag $IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:$SHA
148+
docker tag $IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:pr-${{ github.event.issue.number }}-ci
150149
docker push -a $ECR_REGISTRY/$ECR_REPOSITORY
151150
152151
ephemeral-env-up:
@@ -181,7 +180,7 @@ jobs:
181180
aws ecr describe-images \
182181
--registry-id $(echo "${{ steps.login-ecr.outputs.registry }}" | grep -Eo "^[0-9]+") \
183182
--repository-name superset-ci \
184-
--image-ids imageTag=${{ steps.get-sha.outputs.sha }}
183+
--image-ids imageTag=pr-${{ github.event.issue.number }}-ci
185184
186185
- name: Fail on missing container image
187186
if: steps.check-image.outcome == 'failure'
@@ -204,7 +203,7 @@ jobs:
204203
with:
205204
task-definition: .github/workflows/ecs-task-definition.json
206205
container-name: superset-ci
207-
image: ${{ steps.login-ecr.outputs.registry }}/superset-ci:pr-${{ github.event.issue.number }}
206+
image: ${{ steps.login-ecr.outputs.registry }}/superset-ci:pr-${{ github.event.issue.number }}-ci
208207

209208
- name: Update env vars in the Amazon ECS task definition
210209
run: |

scripts/build_docker.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ def run_cmd(command: str) -> str:
4040
output += line
4141

4242
process.wait() # Wait for the subprocess to finish
43+
44+
if process.returncode != 0:
45+
raise subprocess.CalledProcessError(process.returncode, command, output)
46+
4347
return output
4448

4549

@@ -79,7 +83,7 @@ def make_docker_tag(l: list[str]) -> str:
7983

8084
def get_docker_tags(
8185
build_preset: str,
82-
build_platform: str,
86+
build_platforms: list[str],
8387
sha: str,
8488
build_context: str,
8589
build_context_ref: str,
@@ -91,17 +95,18 @@ def get_docker_tags(
9195
tags: set[str] = set()
9296
tag_chunks: list[str] = []
9397

94-
short_build_platform = build_platform.replace("linux/", "").replace("64", "")
95-
9698
is_latest = is_latest_release(build_context_ref)
9799

98100
if build_preset != "lean":
99101
# Always add the preset_build name if different from default (lean)
100102
tag_chunks += [build_preset]
101103

102-
if short_build_platform != "amd":
103-
# Always a platform indicator if different from default (amd)
104-
tag_chunks += [short_build_platform]
104+
if len(build_platforms) == 1:
105+
build_platform = build_platforms[0]
106+
short_build_platform = build_platform.replace("linux/", "").replace("64", "")
107+
if short_build_platform != "amd":
108+
# Always a platform indicator if different from default (amd)
109+
tag_chunks += [short_build_platform]
105110

106111
# Always craft a tag for the SHA
107112
tags.add(make_docker_tag([sha] + tag_chunks))
@@ -123,7 +128,7 @@ def get_docker_tags(
123128

124129
def get_docker_command(
125130
build_preset: str,
126-
build_platform: str,
131+
build_platforms: list[str],
127132
is_authenticated: bool,
128133
sha: str,
129134
build_context: str,
@@ -160,7 +165,7 @@ def get_docker_command(
160165

161166
tags = get_docker_tags(
162167
build_preset,
163-
build_platform,
168+
build_platforms,
164169
sha,
165170
build_context,
166171
build_context_ref,
@@ -170,8 +175,14 @@ def get_docker_command(
170175

171176
docker_args = "--load" if not is_authenticated else "--push"
172177
target_argument = f"--target {build_target}" if build_target else ""
173-
short_build_platform = build_platform.replace("linux/", "").replace("64", "")
174-
cache_ref = f"{CACHE_REPO}:{py_ver}-{short_build_platform}"
178+
179+
cache_ref = f"{CACHE_REPO}:{py_ver}"
180+
if len(build_platforms) == 1:
181+
build_platform = build_platforms[0]
182+
short_build_platform = build_platform.replace("linux/", "").replace("64", "")
183+
cache_ref = f"{CACHE_REPO}:{py_ver}-{short_build_platform}"
184+
platform_arg = "--platform " + ",".join(build_platforms)
185+
175186
cache_from_arg = f"--cache-from=type=registry,ref={cache_ref}"
176187
cache_to_arg = (
177188
f"--cache-to=type=registry,mode=max,ref={cache_ref}" if is_authenticated else ""
@@ -187,7 +198,7 @@ def get_docker_command(
187198
{cache_from_arg} \\
188199
{cache_to_arg} \\
189200
{build_arg} \\
190-
--platform {build_platform} \\
201+
{platform_arg} \\
191202
--label sha={sha} \\
192203
--label target={build_target} \\
193204
--label build_trigger={build_context} \\
@@ -206,20 +217,23 @@ def get_docker_command(
206217
@click.option(
207218
"--platform",
208219
type=click.Choice(["linux/arm64", "linux/amd64"]),
209-
default="linux/amd64",
220+
default=["linux/amd64"],
221+
multiple=True,
210222
)
211223
@click.option("--build_context_ref", help="a reference to the pr, release or branch")
212224
@click.option("--dry-run", is_flag=True, help="Run the command in dry-run mode.")
225+
@click.option("--verbose", is_flag=True, help="Print more info")
213226
@click.option(
214227
"--force-latest", is_flag=True, help="Force the 'latest' tag on the release"
215228
)
216229
def main(
217230
build_preset: str,
218231
build_context: str,
219232
build_context_ref: str,
220-
platform: str,
233+
platform: list[str],
221234
dry_run: bool,
222235
force_latest: bool,
236+
verbose: bool,
223237
) -> None:
224238
"""
225239
This script executes docker build and push commands based on given arguments.
@@ -262,6 +276,8 @@ def main(
262276
"""
263277
)
264278
script = script + docker_build_command
279+
if verbose:
280+
run_cmd("cat Dockerfile")
265281
stdout = run_cmd(script)
266282
else:
267283
print("Dry Run - Docker Build Command:")

0 commit comments

Comments
 (0)