Skip to content

Commit 632b54e

Browse files
authored
Merge pull request #86 from Staffbase/DIA-3549-avoid-image-rebuilding
2 parents bba0361 + 8c6f8e4 commit 632b54e

File tree

2 files changed

+84
-34
lines changed

2 files changed

+84
-34
lines changed

README.md

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
# 🚀 GitHub Action for GitOps
22

3-
This GitHub Action can be used for our GitOps workflow.
4-
The GitHub Action will build and push the Docker image for your service and deploys the new version at your Kubernetes clusters.
3+
This GitHub Action can be used for our GitOps workflow. The GitHub Action will build and push the Docker image for your service and deploys
4+
the new version at your Kubernetes clusters.
55

66
## Requirement
77

8-
When you want to use this GitHub Action your GitHub repository should have a `dev` and `master` / `main` branch and it should use tags for releases.
8+
When you want to use this GitHub Action your GitHub repository should have a `dev` and `master` / `main` branch and it should use tags for
9+
releases.
910

1011
- For the `dev` branch we will change the files specified under `gitops-dev`.
1112
- For the `master` / `main` branch we will change the files specified under `gitops-stage`.
1213
- For a new tag the files under `gitops-prod` will be used.
1314

14-
This GitOps setup should be the default for all your repositories.
15-
However, if you have a special case, you can leave `gitops-dev`, `gitops-stage` and `gitops-prod` undefined, then those steps will be skipped.
15+
This GitOps setup should be the default for all your repositories. However, if you have a special case, you can
16+
leave `gitops-dev`, `gitops-stage` and `gitops-prod` undefined, then those steps will be skipped.
1617

1718
## Usages
1819

@@ -21,7 +22,7 @@ However, if you have a special case, you can leave `gitops-dev`, `gitops-stage`
2122
```yaml
2223
name: CD
2324

24-
on: [push]
25+
on: [ push ]
2526

2627
jobs:
2728
ci-cd:
@@ -53,7 +54,7 @@ jobs:
5354
```yaml
5455
name: CD
5556

56-
on: [push]
57+
on: [ push ]
5758

