Skip to content

Commit 923c2c6

Browse files
smiller171MaxymVlasovyermulnik
authored
feat(ci): Build multi-arch Docker images (amd64, arm64) (antonbabenko#496)
* build ARM images * Fix GH API rate limits * `docker buildx` currently does not support `load` and multi-arch at the same time. And used Github Action does not support output=type=oci --------- Co-authored-by: Maksym Vlasov <[email protected]> Co-authored-by: George L. Yermulnik <[email protected]>
1 parent f766cba commit 923c2c6

File tree

4 files changed

+75
-28
lines changed

4 files changed

+75
-28
lines changed

.github/workflows/build-image-test.yaml

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,25 @@ jobs:
2222
.dockerignore
2323
tools/entrypoint.sh
2424
25+
- name: Set up Docker Buildx
26+
uses: docker/setup-buildx-action@4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c # v2.5.0
27+
2528
- name: Build if Dockerfile changed
2629
if: steps.changed-files-specific.outputs.any_changed == 'true'
2730
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 # v4.0.0
2831
with:
2932
context: .
3033
build-args: |
3134
INSTALL_ALL=true
32-
platforms: linux/amd64
35+
platforms: linux/amd64 # Only one allowed here, see https://github.com/docker/buildx/issues/59#issuecomment-1433097926
3336
push: false
37+
load: true
3438
tags: |
3539
ghcr.io/${{ github.repository }}:${{ env.IMAGE_TAG }}
40+
# Fix multi-platform: https://github.com/docker/buildx/issues/1533
41+
provenance: false
42+
secrets: |
43+
"github_token=${{ secrets.GITHUB_TOKEN }}"
3644
3745
- name: Run structure tests
3846
if: steps.changed-files-specific.outputs.any_changed == 'true'
@@ -48,3 +56,21 @@ jobs:
4856
image: ghcr.io/${{ github.repository }}:${{ env.IMAGE_TAG }}
4957
config-file: ${{ github.workspace }}/.github/.dive-ci.yaml
5058
github-token: ${{ secrets.GITHUB_TOKEN }}
59+
60+
# Can't build both platforms and use --load at the same time
61+
# https://github.com/docker/buildx/issues/59#issuecomment-1433097926
62+
- name: Build Multi-arch docker-image
63+
if: steps.changed-files-specific.outputs.any_changed == 'true'
64+
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 # v4.0.0
65+
with:
66+
context: .
67+
build-args: |
68+
INSTALL_ALL=true
69+
platforms: linux/amd64,linux/arm64
70+
push: false
71+
tags: |
72+
ghcr.io/${{ github.repository }}:${{ env.IMAGE_TAG }}
73+
# Fix multi-platform: https://github.com/docker/buildx/issues/1533
74+
provenance: false
75+
secrets: |
76+
"github_token=${{ secrets.GITHUB_TOKEN }}"

.github/workflows/build-image.yaml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,39 @@ jobs:
2727
- name: Set tag for image
2828
run: |
2929
echo IMAGE_TAG=$([ ${{ github.ref_type }} == 'tag' ] && echo ${{ github.ref_name }} || echo 'latest') >> $GITHUB_ENV
30+
31+
- name: Set up Docker Buildx
32+
uses: docker/setup-buildx-action@4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c # v2.5.0
33+
3034
- name: Build and Push release
3135
if: github.event_name != 'schedule'
3236
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 # v4.0.0
3337
with:
3438
context: .
3539
build-args: |
3640
INSTALL_ALL=true
37-
platforms: linux/amd64
41+
platforms: linux/amd64,linux/arm64
3842
push: true
3943
tags: |
4044
ghcr.io/${{ github.repository }}:${{ env.IMAGE_TAG }}
4145
ghcr.io/${{ github.repository }}:latest
46+
# Fix multi-platform: https://github.com/docker/buildx/issues/1533
47+
provenance: false
48+
secrets: |
49+
"github_token=${{ secrets.GITHUB_TOKEN }}"
50+
4251
- name: Build and Push nightly
4352
if: github.event_name == 'schedule'
4453
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 # v4.0.0
4554
with:
4655
context: .
4756
build-args: |
4857
INSTALL_ALL=true
49-
platforms: linux/amd64
58+
platforms: linux/amd64,linux/arm64
5059
push: true
5160
tags: |
5261
ghcr.io/${{ github.repository }}:nightly
62+
# Fix multi-platform: https://github.com/docker/buildx/issues/1533
63+
provenance: false
64+
secrets: |
65+
"github_token=${{ secrets.GITHUB_TOKEN }}"

Dockerfile

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
ARG TAG=3.11.1-alpine3.17@sha256:d8b0703ce84fe5a52d485f212e9d852bcdb8606798064f5f21af57325a7cf73f
22
FROM python:${TAG} as builder
3+
ARG TARGETOS
4+
ARG TARGETARCH
35

46
WORKDIR /bin_dir
57

@@ -22,7 +24,7 @@ RUN [ ${PRE_COMMIT_VERSION} = "latest" ] && pip3 install --no-cache-dir pre-comm
2224
RUN if [ "${TERRAFORM_VERSION}" = "latest" ]; then \
2325
TERRAFORM_VERSION="$(curl -s https://api.github.com/repos/hashicorp/terraform/releases/latest | grep tag_name | grep -o -E -m 1 "[0-9.]+")" \
2426
; fi && \
25-
curl -L "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip" > terraform.zip && \
27+
curl -L "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_${TARGETOS}_${TARGETARCH}.zip" > terraform.zip && \
2628
unzip terraform.zip terraform && rm terraform.zip
2729

2830
#
@@ -74,18 +76,18 @@ RUN . /.env && \
7476
if [ "$INFRACOST_VERSION" != "false" ]; then \
7577
( \
7678
INFRACOST_RELEASES="https://api.github.com/repos/infracost/infracost/releases" && \
77-
[ "$INFRACOST_VERSION" = "latest" ] && curl -L "$(curl -s ${INFRACOST_RELEASES}/latest | grep -o -E -m 1 "https://.+?-linux-amd64.tar.gz")" > infracost.tgz \
78-
|| curl -L "$(curl -s ${INFRACOST_RELEASES} | grep -o -E "https://.+?v${INFRACOST_VERSION}/infracost-linux-amd64.tar.gz")" > infracost.tgz \
79-
) && tar -xzf infracost.tgz && rm infracost.tgz && mv infracost-linux-amd64 infracost \
79+
[ "$INFRACOST_VERSION" = "latest" ] && curl -L "$(curl -s ${INFRACOST_RELEASES}/latest | grep -o -E -m 1 "https://.+?-${TARGETOS}-${TARGETARCH}.tar.gz")" > infracost.tgz \
80+
|| curl -L "$(curl -s ${INFRACOST_RELEASES} | grep -o -E "https://.+?v${INFRACOST_VERSION}/infracost-${TARGETOS}-${TARGETARCH}.tar.gz")" > infracost.tgz \
81+
) && tar -xzf infracost.tgz && rm infracost.tgz && mv infracost-${TARGETOS}-${TARGETARCH} infracost \
8082
; fi
8183

