Skip to content

Fix race condition #384

Fix race condition

Fix race condition #384

Workflow file for this run

# Publish flant/shell-operator-dev image to hub.docker.com and ghcr.io.
# Start when PR is labeled with 'publish/image/dev' or 'publish/image/dev/amd64'.
# Label 'publish/image/dev/amd64' publishes image only for amd64 arhitecture.
# Label 'publish/image/dev' publishes a multi-arch image, it is a long-lasting operation (~1h).
name: Publish dev image
on:
pull_request:
types: [labeled]
env:
QEMU_PLATFORMS: arm64,arm
BUILDX_PLATFORMS: "linux/amd64,linux/arm64,linux/arm/v7"
BUILDX_PLATFORMS_AMD64: "linux/amd64"
GHCR_IO_REPO: ghcr.io/flant/shell-operator-dev
jobs:
check:
name: Check and remove label
runs-on: ubuntu-latest
outputs:
run_publish: ${{ steps.check.outputs.run_publish }}
build_multi_arch: ${{ steps.check.outputs.build_multi_arch }}
steps:
- uses: actions/github-script@v6
id: check
with:
script: |
const PUBLISH_DEV_LABEL = 'publish/image/dev';
const PUBLISH_AMD64_LABEL = 'publish/image/dev/amd64';
const labelName = context.payload.label.name;
let runPublish = false;
let buildMultiArch = false;
if (labelName === PUBLISH_DEV_LABEL) {
runPublish = true;
buildMultiArch = true;
}
if (labelName === PUBLISH_AMD64_LABEL) {
runPublish = true;
}
if (!runPublish) {
return console.log(`Not a 'publish' label: '${labelName}'. Skip 'publish dev image'.`);
}
if (buildMultiArch) {
console.log(`Detect 'publish' label '${labelName}'. Remove label and run 'publish dev image' for all architectures.`);
} else {
console.log(`Detect 'publish' label '${labelName}'. Remove label and run 'publish dev image' for amd64 arch only.`);
}
core.setOutput('run_publish', 'true');
core.setOutput('build_multi_arch', buildMultiArch.toString());
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
name: labelName,
});
} catch (e) {
console.log(`Error occurred while remove label. Possibly label is already removed. Ignore '${typeof e}' error.`);
}
publish_dev_image:
name: Build and publish
runs-on: ubuntu-latest
needs:
- check
if: needs.check.outputs.run_publish == 'true'
steps:
- uses: actions/checkout@v4
- name: Prepare environment
env:
BUILD_MULTI_ARCH: ${{ needs.check.outputs.build_multi_arch }}
run: |
: Image name and version for dev image
# Example: dev-feat_branch-371e2d3b-2020.02.06_18:37:42
APP_VERSION=dev-${GITHUB_REF#refs/heads/}-${GITHUB_SHA::8}-$(date +'%Y.%m.%d_%H:%M:%S')
GHCR_IO_IMAGE_NAME="${GHCR_IO_REPO}:pr${{ github.event.pull_request.number }}"
echo "APP_VERSION=${APP_VERSION}" >> ${GITHUB_ENV}
echo "GHCR_IO_IMAGE_NAME=${GHCR_IO_IMAGE_NAME}" >> ${GITHUB_ENV}
echo "========================================="
echo "APP_VERSION = $APP_VERSION"
echo "GHCR_IO_IMAGE_NAME = $GHCR_IO_IMAGE_NAME"
echo "========================================="
if [[ ${BUILD_MULTI_ARCH} == "false" ]] ; then
echo "BUILDX_PLATFORMS=${BUILDX_PLATFORMS_AMD64}" >> ${GITHUB_ENV}
fi
echo "BUILD_MULTI_ARCH = ${BUILD_MULTI_ARCH}"
echo "BUILDX_PLATFORMS = ${BUILDX_PLATFORMS}"
echo "========================================="
- name: Set up QEMU
if: needs.check.outputs.build_multi_arch == 'true'
uses: docker/[email protected]
with:
platforms: "${{ env.QEMU_PLATFORMS }}"
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
with:
version: latest
- name: Login to Github Container Registry
uses: docker/[email protected]
with:
registry: ghcr.io
username: ${{ secrets.GHCR_IO_USER }}
password: ${{ secrets.GHCR_IO_PASS }}
- name: Build and push using buildx
run: |
echo "Build ${GHCR_IO_IMAGE_NAME} with version '${APP_VERSION}'"
docker buildx build \
--platform $BUILDX_PLATFORMS \
--build-arg appVersion=$APP_VERSION \
--tag $GHCR_IO_IMAGE_NAME \
--push .
- name: Inspect binaries
if: needs.check.outputs.build_multi_arch == 'true'
run: |
# Image for one arhitecture has digest in config field.
# Image with multiple manifests has digest in each manifest.
manifests=$(docker buildx imagetools inspect "${GHCR_IO_IMAGE_NAME}" --raw)
if grep manifests <<<"${manifests}" 2>&1 >/dev/null ; then
jq -r '.manifests[]? | .digest + " " + .platform.os + "/" + .platform.architecture' <<<"${manifests}" \
| while read digest platform ; do
image=${GHCR_IO_IMAGE_NAME}@${digest}
if [[ ${BUILDX_PLATFORMS} != *"${platform}"* ]] ; then
echo "====================================="
echo "Ignore image for non-runnable platform ${platform}"
echo " ${image}"
echo "====================================="
continue
fi
echo "====================================="
echo "Inspect image for platform ${platform}"
echo " ${image}"
echo "====================================="
docker run --rm --platform ${platform} --entrypoint sh ${image} -c \
'apk add file > /dev/null; file /bin/kubectl; file /bin/busybox; file /shell-operator'
done
else
echo Not a multi-arhitecture image.
#echo $(echo -n "${manifests}" | openssl dgst -sha256) ' linux/amd64'
fi