Merge pull request #713 from kristof-mattei/renovate/lock-file-mainte… #702
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Retag containers after new push / PR | |
env: | |
# set this to true in GitHub variables to enable building the container | |
# HAS_CONTAINER: true | |
# Use docker.io for Docker Hub if empty | |
REGISTRY: ghcr.io | |
# github.repository as <account>/<repo> | |
IMAGE_NAME: ${{ github.repository }} | |
concurrency: | |
group: "${{ github.workflow }}" # last one must win | |
cancel-in-progress: false # no we need them | |
on: | |
# Triggers the workflow pushes to main. They can be either direct pushes, or PRs being merged | |
push: | |
branches: [main] | |
# note how we're not doing | |
# pull_request_target, as it isn't what we need. | |
# we need the push event to make it show up nicely in the UI | |
# this however brings a whole new slew of problems, like how do we identify the | |
# incoming PR's artifacts? | |
# well, we set a tag on that PR's artifact, in the form of | |
# pr-{head_of_pr}-{pr_head_of_main} | |
# when with git rev-parse HEAD^2 we can find the incoming PR's head | |
# Problem solved | |
permissions: | |
contents: write | |
packages: write | |
jobs: | |
repo-has-container: | |
name: Repo has container? | |
runs-on: ubuntu-latest | |
outputs: | |
has_container: ${{ steps.determine.outputs.has_container }} | |
steps: | |
- name: Repo has docker container? | |
id: determine | |
shell: bash | |
run: | | |
HAS_CONTAINER="${{ vars.HAS_CONTAINER }}" | |
echo "has_container=${HAS_CONTAINER:-false}" >> ${GITHUB_OUTPUT} | |
retag-containers: | |
name: Retag the containers | |
runs-on: ubuntu-latest | |
needs: | |
- repo-has-container | |
if: | | |
fromJSON(needs.repo-has-container.outputs.has_container) == true | |
steps: | |
- name: Checkout | |
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 | |
with: | |
show-progress: false | |
fetch-depth: 2 | |
- name: Find out if current commit is a merge | |
shell: bash | |
run: | | |
EXIT_CODE=0 | |
# a commit always has a parent, but if it has 2, the commit is a merge | |
# so lets see if we have one | |
# since we're listening to the push event we have to do this manually | |
PARENT2=$(git rev-parse "HEAD^2" --quiet 2>/dev/null) || EXIT_CODE=$? | |
if [ ${EXIT_CODE} -eq 0 ] | |
then | |
echo "The head of the incoming PR is ${PARENT2}" | |
echo "INCOMING_PR_HEAD_COMMIT=${PARENT2}" >> ${GITHUB_ENV} | |
else | |
echo "The incoming push isn't a merge, ergo it's not a PR" | |
fi | |
- name: Setup Node.js | |
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 | |
with: | |
node-version-file: ".nvmrc" | |
cache: "npm" | |
cache-dependency-path: "**/package-lock.json" | |
- name: Install dependencies | |
shell: bash | |
run: | | |
npm ci --ignore-scripts | |
- name: Download crane tar, extract, and add folder to path. | |
uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 | |
with: | |
script: | | |
const tc = require("@actions/tool-cache"); | |
const release = await github.rest.repos.getLatestRelease({ | |
owner: "google", | |
repo: "go-containerregistry" | |
}); | |
const asset = release.data.assets.find(asset => { | |
return asset["content_type"] === "application/gzip" && asset.name === "go-containerregistry_Linux_x86_64.tar.gz"; | |
}); | |
const urlToCraneTar = asset.browser_download_url | |
const craneTarPath = await tc.downloadTool(urlToCraneTar); | |
const craneExtractedFolder = await tc.extractTar(craneTarPath, null, ["--extract", "--gzip"]); | |
core.addPath(craneExtractedFolder); | |
- name: Log into registry ${{ env.REGISTRY }} | |
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 | |
with: | |
registry: ${{ env.REGISTRY }} | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Set full image name | |
shell: bash | |
run: | | |
echo "FULL_IMAGE_NAME=${REGISTRY,,}/${IMAGE_NAME,,}" >> ${GITHUB_ENV} | |
- name: Find all tags for ${{ env.FULL_IMAGE_NAME }} | |
shell: bash | |
run: | | |
crane ls ${FULL_IMAGE_NAME} >> existing_tags | |
echo "These are the existing tags on ${FULL_IMAGE_NAME}:" | |
cat existing_tags | |
- name: Check if the incoming PR has a Docker container, which will be our old tag, if not, or if it's just a push, find the appropriate old tag | |
env: | |
PR_TAG: "pr-${{ github.event.before }}-${{ env.INCOMING_PR_HEAD_COMMIT }}" | |
shell: bash | |
run: | | |
# search for the tag, there can only be zero or one match | |
# we need the || true because otherwise grep returns exit code 1 and github actions then dies | |
pr_tag_found=$(cat existing_tags | grep -c "^${PR_TAG}\$") || true | |
if [ $pr_tag_found -eq 1 ] | |
then | |
echo "Incoming PR produced a Docker image" | |
echo "OLD_TAG=${PR_TAG}" >> ${GITHUB_ENV} | |
echo "SUFFIX=actual" >> ${GITHUB_ENV} | |
else | |
# If we don't have an old tag, then the incoming PR didn't produce a container. | |
# In which case we're going to find the container referenced to the base commit, and add our current sha as a tag to it | |
echo "Incoming PR produced nothing, or there was just a push to main" | |
# so we find the last commit that github processed before this one | |
# which will have gone through the same retagging process | |
# and use that sha as our key to find the Docker container related to that commit | |
old_tag=$(cat existing_tags | grep "^sha-${{ github.event.before }}-.*\$") # .* is actual or retag | |
echo "OLD_TAG=${old_tag}" >> ${GITHUB_ENV} | |
echo "SUFFIX=retag" >> ${GITHUB_ENV} | |
fi | |
- name: Set the new TAGs | |
id: meta | |
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0 | |
with: | |
images: "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}" | |
flavor: | | |
latest=false | |
tags: | | |
type=edge,branch=main | |
type=sha,format=long,prefix=sha-,suffix=-${{ env.SUFFIX }} | |
- name: Actually re-tag the container | |
shell: bash | |
run: | | |
echo "${{ steps.meta.outputs.tags }}" | while read new_tag | |
do | |
crane cp "${FULL_IMAGE_NAME}:${OLD_TAG}" ${new_tag} | |
done |