Skip to content

Scheduled

Scheduled #5525

Workflow file for this run

name: Scheduled
on:
schedule:
- cron: '45 * * * *'
workflow_dispatch:
concurrency:
group: "scheduled"
cancel-in-progress: true
jobs:
check:
runs-on: ubuntu-latest
outputs:
configs: ${{ steps.repo_check.outputs.configs }}
platforms: ${{ steps.repo_check.outputs.platforms }}
steps:
- uses: actions/checkout@v3
- uses: mikefarah/yq@v4.35.1
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ vars.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- id: repo_check
run: |
# This script checks the source github repository for the latest commit hash and checks if the tag exists in the target dockerhub repository.
# If the tag does not exist in dockerhub, we add the config to an array for the deploy job to build and push.
CONFIGS="configs=["
PLATFORMS="platforms=["
# iterate over all images in config file
while IFS=$'\t' read -r INDEX SOURCE_REPOSITORY SOURCE_REF TARGET_REPOSITORY TARGET_TAG; do
CLIENT="${TARGET_REPOSITORY#*/}"
echo "========================================"
echo "Checking config index: $INDEX"
echo "Source repository: $SOURCE_REPOSITORY"
echo "Source ref: $SOURCE_REF"
echo "Client: $CLIENT"
# fetch latest commit hash for image
set -e
RESPONSE=$(curl -s -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/${SOURCE_REPOSITORY}/commits/${SOURCE_REF}\?per_page\=1)
set +e
STATUS=$?
# if we got a response, extract the commit hash
if [ $STATUS -eq 0 ]; then
COMMIT_HASH="$(jq -r '.sha' <<< "$RESPONSE" | cut -c1-7)"
else
echo "Failed to fetch commit hash for ${SOURCE_REPOSITORY}#${SOURCE_REF}"
echo "Response: $RESPONSE"
echo "Status: $STATUS"
exit 1
fi
# catch empty commit hash from jq extraction
if [ -z "$COMMIT_HASH" ]; then
echo "Response: $RESPONSE"
echo "Status: $STATUS"
echo "Failed to fetch commit hash for ${SOURCE_REPOSITORY}#${SOURCE_REF}"
exit 1
fi
if [ "$COMMIT_HASH" = "null" ]; then
echo "Response: $RESPONSE"
echo "Status: $STATUS"
echo "Got null commit hash for ${SOURCE_REPOSITORY}#${SOURCE_REF}"
exit 1
fi
# generate image tag
IMAGE_TAG=${TARGET_TAG}-${COMMIT_HASH}
IMAGE=${TARGET_REPOSITORY}:${IMAGE_TAG}
# check if image exists
docker image pull $IMAGE >/dev/null 2>&1
docker image inspect $IMAGE >/dev/null 2>&1
STATUS=$?
# if image exists, we don't need to build and push it
if [ $STATUS -eq 0 ]; then
echo "Image $IMAGE already exists"
continue
fi
if [ "$(yq -r ".[${INDEX}]" config.yaml)" = "null" ]; then
echo "config data at index ${INDEX} is null"
exit 1
fi
# Extract the platforms for the specified client
platforms=$(yq e ".$CLIENT[]" platforms.yaml)
platformsOutput=""
for platform in $platforms; do
slug=$(echo "$platform" | tr '/' '-')
runner=$(yq e ".\"$platform\"" runners.yaml)
CONFIGS="${CONFIGS}$(yq -r -o=json ".[${INDEX}]" config.yaml | jq --arg plat "$platform" --arg run "$runner" --arg slg "$slug" '. + {"platform": $plat, "runner": $run, "slug": $slg}'),"
platformsOutput+="$platform,"
done
platformsOutput="${platformsOutput%,}"
PLATFORMS="${PLATFORMS}$(yq -r -o=json ".[${INDEX}]" config.yaml | jq --arg platforms "$platformsOutput" '. + {"platforms": $platforms}'),"
done < <(yq -r 'to_entries | map_values({"value":.value, "index":.key}) | .[] | [.index, .value.source.repository, .value.source.ref, .value.target.repository, .value.target.tag] | @tsv' config.yaml)
# check if last character is a comma and remove it
[[ $CONFIGS == *, ]] &&
CONFIGS="${CONFIGS%?}"
[[ $PLATFORMS == *, ]] &&
PLATFORMS="${PLATFORMS%?}"
# close json array
CONFIGS="${CONFIGS}]"
PLATFORMS="${PLATFORMS}]"
echo "CONFIGS: $CONFIGS"
echo "PLATFORMS: $PLATFORMS"
echo $CONFIGS >> $GITHUB_OUTPUT
echo $PLATFORMS >> $GITHUB_OUTPUT
deploy:
needs: check
if: ${{ needs.check.outputs.configs != '[]' && needs.check.outputs.configs != '' }}
strategy:
fail-fast: false
matrix:
config: ${{fromJson(needs.check.outputs.configs)}}
runs-on: ${{ matrix.config.runner }}
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/install-deps
with:
repository: ${{ matrix.config.source.repository }}
- uses: ./.github/actions/deploy
with:
source_repository: ${{ matrix.config.source.repository }}
source_ref: ${{ matrix.config.source.ref }}
build_script: ${{ matrix.config.build_script }}
target_tag: ${{ matrix.config.target.tag }}-${{ matrix.config.slug }}
target_repository: ${{ matrix.config.target.repository }}
target_dockerfile: ${{ matrix.config.target.dockerfile }}
platform: ${{ matrix.config.platform }}
DOCKER_USERNAME: "${{ vars.DOCKER_USERNAME }}"
DOCKER_PASSWORD: "${{ secrets.DOCKER_PASSWORD }}"
MACOS_PASSWORD: "${{ secrets.MACOS_PASSWORD }}"
manifest:
needs:
- check
- deploy
runs-on: ubuntu-latest
if: ${{ !cancelled() && needs.check.outputs.platforms != '[]' && needs.check.outputs.platforms != '' }}
strategy:
fail-fast: false
matrix:
platforms: ${{fromJson(needs.check.outputs.platforms)}}
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/manifest
with:
source_repository: ${{ matrix.platforms.source.repository }}
source_ref: ${{ matrix.platforms.source.ref }}
target_tag: ${{ matrix.platforms.target.tag }}
target_repository: ${{ matrix.platforms.target.repository }}
platforms: ${{ matrix.platforms.platforms }}
DOCKER_USERNAME: "${{ vars.DOCKER_USERNAME }}"
DOCKER_PASSWORD: "${{ secrets.DOCKER_PASSWORD }}"
notify:
name: Discord Notification
runs-on: ubuntu-latest
needs:
- check
- deploy
- manifest
if: cancelled() || failure()
steps:
- name: Notify
uses: nobrayner/discord-webhook@v1
with:
github-token: ${{ secrets.github_token }}
discord-webhook: ${{ secrets.DISCORD_WEBHOOK }}