From af75cab40a461ea6f9ace3d8accda4da9fe6c130 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 23 May 2024 21:27:55 +1200 Subject: [PATCH] Implement build-and-test Github Actions CI using AWS spot instances --- .github/workflows/build-and-test-x86_64.yml | 11 ++ .github/workflows/build-and-test.yml | 145 ++++++++++++++++++++ scripts/github-actions-build.sh | 13 ++ scripts/github-actions-test.sh | 13 ++ 4 files changed, 182 insertions(+) create mode 100644 .github/workflows/build-and-test-x86_64.yml create mode 100644 .github/workflows/build-and-test.yml create mode 100755 scripts/github-actions-build.sh create mode 100755 scripts/github-actions-test.sh diff --git a/.github/workflows/build-and-test-x86_64.yml b/.github/workflows/build-and-test-x86_64.yml new file mode 100644 index 00000000000..569eb43672f --- /dev/null +++ b/.github/workflows/build-and-test-x86_64.yml @@ -0,0 +1,11 @@ +name: Build And Test (x86-64) + +on: [push, pull_request] + +jobs: + build-and-test-x86-64: + uses: ./.github/workflows/build-and-test.yml + with: + architecture: x86_64 + instance_type: c5.9xlarge + secrets: inherit diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 00000000000..ede21622b0f --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,145 @@ +name: Build And Test + +# Based on +# https://blog.devgenius.io/create-register-and-terminate-ec2-spot-instances-via-github-actions-aef473b8a00f + +on: + workflow_call: + inputs: + architecture: + required: true + type: string + instance_type: + required: true + type: string + secrets: + ACTIONS_TOKEN: + required: true + +env: + EC2_SECURITY_GROUP_ID: sg-072c6deccd49e89c8 # rr-testing + AWS_ROLE_ARN: arn:aws:iam::019859450731:role/SpotInstanceManager + AWS_REGION: us-east-2 + RUNNER_VERSION: "2.316.1" + +jobs: + start-runner: + name: Start Runner + permissions: write-all + runs-on: ubuntu-latest + outputs: + EC2_HOST: ${{ env.EC2_HOST }} + EC2_INSTANCE_ID: ${{ env.EC2_INSTANCE_ID }} + steps: + - name: "Run :: Configure AWS credentials" + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.AWS_ROLE_ARN }} + role-session-name: pipeline-assume-role-session + aws-region: ${{ env.AWS_REGION }} + + - name: "Run :: Create and register AWS spot instance" + run: |2- + # Get GitHub Actions runner registration token + response=$(curl -s -X POST -H 'Accept: application/vnd.github+json' -H 'Authorization: Bearer ${{ secrets.ACTIONS_TOKEN }}' -H 'X-GitHub-Api-Version: 2022-11-28' https://api.github.com/orgs/rr-debugger/actions/runners/registration-token) + RUNNER_REG_TOKEN=$(echo "$response" | jq -r .token) + + if [ $RUNNER_REG_TOKEN != "null" ]; then + USER_DATA="#!/bin/bash + + # Make sure the VM doesn't run for more than an hour + shutdown +60 + + apt-get update -y + apt-get dist-upgrade -f -y + + # Install GitHub Actions runner + mkdir /home/ubuntu/actions-runner && cd /home/ubuntu/actions-runner + curl -o actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz -L https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz + echo \"Github Runner Installed\" + # Extract the installer + tar xzf ./actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz + echo \"Github Runner Installer Extracted\" + + # Run GitHub Actions runner configuration + yes '' | ./config.sh --url https://github.com/${GITHUB_REPOSITORY} --token $RUNNER_REG_TOKEN --labels ${{ inputs.architecture }}_${{github.sha}} + echo \"Github Runner Configured\" + + # Run GitHub Actions runner + yes '' | ./run.sh + echo \"Github Runner UP!\" + " + + IMAGE_ID=$(aws ec2 describe-images --owners 099720109477 --filters 'Name=architecture,Values=${{ inputs.architecture }}' 'Name=name,Values=ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-*' | jq --raw-output .Images[0].ImageId) + echo "IMAGE_ID :: $IMAGE_ID" + + ENCODED_USER_DATA=$(echo -n "$USER_DATA" | sed 's/^[[:space:]]*//' | base64 -w 0) + echo "ENCODED_USER_DATA :: $ENCODED_USER_DATA" + + INSTANCE_ID=$(aws ec2 run-instances --image-id $IMAGE_ID --instance-type ${{ inputs.instance_type }} --user-data $ENCODED_USER_DATA --security-group-ids ${{ env.EC2_SECURITY_GROUP_ID }} --instance-market-options MarketType=spot --instance-initiated-shutdown-behavior terminate --query 'Instances[0].InstanceId' --output text) + echo "INSTANCE_ID :: $INSTANCE_ID" + + aws ec2 wait instances-running --instance_ids $INSTANCE_ID + HOSTNAME=$(aws ec2 describe-instances --instance-ids $INSTANCE_ID --query 'Reservations[0].Instances[0].PublicDnsName' --output text) + echo "HOSTNAME :: $HOSTNAME" + + echo "EC2_HOST=$HOSTNAME" >> $GITHUB_ENV + echo "EC2_INSTANCE_ID=$INSTANCE_ID" >> $GITHUB_ENV + else + echo "$response" + exit 1 + fi + + build-and-test: + name: Build And Test + permissions: + contents: read + runs-on: + labels: ${{ inputs.architecture }}_${{github.sha}} + needs: + - start-runner + steps: + - name: Start + run: |2- + echo " Starting GitHub Action!" && + echo "STEPS_CAN_PROCEED=true" >> $GITHUB_ENV + + - name: "Run :: Checkout repository" + uses: actions/checkout@v2 + + - name: "Run :: Build" + run: ./scripts/github-actions-build.sh + + - name: "Run :: Test" + run: ./scripts/github-actions-test.sh + + stop-runner: + name: Stop Runner + permissions: write-all + runs-on: ubuntu-latest + needs: + - start-runner + - build-and-test + if: ${{ always() }} + steps: + - name: "Run :: Configure AWS credentials" + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.AWS_ROLE_ARN }} + role-session-name: pipeline-assume-role-session + aws-region: ${{ env.AWS_REGION }} + + - name: "Run :: Terminate and unregister AWS spot instance" + run: |2- + aws ec2 terminate-instances --instance-ids ${{ needs.start-runner.outputs.EC2_INSTANCE_ID }} + gh_runner_label=${{ needs.start-runner.outputs.EC2_RUNNER }} + response=$(curl -X GET https://api.github.com/orgs/rr-debugger/actions/runners -H 'Authorization: Bearer ${{ secrets.ACTIONS_TOKEN }}' + ) + offline_runners=$(echo "$response" | jq '.runners | map(select((.labels? | any(.name == "${{ inputs.architecture }}_${{github.sha}}"))))') + echo "Offline Runners :: $offline_runners" + + echo "Attempting to remove offline runners..." + for runner in $(echo "$offline_runners" | jq -r '.[].id'); do + echo "Triggering action for runner ID: $runner" + curl -X DELETE https://api.github.com/orgs/rr-debugger/actions/runners/$runner -H 'Authorization: Bearer ${{ secrets.ACTIONS_TOKEN }}' + done diff --git a/scripts/github-actions-build.sh b/scripts/github-actions-build.sh new file mode 100755 index 00000000000..118201ceb81 --- /dev/null +++ b/scripts/github-actions-build.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set +x # echo commands +set -e # default to exiting on error" + +uname -a + +sudo apt-get install -y rpm ccache cmake g++ pkg-config zlib1g-dev git python-dev-is-python3 libacl1-dev ninja-build manpages-dev capnproto libcapnp-dev gdb lldb python3-pexpect + +mkdir obj +cd obj +cmake -G Ninja -DCMAKE_BUILD_TYPE=DEBUG -Dstaticlibs=FALSE .. +ninja diff --git a/scripts/github-actions-test.sh b/scripts/github-actions-test.sh new file mode 100755 index 00000000000..5e480b3e02a --- /dev/null +++ b/scripts/github-actions-test.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set +x # echo commands +set -e # default to exiting on error" + +# Enable perf events for rr +echo 0 | sudo tee /proc/sys/kernel/perf_event_paranoid +# Enable ptrace-attach to any process. This lets us get more data when tests fail. +echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope +# Disable AppArmor restrictions on user namespaces, which our tests need to use +(echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns) || true +let halfproc=`nproc`/2 +ctest -j$halfproc --verbose