Upgrade kernel on charm upgrade #283
Workflow file for this run
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: End-to-End Test | |
on: | |
pull_request: | |
jobs: | |
build-charm: | |
name: Build Charm | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v3 | |
- name: Remove Unnecessary Components | |
run: | | |
rm -rf .git | |
rm -rf .github | |
- name: Write lxd-profile.yaml | |
run: | | |
cat << EOF > ./lxd-profile.yaml | |
config: | |
security.nesting: true | |
security.privileged: true | |
raw.lxc: | | |
lxc.apparmor.profile=unconfined | |
lxc.mount.auto=proc:rw sys:rw cgroup:rw | |
lxc.cgroup.devices.allow=a | |
lxc.cap.drop= | |
devices: | |
kmsg: | |
path: /dev/kmsg | |
source: /dev/kmsg | |
type: unix-char | |
EOF | |
- name: Cache github-runner Charm | |
uses: actions/cache@v3 | |
id: cache-charm | |
with: | |
path: github-runner_ubuntu-22.04-amd64.charm | |
key: github-runner-charm-${{ hashFiles('**/*') }} | |
- name: Setup LXD | |
if: steps.cache-charm.outputs.cache-hit != 'true' | |
uses: canonical/setup-lxd@main | |
- name: Install charmcraft | |
if: steps.cache-charm.outputs.cache-hit != 'true' | |
run: sudo snap install charmcraft --classic | |
- name: Pack github-runner Charm | |
if: steps.cache-charm.outputs.cache-hit != 'true' | |
run: charmcraft pack || ( cat ~/.local/state/charmcraft/log/* && exit 1 ) | |
- name: Upload github-runner Charm | |
uses: actions/upload-artifact@v3 | |
with: | |
name: dangerous-test-only-github-runner_ubuntu-22.04-amd64.charm | |
path: github-runner_ubuntu-22.04-amd64.charm | |
run-id: | |
name: Generate Run ID | |
runs-on: ubuntu-latest | |
outputs: | |
run-id: ${{ steps.run-id.outputs.run-id }} | |
steps: | |
- name: Generate Run ID | |
id: run-id | |
run: | | |
echo "run-id=e2e-$(LC_ALL=C tr -dc 'a-z' < /dev/urandom | head -c4)" >> $GITHUB_OUTPUT | |
deploy-e2e-test-runner: | |
name: Deploy End-to-End Test Runner (${{ matrix.event.name }}) | |
runs-on: ubuntu-latest | |
needs: [build-charm, run-id] | |
strategy: | |
matrix: | |
event: | |
- name: pull_request | |
abbreviation: pr | |
- name: workflow_dispatch | |
abbreviation: wd | |
steps: | |
- name: Setup Lxd Juju Controller | |
uses: charmed-kubernetes/actions-operator@main | |
with: | |
juju-channel: 3.1/stable | |
provider: lxd | |
- name: Install GitHub Cli | |
run: which gh || sudo apt install gh -y | |
- name: Create Testing Juju Model | |
run: juju add-model testing | |
- name: Set Testing Model Proxy Configuration | |
run: | | |
juju model-config juju-http-proxy=$http_proxy | |
juju model-config juju-https-proxy=$https_proxy | |
juju model-config juju-no-proxy=$no_proxy | |
- name: Change Testing Model Logging Level | |
run: juju model-config logging-config="<root>=INFO;unit=DEBUG" | |
- name: Download github-runner Charm | |
uses: actions/download-artifact@v3 | |
with: | |
name: dangerous-test-only-github-runner_ubuntu-22.04-amd64.charm | |
- name: Enable br_netfilter | |
run: sudo modprobe br_netfilter | |
- name: Generate Runner Name | |
id: runner-name | |
run: echo name=${{ matrix.event.abbreviation }}-${{ needs.run-id.outputs.run-id }} >> $GITHUB_OUTPUT | |
- name: Deploy github-runner Charm | |
run: | | |
cp github-runner_ubuntu-22.04-amd64.charm /home/$USER/github-runner_ubuntu-22.04-amd64.charm | |
juju deploy /home/$USER/github-runner_ubuntu-22.04-amd64.charm \ | |
${{ steps.runner-name.outputs.name }} \ | |
--base [email protected] \ | |
--config path=${{ secrets.E2E_TESTING_REPO }} \ | |
--config token=${{ secrets.E2E_TESTING_TOKEN }} \ | |
--config virtual-machines=1 \ | |
--config denylist=10.0.0.0/8 \ | |
--config test-mode=insecure | |
- name: Watch github-runner (Pull Request) | |
if: matrix.event.name == 'pull_request' | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
timeout-minutes: 30 | |
run: | | |
juju debug-log --replay --tail & | |
while :; do | |
JOBS=$(gh api \ | |
-H "Accept: application/vnd.github+json" \ | |
-H "X-GitHub-Api-Version: 2022-11-28" \ | |
/repos/${{ secrets.E2E_TESTING_REPO }}/actions/runs/$GITHUB_RUN_ID/attempts/$GITHUB_RUN_ATTEMPT/jobs) | |
CONCLUSION=$(echo $JOBS | jq -r '.jobs[] | select(.name == "End-to-End Test") | .conclusion') | |
STATUS=$(echo $JOBS | jq -r '.jobs[] | select(.name == "End-to-End Test") | .status') | |
if [[ $STATUS != "queued" && $STATUS != "in_progress" ]]; then | |
break | |
fi | |
sleep 10 | |
done | |
if [[ $STATUS != "completed" || $CONCLUSION != "success" ]]; then | |
echo "test workflow failed with status: $STATUS, conclusion: $CONCLUSION" | |
kill $(jobs -p) | |
exit 1 | |
fi | |
- name: Watch github-runner (Workflow Dispatch) | |
if: matrix.event.name == 'workflow_dispatch' | |
env: | |
GH_TOKEN: ${{ secrets.E2E_TESTING_TOKEN }} | |
run: | | |
juju debug-log --replay --tail & | |
# Base any future branches on the current branch | |
REF_SHA=$(gh api \ | |
-H "Accept: application/vnd.github+json" \ | |
-H "X-GitHub-Api-Version: 2022-11-28" \ | |
/repos/${{ secrets.E2E_TESTING_REPO }}/git/ref/heads/$GITHUB_HEAD_REF \ | |
--jq .object.sha) | |
# Create a temporary reference/branch | |
gh api \ | |
--method POST \ | |
-H "Accept: application/vnd.github+json" \ | |
-H "X-GitHub-Api-Version: 2022-11-28" \ | |
/repos/${{ secrets.E2E_TESTING_REPO }}/git/refs \ | |
-f ref='refs/heads/${{ steps.runner-name.outputs.name }}' \ | |
-f sha=$REF_SHA | |
# Dispatch other workflow | |
gh workflow run workflow_dispatch_test.yaml \ | |
-R ${{ secrets.E2E_TESTING_REPO }} \ | |
--ref ${{ steps.runner-name.outputs.name }} \ | |
-f runner=${{ steps.runner-name.outputs.name }} | |
get-workflow-status() { | |
# Search recent workflow runs for the one designated by the run-id ref | |
output=$(gh run list \ | |
-R ${{ secrets.E2E_TESTING_REPO }} \ | |
-L 100 \ | |
--json headBranch,status \ | |
--jq '[.[] | select(.headBranch=="${{ steps.runner-name.outputs.name }}")]') | |
# Workflows that have not started have no status | |
if [ $(echo "$output" | jq 'length') -eq 0 ] | |
then | |
echo "not_started" | |
else | |
# Parse output with jq to get the status field of the first object | |
status=$(echo "$output" | jq -r '.[0].status') | |
echo "$status" | |
fi | |
} | |
# Wait for the workflow to start while checking its status | |
for i in {1..360} | |
do | |
status=$(get-workflow-status) | |
echo "workflow status: $status" | |
if [[ $status != "not_started" && $status != "queued" && $status != "in_progress" ]]; then | |
break | |
fi | |
sleep 10 | |
done | |
# Make sure the workflow was completed or else consider it failed | |
conclusion=$(gh run list \ | |
-R ${{ secrets.E2E_TESTING_REPO }} \ | |
-L 100 \ | |
--json headBranch,conclusion \ | |
--jq '.[] | select(.headBranch=="${{ steps.runner-name.outputs.name }}") | .conclusion') | |
if [[ $status != "completed" || $conclusion != "success" ]]; then | |
echo "test workflow failed with status: $status, conclusion: $conclusion" | |
kill $(jobs -p) | |
exit 1 | |
else | |
echo "Workflow completed with status: $status, conclusion: $conclusion, run-id: ${{ steps.runner-name.outputs.name }}" | |
kill $(jobs -p) | |
fi | |
- name: Show Firewall Rules | |
run: | | |
juju ssh ${{ steps.runner-name.outputs.name }}/0 sudo nft list ruleset | |
- name: Clean Up | |
if: always() && matrix.event.name == 'workflow_dispatch' | |
env: | |
GH_TOKEN: ${{ github.token }} | |
run: | | |
gh api \ | |
--method DELETE \ | |
-H "Accept: application/vnd.github+json" \ | |
-H "X-GitHub-Api-Version: 2022-11-28" \ | |
"/repos/${{ secrets.E2E_TESTING_REPO }}/git/refs/heads/${{ steps.runner-name.outputs.name }}" | |
echo "Deleted ref ${{ steps.runner-name.outputs.name }}" | |
e2e-test: | |
name: End-to-End Test | |
needs: [build-charm, run-id] | |
runs-on: [self-hosted, linux, x64, "pr-${{ needs.run-id.outputs.run-id }}"] | |
steps: | |
# below is a series of simple tests to assess the functionality of the newly spawned runner. | |
- name: Echo hello world | |
run: echo "hello world" | |
- name: File permission for /usr/local/bin | |
run: ls -ld /usr/local/bin | grep drwxrwxrwx | |
- name: Test file permission for /usr/local/bin | |
run: touch /usr/local/bin/test_file | |
# "Install microk8s" step will test if the proxies settings are correct. | |
- name: Proxy set in /etc/environment | |
run: cat /etc/environment | |
# "Update apt in python docker container" step will test docker default proxy settings due to | |
# pulling the python image. | |
- name: Proxy set in docker daemon | |
run: | | |
[[ -z "${http_proxy}" && -z "${HTTP_PROXY}" ]] \ | |
|| sudo cat /etc/systemd/system/docker.service.d/http-proxy.conf | grep HTTP_PROXY | |
# "Update apt in python docker container" step will test docker client default proxy settings. | |
- name: Proxy set in docker client | |
run: | | |
[[ -z "${http_proxy}" && -z "${HTTP_PROXY}" ]] \ | |
|| cat /home/ubuntu/.docker/config.json | grep httpProxy | |
- name: Install microk8s | |
run: sudo snap install microk8s --classic | |
- name: Wait for microk8s | |
timeout-minutes: 10 | |
run: microk8s status --wait-ready | |
- name: Deploy nginx for testing | |
run: microk8s kubectl create deployment nginx --image=nginx | |
- name: Wait for nginx to be ready | |
run: microk8s kubectl rollout status deployment/nginx --timeout=30m | |
- name: Update apt in python docker container | |
run: docker run python:3.10-slim apt update | |
- name: Docker version | |
run: docker version | |
- name: Check python alias for python3 | |
run: python --version | |
- name: pip version | |
run: python3 -m pip --version | |
- name: npm version | |
run: npm --version | |
- name: shellcheck version | |
run: shellcheck --version | |
- name: jq version | |
run: jq --version | |
- name: yq version | |
run: yq --version | |
- name: install check-jsonschema | |
run: python3 -m pip install check-jsonschema | |
# Test program installed by pip. The directory `~/.local/bin` need to be added to PATH. | |
- name: test check-jsonschema | |
run: check-jsonschema --version | |
- name: Test Firewall | |
run: | | |
HOST_IP=$(ip route | grep default | cut -f 3 -d" ") | |
[ $((ping $HOST_IP -c 5 || :) | grep "Destination Port Unreachable" | wc -l) -eq 5 ] |