8284
# Terraform docs
8385
RUN . /.env && \
8486
if [ "$TERRAFORM_DOCS_VERSION" != "false" ]; then \
8587
( \
8688
TERRAFORM_DOCS_RELEASES="https://api.github.com/repos/terraform-docs/terraform-docs/releases" && \
87-
[ "$TERRAFORM_DOCS_VERSION" = "latest" ] && curl -L "$(curl -s ${TERRAFORM_DOCS_RELEASES}/latest | grep -o -E -m 1 "https://.+?-linux-amd64.tar.gz")" > terraform-docs.tgz \
88-
|| curl -L "$(curl -s ${TERRAFORM_DOCS_RELEASES} | grep -o -E "https://.+?v${TERRAFORM_DOCS_VERSION}-linux-amd64.tar.gz")" > terraform-docs.tgz \
89+
[ "$TERRAFORM_DOCS_VERSION" = "latest" ] && curl -L "$(curl -s ${TERRAFORM_DOCS_RELEASES}/latest | grep -o -E -m 1 "https://.+?-${TARGETOS}-${TARGETARCH}.tar.gz")" > terraform-docs.tgz \
90+
|| curl -L "$(curl -s ${TERRAFORM_DOCS_RELEASES} | grep -o -E "https://.+?v${TERRAFORM_DOCS_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz")" > terraform-docs.tgz \
8991
) && tar -xzf terraform-docs.tgz terraform-docs && rm terraform-docs.tgz && chmod +x terraform-docs \
9092
; fi
9193

