Automated Builder #525
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: "Automated Builder" | |
on: | |
workflow_dispatch: | |
inputs: | |
binary_version: | |
description: "Specify the version" | |
required: true | |
repository_name: | |
description: "Specify the repository" | |
required: true | |
repository_org: | |
description: "Specify the organization" | |
required: true | |
repository_dispatch: | |
types: | |
- webhook | |
env: | |
DEPOT_BINARY_VERSION: "${{ inputs.binary_version }}" | |
DEPOT_REPOSITORY_ORG: "${{ inputs.repository_org }}" | |
DEPOT_REPOSITORY_NAME: "${{ inputs.repository_name }}" | |
DEPOT_BUCKET_NAME: "depot" | |
DEPOT_BUCKET_PUBLIC_URL: "https://depot.r2.restake.cloud" | |
SLACK_BOT_TOKEN: "${{ secrets.SLACK_BOT_TOKEN }}" | |
SLACK_CHANNEL_ID: "C06QF8AKYMV" | |
jobs: | |
outputs: | |
name: "Outputs" | |
runs-on: "ubuntu-latest" | |
outputs: | |
depot_binaries: "${{ steps.set-outputs.outputs.depot_binaries }}" | |
depot_binary_build_name: "${{ steps.set-outputs.outputs.depot_binary_build_name }}" | |
depot_purpose: "${{ steps.set-outputs.outputs.depot_purpose }}" | |
depot_project_name: "${{ steps.set-outputs.outputs.depot_project_name }}" | |
depot_automatic_builds: "${{ steps.set-outputs.outputs.depot_automatic_builds }}" | |
depot_run_docker_build: "${{ steps.set-outputs.outputs.depot_run_docker_build }}" | |
depot_docker_binaries: "${{ steps.set-outputs.outputs.depot_docker_binaries }}" | |
depot_patches: "${{ steps.set-outputs.outputs.depot_patches }}" | |
depot_run_build: "${{ steps.set-outputs.outputs.depot_run_build }}" | |
depot_builder: "${{ steps.set-outputs.outputs.depot_builder }}" | |
depot_builder_version: "${{ steps.set-outputs.outputs.depot_builder_version }}" | |
depot_cpu: "${{ steps.set-outputs.outputs.depot_cpu }}" | |
steps: | |
- id: "checkout" | |
name: "Checkout code" | |
uses: actions/checkout@v4 | |
- id: "setup-deno" | |
name: "Set up Deno" | |
uses: denoland/setup-deno@v1 | |
with: | |
deno-version: 1.41.0 | |
- id: "setup-envvars" | |
name: "Set up environment variables" | |
run: deno run --allow-write --allow-env --allow-read ./utils/env.ts | |
- id: "set-outputs" | |
name: "Set outputs to use in other jobs" | |
run: | | |
echo "depot_automatic_builds=${{ env.DEPOT_AUTOMATIC_BUILDS }}" >> $GITHUB_OUTPUT | |
echo "depot_run_docker_build=${{ env.DEPOT_RUN_DOCKER_BUILD }}" >> $GITHUB_OUTPUT | |
echo "depot_purpose=${{ env.DEPOT_PURPOSE }}" >> $GITHUB_OUTPUT | |
echo "depot_project_name=${{ env.DEPOT_PROJECT_NAME }}" >> $GITHUB_OUTPUT | |
echo "depot_docker_binaries=${{ env.DEPOT_DOCKER_BINARIES }}" >> $GITHUB_OUTPUT | |
echo "depot_patches=${{ env.DEPOT_PATCHES }}" >> $GITHUB_OUTPUT | |
echo "depot_run_build=${{ env.DEPOT_RUN_BUILD }}" >> $GITHUB_OUTPUT | |
echo "depot_builder=${{ env.DEPOT_BUILDER }}" >> $GITHUB_OUTPUT | |
echo "depot_builder_version=${{ env.DEPOT_BUILDER_VERSION }}" >> $GITHUB_OUTPUT | |
echo "depot_cpu=${{ env.DEPOT_CPU }}" >> $GITHUB_OUTPUT | |
printf "depot_binaries=%s\n" "${DEPOT_BINARIES//$'\n'/\\n}" >> $GITHUB_OUTPUT | |
printf "depot_binary_build_name=%s\n" "${DEPOT_BINARY_BUILD_NAME//$'\n'/\\n}" >> $GITHUB_OUTPUT | |
build: | |
name: "Build" | |
runs-on: "ubuntu-latest-l" | |
needs: ["outputs"] | |
if: ${{ needs.outputs.outputs.depot_run_build == 'true' }} | |
steps: | |
- id: "checkout" | |
name: "Checkout code" | |
uses: actions/checkout@v4 | |
- id: "setup-deno" | |
name: "Set up Deno" | |
uses: denoland/setup-deno@v1 | |
with: | |
deno-version: 1.41.0 | |
- id: "set-builder-env" | |
name: "Set environment variables for build" | |
run: | | |
echo "DEPOT_BUILDER=${{ needs.outputs.outputs.depot_builder }}" >> "${GITHUB_ENV}" | |
echo "DEPOT_BUILDER_VERSION=${{ needs.outputs.outputs.depot_builder_version }}" >> "${GITHUB_ENV}" | |
echo "DEPOT_CPU=${{ needs.outputs.outputs.depot_cpu }}" >> "${GITHUB_ENV}" | |
echo "DEPOT_PROJECT_NAME=${{ needs.outputs.outputs.depot_project_name }}" >> "${GITHUB_ENV}" | |
echo "DEPOT_BINARY_BUILD_NAME=${{ needs.outputs.outputs.depot_binary_build_name }}" >> "${GITHUB_ENV}" | |
- id: "setup-builder-packages" | |
name: "Install builder packages" | |
run: bash ./builders/${{ env.DEPOT_BUILDER }}/deps.sh | |
- id: "cache-tooling" | |
name: "Cache tooling" | |
uses: "actions/cache@v4" | |
if: "${{ steps.setup-builder-packages.outputs.cached-tooling-key != '' }}" | |
with: | |
path: "${{ steps.setup-builder-packages.outputs.cached-tooling-path }}" | |
key: "${{ steps.setup-builder-packages.outputs.cached-tooling-key }}" | |
- id: "setup-builder" | |
name: "Setup builder" | |
run: bash ./builders/${{ env.DEPOT_BUILDER }}/setup.sh | |
- id: "clone" | |
name: "Clone protocol source" | |
uses: "actions/checkout@v4" | |
with: | |
repository: "${{ env.DEPOT_REPOSITORY_ORG }}/${{ env.DEPOT_REPOSITORY_NAME }}" | |
fetch-tags: true | |
path: "${{ env.DEPOT_PROJECT_NAME }}" | |
ref: "refs/tags/${{ env.DEPOT_BINARY_VERSION }}" | |
submodules: true | |
- id: "apply-patches" | |
name: "Apply patches" | |
if: ${{ needs.outputs.outputs.depot_patches == 'true' }} | |
run: | | |
set -euo pipefail | |
shopt -s nullglob | |
cd "${GITHUB_WORKSPACE}/${{ env.DEPOT_PROJECT_NAME }}" | |
git am --3way "${GITHUB_WORKSPACE}/patches/${{ env.DEPOT_PROJECT_NAME }}"/*.patch | |
- id: "build-binaries" | |
name: "Run protocol-specific build script" | |
run: bash "./scripts/${{ env.DEPOT_PROJECT_NAME }}/build.sh" | |
- id: "generate-checksum" | |
name: "Generate checksum file" | |
run: | | |
cd ${{ env.DEPOT_PROJECT_NAME }}/bin | |
sha256sum * > SHA256SUMS | |
- id: "upload-artifacts" | |
name: "Save binary to workspace" | |
uses: "actions/upload-artifact@v4" | |
with: | |
name: "binaries" | |
path: "${{ env.DEPOT_PROJECT_NAME }}/bin/*" | |
if-no-files-found: "error" | |
retention-days: 1 | |
upload: | |
name: "Upload" | |
needs: [ "build", "outputs" ] | |
runs-on: "ubuntu-latest" | |
if: ${{ needs.outputs.outputs.depot_automatic_builds == 'true' || github.event_name == 'workflow_dispatch' }} | |
steps: | |
- id: "checkout" | |
name: "Checkout code" | |
uses: actions/checkout@v4 | |
- id: "download-artifacts" | |
name: "Download binaries from workspace" | |
uses: "actions/download-artifact@v4" | |
with: | |
name: "binaries" | |
path: "binaries" | |
- id: "setup-rclone" | |
name: "Set up rclone CLI" | |
run: curl https://rclone.org/install.sh | sudo bash | |
- id: "setup-rclone-config" | |
name: "Set up rclone config" | |
run: printf "%s" "${{ secrets.R2_CONFIG }}" > rclone.conf | |
- id: "upload-binary" | |
name: "Upload binary to R2 bucket and verify a successful upload" | |
run: | | |
set -euo pipefail | |
for file in binaries/*; do | |
if [ -f "$file" ]; then | |
filename=$(basename "$file") | |
directory="${{ needs.outputs.outputs.depot_purpose }}/${{ needs.outputs.outputs.depot_project_name }}/${{ env.DEPOT_BINARY_VERSION }}" | |
rclone --config="rclone.conf" copy "$file" "r2:${{ env.DEPOT_BUCKET_NAME }}/${directory}" | |
status_code=$(curl -sL -w "%{http_code}\\n" "${{ env.DEPOT_BUCKET_PUBLIC_URL }}/${directory}/${filename}" -o /dev/null) | |
if [ "$status_code" -ne 200 ]; then | |
echo "Error: Binary $filename is not downloadable (HTTP status code $status_code)" | |
exit 1 | |
fi | |
fi | |
done | |
docker: | |
name: "Build and Publish Docker" | |
runs-on: "ubuntu-latest-l" | |
needs: [ "outputs", "build" ] | |
if: ${{ needs.outputs.outputs.depot_run_docker_build == 'true' && (always() && !failure() && !cancelled()) }} | |
steps: | |
- id: "checkout" | |
name: "Checkout repository" | |
uses: actions/checkout@v4 | |
- id: "download-binaries" | |
name: "Download binaries artifact" | |
if: ${{ needs.outputs.outputs.depot_run_build == 'true' }} | |
uses: actions/download-artifact@v4 | |
with: | |
name: "binaries" | |
path: "binaries" | |
- id: "set-docker-env" | |
name: "Set environment variables for Docker" | |
run: | | |
echo "DEPOT_PROJECT_NAME=${{ needs.outputs.outputs.depot_project_name }}" >> "${GITHUB_ENV}" | |
echo "DEPOT_BINARY_VERSION=${{ env.DEPOT_BINARY_VERSION }}" >> "${GITHUB_ENV}" | |
project_dockerfile="docker/${{ needs.outputs.outputs.depot_project_name }}.Dockerfile" | |
if [ -f "${project_dockerfile}" ]; then | |
echo "DEPOT_DOCKERFILE=${project_dockerfile}" >> "${GITHUB_ENV}" | |
else | |
echo DEPOT_DOCKERFILE="docker/default.Dockerfile" >> "${GITHUB_ENV}" | |
fi | |
- id: "login-ghcr" | |
name: "Log in to the Container registry" | |
uses: "docker/[email protected]" | |
with: | |
registry: "ghcr.io" | |
username: "restake-bot" | |
password: "${{ secrets.RESTAKE_BOT_TOKEN }}" | |
- id: "build-docker" | |
name: "Build and push Docker image" | |
uses: docker/build-push-action@v5 | |
with: | |
context: . | |
file: "${{ env.DEPOT_DOCKERFILE }}" | |
build-args: | | |
DEPOT_BINARY_VERSION=${{ env.DEPOT_BINARY_VERSION }} | |
DEPOT_DOCKER_BINARIES=${{ needs.outputs.outputs.depot_docker_binaries }} | |
platforms: "linux/amd64" | |
push: true | |
no-cache: true | |
tags: | | |
ghcr.io/restake/depot/${{ env.DEPOT_PROJECT_NAME }}:${{ env.DEPOT_BINARY_VERSION }} | |
notify-binary: | |
name: "Notify binary build success on Slack" | |
runs-on: "ubuntu-latest" | |
needs: ["build", "upload", "outputs"] | |
if: ${{ needs.outputs.outputs.depot_automatic_builds == 'true' && needs.build.result == 'success' || needs.upload.result == 'success' || needs.build.result != 'success' || needs.upload.result != 'success' }} | |
steps: | |
- id: "get-workflow-url" | |
name: "Get workflow URL" | |
run: | | |
workflow_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" | |
echo "WORKFLOW_URL=${workflow_url}" >> "${GITHUB_ENV}" | |
echo "DEPOT_BINARY_NAMES=${{ needs.outputs.outputs.depot_binaries }}" >> "${GITHUB_ENV}" | |
- id: "checkout" | |
name: "Checkout code" | |
uses: actions/checkout@v4 | |
- id: "slack-notify-failure" | |
name: "Notify on Slack upon failure" | |
if: "${{ needs.build.result != 'success' || needs.upload.result != 'success' }}" | |
uses: slackapi/[email protected] | |
with: | |
channel-id: "${{ env.SLACK_CHANNEL_ID }}" | |
payload-file-path: "./templates/notify-failure.json" | |
- id: "slack-notify-success" | |
name: "Notify on Slack upon success" | |
if: "${{ needs.build.result == 'success' && needs.upload.result == 'success' }}" | |
uses: slackapi/[email protected] | |
with: | |
channel-id: "${{ env.SLACK_CHANNEL_ID }}" | |
payload-file-path: "./templates/notify-success.json" | |
notify-docker: | |
name: "Notify Docker image build on Slack" | |
runs-on: "ubuntu-latest" | |
needs: ["docker", "outputs"] | |
if: ${{ needs.outputs.outputs.depot_run_docker_build == 'true' && needs.docker.result == 'success' && (always() && !failure() && !cancelled()) }} | |
outputs: | |
docker-status: "${{ needs.docker.result }}" | |
steps: | |
- id: "set-project-name" | |
name: "Set project name to envvar" | |
run: echo "DEPOT_PROJECT_NAME=${{ needs.outputs.outputs.depot_project_name }}" >> "${GITHUB_ENV}" | |
- id: "envvar-test" | |
run: | | |
echo ${{ env.DEPOT_PROJECT_NAME }} | |
echo ${{ env.DEPOT_BINARY_VERSION }} | |
- id: "checkout" | |
name: "Checkout code" | |
uses: actions/checkout@v4 | |
- id: "slack-notify-docker" | |
name: "Notify Docker image build on Slack" | |
uses: slackapi/[email protected] | |
with: | |
channel-id: "${{ env.SLACK_CHANNEL_ID }}" | |
payload-file-path: "./templates/notify-docker.json" |