5859
jobs:
5960
ci-cd:
@@ -78,7 +79,7 @@ jobs:
7879
```yaml
7980
name: CD
8081

81-
on: [push]
82+
on: [ push ]
8283

8384
jobs:
8485
ci-cd:
@@ -105,27 +106,29 @@ jobs:
105106
106107
## Inputs
107108
108-
| Name | Description | Default |
109-
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------|-----------------------------|
110-
| `docker-registry` | Docker Registry | `staffbase.jfrog.io` |
111-
| `docker-image` | Docker Image | |
112-
| `docker-username` | Username for the Docker Registry | |
113-
| `docker-password` | Password for the Docker Registry | |
114-
| `docker-file` | Dockerfile | `./Dockerfile` |
115-
| `docker-build-args` | List of build-time variables | |
116-
| `docker-build-secrets` | List of secrets to expose to the build (e.g., key=string, GIT_AUTH_TOKEN=mytoken) | |
117-
| `docker-build-secret-files` | List of secret files to expose to the build (e.g., key=filename, MY_SECRET=./secret.txt) | |
118-
| `docker-build-target` | Sets the target stage to build like: "runtime" | |
119-
| `docker-build-provenance` | Generate [provenance](https://docs.docker.com/build/attestations/slsa-provenance/) attestation for the build | `false` |
120-
| `gitops-organization` | GitHub Organization for GitOps | `Staffbase` |
121-
| `gitops-repository` | GitHub Repository for GitOps | `mops` |
122-
| `gitops-user` | GitHub User for GitOps | `Staffbot` |
123-
| `gitops-email` | GitHub Email for GitOps | `[email protected]` |
124-
| `gitops-token` | GitHub Token for GitOps | |
125-
| `gitops-dev` | Files which should be updated by the GitHub Action for DEV, must be relative to the root of the GitOps repository | |
126-
| `gitops-stage` | Files which should be updated by the GitHub Action for STAGE, must be relative to the root of the GitOps repository | |
127-
| `gitops-prod` | Files which should be updated by the GitHub Action for PROD, must be relative to the root of the GitOps repository | |
128-
| `working-directory` | The directory in which the GitOps action should be executed. The docker-file variable should be relative to working directory. | `.` |
109+
| Name | Description | Default |
110+
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------|
111+
| `docker-registry` | Docker Registry | `staffbase.jfrog.io` |
112+
| `docker-registry-api` | Docker Registry API (used for retagging without pulling) | `https://staffbase.jfrog.io/artifactory/api/docker/` |
113+
| `docker-image` | Docker Image | |
114+
| `docker-username` | Username for the Docker Registry | |
115+
| `docker-password` | Password for the Docker Registry | |
116+
| `docker-file` | Dockerfile | `./Dockerfile` |
117+
| `docker-build-args` | List of build-time variables | |
118+
| `docker-build-secrets` | List of secrets to expose to the build (e.g., key=string, GIT_AUTH_TOKEN=mytoken) | |
119+
| `docker-build-secret-files` | List of secret files to expose to the build (e.g., key=filename, MY_SECRET=./secret.txt) | |
120+
| `docker-build-target` | Sets the target stage to build like: "runtime" | |
121+
| `docker-build-provenance` | Generate [provenance](https://docs.docker.com/build/attestations/slsa-provenance/) attestation for the build | `false` |
122+
| `docker-disable-retagging` | Disables retagging of existing images and run a new build instead | `false` |
123+
| `gitops-organization` | GitHub Organization for GitOps | `Staffbase` |
124+
| `gitops-repository` | GitHub Repository for GitOps | `mops` |
125+
| `gitops-user` | GitHub User for GitOps | `Staffbot` |
126+
| `gitops-email` | GitHub Email for GitOps | `[email protected]` |
127+
| `gitops-token` | GitHub Token for GitOps | |
128+
| `gitops-dev` | Files which should be updated by the GitHub Action for DEV, must be relative to the root of the GitOps repository | |
129+
| `gitops-stage` | Files which should be updated by the GitHub Action for STAGE, must be relative to the root of the GitOps repository | |
130+
| `gitops-prod` | Files which should be updated by the GitHub Action for PROD, must be relative to the root of the GitOps repository | |
131+
| `working-directory` | The directory in which the GitOps action should be executed. The docker-file variable should be relative to working directory. | `.` |
129132

130133
## Contributing
131134

@@ -150,5 +153,4 @@ This project is licensed under the Apache-2.0 License - see the [LICENSE.md](LIC
150153

151154
## Releasing new versions
152155

153-
Go to the release overview page and publish the draft release with a new version number.
154-
Make sure to update the floating version commit.
156+
Go to the release overview page and publish the draft release with a new version number. Make sure to update the floating version commit.

action.yml

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ inputs:
77
description: 'Docker Registry'
88
required: true
99
default: 'staffbase.jfrog.io'
10+
docker-registry-api:
11+
description: 'Docker Registry API'
12+
required: false
13+
default: 'https://staffbase.jfrog.io/artifactory/api/docker/'
1014
docker-image:
1115
description: 'Docker Image'
1216
required: true
@@ -36,6 +40,10 @@ inputs:
3640
description: "Generate provenance attestation for the build"
3741
required: false
3842
default: 'false'
43+
docker-disable-retagging:
44+
description: 'Disable retagging of existing images'
45+
required: false
46+
default: 'false'
3947
gitops-organization:
4048
description: 'GitHub Organization for GitOps'
4149
required: true
@@ -81,6 +89,7 @@ runs:
8189
id: preparation
8290
shell: bash
8391
run: |
92+
BUILD="true"
8493
if [[ $GITHUB_REF == refs/heads/master ]]; then
8594
TAG="master-${GITHUB_SHA::8}"
8695
LATEST="master"
@@ -97,10 +106,12 @@ runs:
97106
TAG="${GITHUB_REF:11}"
98107
LATEST="latest"
99108
PUSH="true"
109+
BUILD="${{ inputs.docker-disable-retagging }}"
100110
elif [[ $GITHUB_REF == refs/tags/* ]]; then
101111
TAG="${GITHUB_REF:10}"
102112
LATEST="latest"
103113
PUSH="true"
114+
BUILD="${{ inputs.docker-disable-retagging }}"
104115
else
105116
TAG="${GITHUB_SHA::8}"
106117
PUSH="false"
@@ -111,10 +122,11 @@ runs:
111122
TAG_LIST+=",${{ inputs.docker-registry }}/${{ inputs.docker-image }}:${LATEST}"
112123
fi
113124
114-
echo "tag_list=$TAG_LIST" >> $GITHUB_OUTPUT
115-
echo "tag=$TAG" >> $GITHUB_OUTPUT
125+
echo "build=$BUILD" >> $GITHUB_OUTPUT
116126
echo "latest=$LATEST" >> $GITHUB_OUTPUT
117127
echo "push=$PUSH" >> $GITHUB_OUTPUT
128+
echo "tag=$TAG" >> $GITHUB_OUTPUT
129+
echo "tag_list=$TAG_LIST" >> $GITHUB_OUTPUT
118130
119131
- name: Set up Docker Buildx
120132
if: inputs.docker-username != '' && inputs.docker-password != ''
@@ -128,9 +140,10 @@ runs:
128140
username: ${{ inputs.docker-username }}
129141
password: ${{ inputs.docker-password }}
130142

143+
131144
- name: Build
132145
id: docker_build
133-
if: inputs.docker-username != '' && inputs.docker-password != ''
146+
if: steps.preparation.outputs.build == 'true' && inputs.docker-username != '' && inputs.docker-password != ''
134147
uses: docker/build-push-action@v5
135148
with:
136149
context: ${{ inputs.working-directory }}
@@ -146,6 +159,41 @@ runs:
146159
cache-to: type=gha,mode=max
147160
provenance: ${{ inputs.docker-build-provenance }}
148161

162+
- name: Retag Existing Image
163+
id: docker_retag
164+
if: steps.preparation.outputs.build == 'false'
165+
shell: bash
166+
run: |
167+
CHECK_EXISTING_TAGS="master-${GITHUB_SHA::8} main-${GITHUB_SHA::8}"
168+
CONTENT_TYPE="application/vnd.docker.distribution.manifest.v2+json"
169+
170+
# split docker-image on / into repository and image
171+
REPO=$(echo ${{ inputs.docker-image}} | cut -d'/' -f1)
172+
IMAGE=$(echo ${{ inputs.docker-image}} | cut -d'/' -f2)
173+
174+
echo "CHECK_EXISTING_TAGS: ${CHECK_EXISTING_TAGS}"
175+
echo "RELEASE_TAG: ${RELEASE_TAG:1}"
176+
echo "Check if an image already exists for ${{ inputs.docker-image }}:main|master-${GITHUB_SHA::8} 🐋 ⬇"
177+
178+
MANIFEST=""
179+
for tag in $CHECK_EXISTING_TAGS; do
180+
MANIFEST=$(curl -H "Accept: ${CONTENT_TYPE}" -u "${{ inputs.docker-username }}:${{ inputs.docker-password }}" "${{ inputs.docker-registry-api }}${REPO}/v2/{$IMAGE}/manifests/${tag}")
181+
182+
if [[ $MANIFEST == *"errors"* ]]; then
183+
echo "No image found for ${{ inputs.docker-image }}:${tag} 🚫"
184+
continue
185+
else
186+
echo "Image found for ${{ inputs.docker-image }}:${tag} 🐋 ⬇"
187+
break
188+
fi
189+
# Exit here if no existing manifest was found
190+
exit 1
191+
done
192+
193+
echo "Retagging image with release version and :latest tags for ${{ inputs.docker-image }} 🏷"
194+
curl --fail-with-body -X PUT -H "Content-Type: ${CONTENT_TYPE}" -u "${{ inputs.docker-username }}:${{ inputs.docker-password }}" -d "${MANIFEST}" "${{ inputs.docker-registry-api }}${REPO}/v2/{$IMAGE}/manifests/${{ steps.preparation.outputs.tag }}"
195+
curl --fail-with-body -X PUT -H "Content-Type: ${CONTENT_TYPE}" -u "${{ inputs.docker-username }}:${{ inputs.docker-password }}" -d "${MANIFEST}" "${{ inputs.docker-registry-api }}${REPO}/v2/{$IMAGE}/manifests/${{ steps.preparation.outputs.latest }}"
196+
149197
- name: Checkout GitOps Repository
150198
if: inputs.gitops-token != ''
151199
uses: actions/checkout@v4

0 commit comments

Comments
 (0)