@@ -94,19 +96,22 @@ RUN . /.env \
9496
&& if [ "$TERRAGRUNT_VERSION" != "false" ]; then \
9597
( \
9698
TERRAGRUNT_RELEASES="https://api.github.com/repos/gruntwork-io/terragrunt/releases" && \
97-
[ "$TERRAGRUNT_VERSION" = "latest" ] && curl -L "$(curl -s ${TERRAGRUNT_RELEASES}/latest | grep -o -E -m 1 "https://.+?/terragrunt_linux_amd64")" > terragrunt \
98-
|| curl -L "$(curl -s ${TERRAGRUNT_RELEASES} | grep -o -E -m 1 "https://.+?v${TERRAGRUNT_VERSION}/terragrunt_linux_amd64")" > terragrunt \
99+
[ "$TERRAGRUNT_VERSION" = "latest" ] && curl -L "$(curl -s ${TERRAGRUNT_RELEASES}/latest | grep -o -E -m 1 "https://.+?/terragrunt_${TARGETOS}_${TARGETARCH}")" > terragrunt \
100+
|| curl -L "$(curl -s ${TERRAGRUNT_RELEASES} | grep -o -E -m 1 "https://.+?v${TERRAGRUNT_VERSION}/terragrunt_${TARGETOS}_${TARGETARCH}")" > terragrunt \
99101
) && chmod +x terragrunt \
100102
; fi
101103

102104

103105
# Terrascan
104106
RUN . /.env && \
105107
if [ "$TERRASCAN_VERSION" != "false" ]; then \
108+
if [ "$TARGETARCH" != "amd64" ]; then ARCH="$TARGETARCH"; else ARCH="x86_64"; fi; \
109+
# Convert the first letter to Uppercase
110+
OS="$(echo ${TARGETOS} | cut -c1 | tr '[:lower:]' '[:upper:]' | xargs echo -n; echo ${TARGETOS} | cut -c2-)"; \
106111
( \
107112
TERRASCAN_RELEASES="https://api.github.com/repos/tenable/terrascan/releases" && \
108-
[ "$TERRASCAN_VERSION" = "latest" ] && curl -L "$(curl -s ${TERRASCAN_RELEASES}/latest | grep -o -E -m 1 "https://.+?_Linux_x86_64.tar.gz")" > terrascan.tar.gz \
109-
|| curl -L "$(curl -s ${TERRASCAN_RELEASES} | grep -o -E "https://.+?${TERRASCAN_VERSION}_Linux_x86_64.tar.gz")" > terrascan.tar.gz \
113+
[ "$TERRASCAN_VERSION" = "latest" ] && curl -L "$(curl -s ${TERRASCAN_RELEASES}/latest | grep -o -E -m 1 "https://.+?_${OS}_${ARCH}.tar.gz")" > terrascan.tar.gz \
114+
|| curl -L "$(curl -s ${TERRASCAN_RELEASES} | grep -o -E "https://.+?${TERRASCAN_VERSION}_${OS}_${ARCH}.tar.gz")" > terrascan.tar.gz \
110115
) && tar -xzf terrascan.tar.gz terrascan && rm terrascan.tar.gz && \
111116
./terrascan init \
112117
; fi
@@ -116,8 +121,8 @@ RUN . /.env && \
116121
if [ "$TFLINT_VERSION" != "false" ]; then \
117122
( \
118123
TFLINT_RELEASES="https://api.github.com/repos/terraform-linters/tflint/releases" && \
119-
[ "$TFLINT_VERSION" = "latest" ] && curl -L "$(curl -s ${TFLINT_RELEASES}/latest | grep -o -E -m 1 "https://.+?_linux_amd64.zip")" > tflint.zip \
120-
|| curl -L "$(curl -s ${TFLINT_RELEASES} | grep -o -E "https://.+?/v${TFLINT_VERSION}/tflint_linux_amd64.zip")" > tflint.zip \
124+
[ "$TFLINT_VERSION" = "latest" ] && curl -L "$(curl -s ${TFLINT_RELEASES}/latest | grep -o -E -m 1 "https://.+?_${TARGETOS}_${TARGETARCH}.zip")" > tflint.zip \
125+
|| curl -L "$(curl -s ${TFLINT_RELEASES} | grep -o -E "https://.+?/v${TFLINT_VERSION}/tflint_${TARGETOS}_${TARGETARCH}.zip")" > tflint.zip \
121126
) && unzip tflint.zip && rm tflint.zip \
122127
; fi
123128

@@ -126,8 +131,8 @@ RUN . /.env && \
126131
if [ "$TFSEC_VERSION" != "false" ]; then \
127132
( \
128133
TFSEC_RELEASES="https://api.github.com/repos/aquasecurity/tfsec/releases" && \
129-
[ "$TFSEC_VERSION" = "latest" ] && curl -L "$(curl -s ${TFSEC_RELEASES}/latest | grep -o -E -m 1 "https://.+?/tfsec-linux-amd64")" > tfsec \
130-
|| curl -L "$(curl -s ${TFSEC_RELEASES} | grep -o -E -m 1 "https://.+?v${TFSEC_VERSION}/tfsec-linux-amd64")" > tfsec \
134+
[ "$TFSEC_VERSION" = "latest" ] && curl -L "$(curl -s ${TFSEC_RELEASES}/latest | grep -o -E -m 1 "https://.+?/tfsec-${TARGETOS}-${TARGETARCH}")" > tfsec \
135+
|| curl -L "$(curl -s ${TFSEC_RELEASES} | grep -o -E -m 1 "https://.+?v${TFSEC_VERSION}/tfsec-${TARGETOS}-${TARGETARCH}")" > tfsec \
131136
) && chmod +x tfsec \
132137
; fi
133138

@@ -136,8 +141,8 @@ RUN . /.env && \
136141
if [ "$TFUPDATE_VERSION" != "false" ]; then \
137142
( \
138143
TFUPDATE_RELEASES="https://api.github.com/repos/minamijoyo/tfupdate/releases" && \
139-
[ "$TFUPDATE_VERSION" = "latest" ] && curl -L "$(curl -s ${TFUPDATE_RELEASES}/latest | grep -o -E -m 1 "https://.+?_linux_amd64.tar.gz")" > tfupdate.tgz \
140-
|| curl -L "$(curl -s ${TFUPDATE_RELEASES} | grep -o -E -m 1 "https://.+?${TFUPDATE_VERSION}_linux_amd64.tar.gz")" > tfupdate.tgz \
144+
[ "$TFUPDATE_VERSION" = "latest" ] && curl -L "$(curl -s ${TFUPDATE_RELEASES}/latest | grep -o -E -m 1 "https://.+?_${TARGETOS}_${TARGETARCH}.tar.gz")" > tfupdate.tgz \
145+
|| curl -L "$(curl -s ${TFUPDATE_RELEASES} | grep -o -E -m 1 "https://.+?${TFUPDATE_VERSION}_${TARGETOS}_${TARGETARCH}.tar.gz")" > tfupdate.tgz \
141146
) && tar -xzf tfupdate.tgz tfupdate && rm tfupdate.tgz \
142147
; fi
143148

@@ -146,8 +151,8 @@ RUN . /.env && \
146151
if [ "$HCLEDIT_VERSION" != "false" ]; then \
147152
( \
148153
HCLEDIT_RELEASES="https://api.github.com/repos/minamijoyo/hcledit/releases" && \
149-
[ "$HCLEDIT_VERSION" = "latest" ] && curl -L "$(curl -s ${HCLEDIT_RELEASES}/latest | grep -o -E -m 1 "https://.+?_linux_amd64.tar.gz")" > hcledit.tgz \
150-
|| curl -L "$(curl -s ${HCLEDIT_RELEASES} | grep -o -E -m 1 "https://.+?${HCLEDIT_VERSION}_linux_amd64.tar.gz")" > hcledit.tgz \
154+
[ "$HCLEDIT_VERSION" = "latest" ] && curl -L "$(curl -s ${HCLEDIT_RELEASES}/latest | grep -o -E -m 1 "https://.+?_${TARGETOS}_${TARGETARCH}.tar.gz")" > hcledit.tgz \
155+
|| curl -L "$(curl -s ${HCLEDIT_RELEASES} | grep -o -E -m 1 "https://.+?${HCLEDIT_VERSION}_${TARGETOS}_${TARGETARCH}.tar.gz")" > hcledit.tgz \
151156
) && tar -xzf hcledit.tgz hcledit && rm hcledit.tgz \
152157
; fi
153158

README.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,10 @@ All available tags [here](https://github.com/antonbabenko/pre-commit-terraform/p
9797

9898
**Build from scratch**:
9999

100-
When `--build-arg` is not specified, the latest version of `pre-commit` and `terraform` will be only installed.
100+
> **Note**: To build image you need to have [`docker buildx`](https://docs.docker.com/build/install-buildx/) enabled as default builder.
101+
> Otherwise - provide `TARGETOS` and `TARGETARCH` as additional `--build-arg`'s to `docker build`.
102+
103+
When hooks-related `--build-arg`s are not specified, only the latest version of `pre-commit` and `terraform` will be installed.
101104

102105
```bash
103106
git clone [email protected]:antonbabenko/pre-commit-terraform.git
@@ -184,7 +187,7 @@ curl -L "$(curl -s https://api.github.com/repos/minamijoyo/hcledit/releases/late
184187

185188
We highly recommend using [WSL/WSL2](https://docs.microsoft.com/en-us/windows/wsl/install) with Ubuntu and following the Ubuntu installation guide. Or use Docker.
186189

187-
> Note: We won't be able to help with issues that can't be reproduced in Linux/Mac.
190+
> **Note**: We won't be able to help with issues that can't be reproduced in Linux/Mac.
188191
> So, try to find a working solution and send PR before open an issue.
189192
190193
Otherwise, you can follow [this gist](https://gist.github.com/etiennejeanneaurevolve/1ed387dc73c5d4cb53ab313049587d09):
@@ -204,7 +207,7 @@ E.g. `C:\Users\USERNAME\AppData\Local\Programs\Python\Python39\Lib\site-packages
204207

205208
### 2. Install the pre-commit hook globally
206209

207-
> Note: not needed if you use the Docker image
210+
> **Note**: not needed if you use the Docker image
208211
209212
```bash
210213
DIR=~/.git-template
@@ -238,7 +241,7 @@ pre-commit run -a
238241

239242
Or, using Docker ([available tags](https://github.com/antonbabenko/pre-commit-terraform/pkgs/container/pre-commit-terraform/versions)):
240243

241-
> Note: This command uses your user id and group id for the docker container to use to access the local files. If the files are owned by another user, update the `USERID` environment variable. See [File Permissions section](#docker-usage-file-permissions) for more information.
244+
> **Note**: This command uses your user id and group id for the docker container to use to access the local files. If the files are owned by another user, update the `USERID` environment variable. See [File Permissions section](#docker-usage-file-permissions) for more information.
242245
243246
```bash
244247
TAG=latest
@@ -686,7 +689,7 @@ To replicate functionality in `terraform_docs` hook:
686689
- --hook-config=--retry-once-with-cleanup=true # Boolean. true or false
687690
```
688691

689-
> Note: The flag requires additional dependency to be installed: `jq`.
692+
> **Note**: The flag requires additional dependency to be installed: `jq`.
690693

691694
If `--retry-once-with-cleanup=true`, then in each failed directory the cached modules and providers from the `.terraform` directory will be deleted, before retrying once more. To avoid unnecessary deletion of this directory, the cleanup and retry will only happen if Terraform produces any of the following error messages:
692695

@@ -696,7 +699,7 @@ To replicate functionality in `terraform_docs` hook:
696699
* "Module not installed"
697700
* "Could not load plugin"
698701

699-
**Warning:** When using `--retry-once-with-cleanup=true`, problematic `.terraform/modules/` and `.terraform/providers/` directories will be recursively deleted without prompting for consent. Other files and directories will not be affected, such as the `.terraform/environment` file.
702+
**Warning**: When using `--retry-once-with-cleanup=true`, problematic `.terraform/modules/` and `.terraform/providers/` directories will be recursively deleted without prompting for consent. Other files and directories will not be affected, such as the `.terraform/environment` file.
700703

701704
**Option 2**
702705

@@ -714,7 +717,7 @@ To replicate functionality in `terraform_docs` hook:
714717

715718
`terraform_validate` hook will try to reinitialize them before running the `terraform validate` command.
716719

717-
**Warning:** If you use Terraform workspaces, DO NOT use this option ([details](https://github.com/antonbabenko/pre-commit-terraform/issues/203#issuecomment-918791847)). Consider the first option, or wait for [`force-init`](https://github.com/antonbabenko/pre-commit-terraform/issues/224) option implementation.
720+
**Warning**: If you use Terraform workspaces, DO NOT use this option ([details](https://github.com/antonbabenko/pre-commit-terraform/issues/203#issuecomment-918791847)). Consider the first option, or wait for [`force-init`](https://github.com/antonbabenko/pre-commit-terraform/issues/224) option implementation.
718721

719722
4. `terraform_validate` in a repo with Terraform module, written using Terraform 0.15+ and which uses provider `configuration_aliases` ([Provider Aliases Within Modules](https://www.terraform.io/language/modules/develop/providers#provider-aliases-within-modules)), errors out.
720723

0 commit comments

Comments
 (0)