Conformance Ginkgo (ci-ginkgo) #1154
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: Conformance Ginkgo (ci-ginkgo) | |
# Any change in triggers needs to be reflected in the concurrency group. | |
on: | |
workflow_dispatch: | |
inputs: | |
PR-number: | |
description: "Pull request number." | |
required: true | |
context-ref: | |
description: "Context in which the workflow runs. If PR is from a fork, will be the PR target branch (general case). If PR is NOT from a fork, will be the PR branch itself (this allows committers to test changes to workflows directly from PRs)." | |
required: true | |
SHA: | |
description: "SHA under test (head of the PR branch)." | |
required: true | |
extra-args: | |
description: "[JSON object] Arbitrary arguments passed from the trigger comment via regex capture group. Parse with 'fromJson(inputs.extra-args).argName' in workflow." | |
required: false | |
default: '{}' | |
# Run every 6 hours | |
schedule: | |
- cron: '0 1/6 * * *' | |
# By specifying the access of one of the scopes, all of those that are not | |
# specified are set to 'none'. | |
permissions: | |
# To be able to access the repository with actions/checkout | |
contents: read | |
# To allow retrieving information from the PR API | |
pull-requests: read | |
# To be able to set commit status | |
statuses: write | |
concurrency: | |
# Structure: | |
# - Workflow name | |
# - Event type | |
# - A unique identifier depending on event type: | |
# - schedule: SHA | |
# - workflow_dispatch: PR number | |
# | |
# This structure ensures a unique concurrency group name is generated for each | |
# type of testing, such that re-runs will cancel the previous run. | |
group: | | |
${{ github.workflow }} | |
${{ github.event_name }} | |
${{ | |
(github.event_name == 'schedule' && github.sha) || | |
(github.event_name == 'workflow_dispatch' && github.event.inputs.PR-number) | |
}} | |
cancel-in-progress: true | |
env: | |
check_url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
jobs: | |
setup-vars: | |
name: Setup Vars | |
runs-on: ubuntu-latest | |
outputs: | |
SHA: ${{ steps.vars.outputs.SHA }} | |
context-ref: ${{ steps.vars.outputs.context-ref }} | |
owner: ${{ steps.vars.outputs.owner }} | |
steps: | |
- name: Set up job variables | |
id: vars | |
run: | | |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
SHA="${{ inputs.SHA }}" | |
CONTEXT_REF="${{ inputs.context-ref }}" | |
OWNER="${{ inputs.PR-number }}" | |
else | |
SHA="${{ github.sha }}" | |
CONTEXT_REF="${{ github.sha }}" | |
OWNER="${{ github.ref_name }}" | |
OWNER="${OWNER/./-}" | |
fi | |
echo SHA=${SHA} >> $GITHUB_OUTPUT | |
echo context-ref=${CONTEXT_REF} >> $GITHUB_OUTPUT | |
echo owner=${OWNER} >> $GITHUB_OUTPUT | |
commit-status-start: | |
name: Commit Status Start | |
runs-on: ubuntu-latest | |
steps: | |
- name: Set initial commit status | |
uses: myrotvorets/set-commit-status-action@38f3f27c7d52fb381273e95542f07f0fba301307 # v2.0.0 | |
with: | |
sha: ${{ inputs.SHA || github.sha }} | |
# Pre-build the ginkgo binary so that we don't have to build it for all | |
# runners. | |
build-ginkgo-binary: | |
runs-on: ubuntu-latest | |
name: Build Ginkgo E2E | |
timeout-minutes: 30 | |
steps: | |
# If any of these steps are modified, please update the copy of these | |
# steps further down under the 'setup-and-test' jobs. | |
# Warning: since this is a privileged workflow, subsequent workflow job | |
# steps must take care not to execute untrusted code. | |
- name: Checkout pull request branch (NOT TRUSTED) | |
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 | |
with: | |
ref: ${{ inputs.SHA || github.sha }} | |
persist-credentials: false | |
# Load Ginkgo build from GitHub | |
- name: Load ginkgo E2E from GH cache | |
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 | |
id: cache | |
with: | |
path: /tmp/.ginkgo-build/ | |
key: ${{ runner.os }}-ginkgo-e2e-${{ hashFiles('**/*.go') }} | |
- name: Install Go | |
if: ${{ steps.cache.outputs.cache-hit != 'true' }} | |
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 | |
with: | |
# renovate: datasource=golang-version depName=go | |
go-version: 1.21.6 | |
- name: Build Ginkgo | |
if: ${{ steps.cache.outputs.cache-hit != 'true' }} | |
shell: bash | |
run: | | |
go install github.com/onsi/ginkgo/[email protected] | |
mkdir -p /tmp/.ginkgo-build | |
- name: Build Test | |
if: ${{ steps.cache.outputs.cache-hit != 'true' }} | |
shell: bash | |
run: | | |
cd test | |
/home/runner/go/bin/ginkgo build | |
strip test.test | |
tar -cz test.test -f test.tgz | |
- name: Store Ginkgo Test in GitHub cache path | |
if: ${{ steps.cache.outputs.cache-hit != 'true' }} | |
shell: bash | |
run: | | |
mkdir -p /tmp/.ginkgo-build/ | |
if [ -f test/test.tgz ]; then | |
cp test/test.tgz /tmp/.ginkgo-build/ | |
echo "file copied" | |
fi | |
wait-for-images: | |
needs: setup-vars | |
runs-on: ubuntu-latest | |
name: Wait for images | |
timeout-minutes: 30 | |
steps: | |
- name: Checkout context ref (trusted) | |
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 | |
with: | |
ref: ${{ inputs.context-ref || github.sha }} | |
persist-credentials: false | |
- name: Set Environment Variables | |
uses: ./.github/actions/set-env-variables | |
- name: Wait for images to be available | |
timeout-minutes: 30 | |
shell: bash | |
run: | | |
for image in cilium-ci operator-generic-ci hubble-relay-ci ; do | |
until docker manifest inspect quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/$image:${{ needs.setup-vars.outputs.SHA }} &> /dev/null; do sleep 45s; done | |
done | |
generate-matrix: | |
name: Generate Job Matrix from YAMLs | |
needs: setup-vars | |
runs-on: ubuntu-latest | |
outputs: | |
matrix: ${{ steps.set-matrix.outputs.matrix }} | |
steps: | |
- name: Checkout context ref (trusted) | |
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 | |
with: | |
ref: ${{ inputs.context-ref || github.sha }} | |
persist-credentials: false | |
- name: Convert YAML to JSON | |
run: | | |
work_dir=".github/actions/ginkgo" | |
destination_directory="/tmp/generated/ginkgo" | |
mkdir -p "${destination_directory}" | |
for file in "${work_dir}"/main*.yaml; do | |
if [[ -f "$file" ]]; then | |
filename=$(basename "$file") | |
new_filename="${filename%.yaml}.json" | |
yq -o=json "${file}" | jq . > "${destination_directory}/${new_filename}" | |
fi | |
done | |
- name: Generate Matrix | |
id: set-matrix | |
run: | | |
if ${{ github.event_name == 'schedule' }}; then | |
k8s_versions_to_run='main-scheduled.json' | |
else | |
k8s_versions_to_run='main-prs.json' | |
fi | |
# Generate a Matrix from all k8s versions defined in '${k8s_versions_to_run}' | |
# combined with 'main-focus.yaml'. | |
# Use 'main-k8s-versions.yaml' to | |
# retrieve which kernel versions should be used for which k8s version. | |
dir="/tmp/generated/ginkgo" | |
cd ${dir} | |
jq --argjson prs "$(jq '.["k8s-version"]' ${k8s_versions_to_run})" \ | |
--argfile focus main-focus.json \ | |
'.include |= map(select(.["k8s-version"] as $k | $prs[] | select($k == .))) + $focus.include | | |
. + {"k8s-version": $prs} | | |
.focus = $focus.focus | .exclude = $focus.exclude' \ | |
main-k8s-versions.json> /tmp/merged.json | |
echo "Generated matrix:" | |
cat /tmp/merged.json | |
echo "matrix=$(jq -c . < /tmp/merged.json)" >> $GITHUB_OUTPUT | |
setup-and-test: | |
needs: [setup-vars, build-ginkgo-binary, generate-matrix, wait-for-images] | |
runs-on: | |
group: ginkgo-runners | |
timeout-minutes: 35 | |
name: "E2E Test (${{ matrix.k8s-version }}, ${{matrix.focus}})" | |
env: | |
job_name: "E2E Test (${{ matrix.k8s-version }}, ${{matrix.focus}})" | |
strategy: | |
fail-fast: false | |
max-parallel: 60 | |
matrix: ${{ fromJSON(needs.generate-matrix.outputs.matrix) }} | |
steps: | |
- name: Checkout context ref (trusted) | |
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 | |
with: | |
ref: ${{ inputs.context-ref || github.sha }} | |
persist-credentials: false | |
- name: Set Environment Variables | |
uses: ./.github/actions/set-env-variables | |
# Warning: since this is a privileged workflow, subsequent workflow job | |
# steps must take care not to execute untrusted code. | |
- name: Checkout pull request branch (NOT TRUSTED) | |
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 | |
with: | |
ref: ${{ inputs.SHA || github.sha }} | |
persist-credentials: false | |
- name: Install cilium-cli | |
shell: bash | |
run: | | |
cid=$(docker create quay.io/cilium/cilium-cli-ci:latest ls) | |
docker cp $cid:/usr/local/bin/cilium ./cilium-cli | |
docker rm $cid | |
- name: Install helm | |
shell: bash | |
run: | | |
# renovate: datasource=github-releases depName=helm/helm | |
HELM_VERSION=v3.13.1 | |
wget "https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz" | |
tar -xf "helm-${HELM_VERSION}-linux-amd64.tar.gz" | |
mv ./linux-amd64/helm ./helm | |
- name: Provision LVH VMs | |
id: provision-vh-vms | |
uses: cilium/little-vm-helper@9d758b756305e83718a51b792a5aeabd022a39ec # v0.0.16 | |
with: | |
test-name: datapath-conformance | |
install-dependencies: true | |
image-version: ${{ matrix.kernel }} | |
host-mount: ./ | |
cpu: 4 | |
mem: 12G | |
cmd: | | |
git config --global --add safe.directory /host | |
mv /host/helm /usr/bin | |
mv /host/cilium-cli /usr/bin | |
- name: Provision kind | |
timeout-minutes: 5 | |
uses: cilium/little-vm-helper@9d758b756305e83718a51b792a5aeabd022a39ec # v0.0.16 | |
with: | |
provision: 'false' | |
cmd: | | |
cd /host/ | |
if [[ "${{ matrix.kernel }}" == bpf-next-* ]]; then | |
./contrib/scripts/kind.sh "" 2 "" "${{ matrix.kube-image }}" "none" "${{ matrix.ip-family }}" | |
kubectl label node kind-worker2 cilium.io/ci-node=kind-worker2 | |
# Avoid re-labeling this node by setting "node-role.kubernetes.io/controlplane" | |
kubectl label node kind-worker2 node-role.kubernetes.io/controlplane= | |
else | |
./contrib/scripts/kind.sh "" 1 "" "${{ matrix.kube-image }}" "iptables" "${{ matrix.ip-family }}" | |
fi | |
# Some tests using demo-customcalls.yaml are mounting this directoy | |
mkdir -p /home/vagrant/go/src/github.com/cilium | |
ln -s /host /home/vagrant/go/src/github.com/cilium/cilium | |
git config --add safe.directory /cilium | |
# Load Ginkgo build from GitHub | |
- name: Load ${{ matrix.name }} Ginkgo build from GitHub | |
uses: actions/cache/restore@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 | |
id: cache | |
with: | |
path: /tmp/.ginkgo-build/ | |
key: ${{ runner.os }}-ginkgo-e2e-${{ hashFiles('**/*.go') }} | |
# Re-build the tests if it was a cache miss. | |
- name: Install Go | |
if: ${{ steps.cache.outputs.cache-hit != 'true' }} | |
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 | |
with: | |
# renovate: datasource=golang-version depName=go | |
go-version: 1.21.6 | |
- name: Build Ginkgo | |
if: ${{ steps.cache.outputs.cache-hit != 'true' }} | |
shell: bash | |
run: | | |
go install github.com/onsi/ginkgo/[email protected] | |
mkdir -p /tmp/.ginkgo-build | |
- name: Build Test | |
if: ${{ steps.cache.outputs.cache-hit != 'true' }} | |
shell: bash | |
run: | | |
cd test | |
/home/runner/go/bin/ginkgo build | |
strip test.test | |
tar -cz test.test -f test.tgz | |
- name: Store Ginkgo Test in GitHub cache path | |
if: ${{ steps.cache.outputs.cache-hit != 'true' }} | |
shell: bash | |
run: | | |
mkdir -p /tmp/.ginkgo-build/ | |
if [ -f test/test.tgz ]; then | |
cp test/test.tgz /tmp/.ginkgo-build/ | |
echo "file copied" | |
fi | |
- name: Copy Ginkgo binary | |
shell: bash | |
run: | | |
cd test/ | |
tar -xf /tmp/.ginkgo-build/test.tgz | |
- name: Run tests | |
id: run-tests | |
timeout-minutes: 40 | |
uses: cilium/little-vm-helper@9d758b756305e83718a51b792a5aeabd022a39ec # v0.0.16 | |
with: | |
provision: 'false' | |
cmd: | | |
cd /host/test/ | |
kubectl get ns -A -o wide | |
kubectl get pods -A -o wide | |
export K8S_NODES=2 | |
export NETNEXT=0 | |
if [[ "${{ matrix.kernel }}" == bpf-next-* ]]; then | |
export KERNEL=net-next | |
export NETNEXT=1 | |
export KUBEPROXY=0 | |
export K8S_NODES=3 | |
export NO_CILIUM_ON_NODES=kind-worker2 | |
elif [[ "${{ matrix.kernel }}" == 4.19-* ]]; then | |
export KERNEL=419 | |
elif [[ "${{ matrix.kernel }}" == 5.4-* ]]; then | |
export KERNEL=54 | |
fi | |
export K8S_VERSION=${{ matrix.k8s-version }} | |
export CNI_INTEGRATION=kind | |
export INTEGRATION_TESTS=true | |
# GitHub actions do not support IPv6 connectivity to outside | |
# world. | |
export CILIUM_NO_IPV6_OUTSIDE=true | |
echo "/root/go/bin/ginkgo \ | |
--focus=\"${{ matrix.cliFocus }}\" \ | |
--skip=\"${{ matrix.cliSkip }}\" \ | |
--seed=1679952881 \ | |
-v -- \ | |
-cilium.provision=false \ | |
-cilium.image=quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/cilium-ci \ | |
-cilium.tag=${{ needs.setup-vars.outputs.SHA }} \ | |
-cilium.operator-image=quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/operator \ | |
-cilium.operator-tag=${{ needs.setup-vars.outputs.SHA }} \ | |
-cilium.hubble-relay-image=quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/hubble-relay-ci \ | |
-cilium.hubble-relay-tag=${{ needs.setup-vars.outputs.SHA }} \ | |
-cilium.kubeconfig=/root/.kube/config \ | |
-cilium.provision-k8s=false \ | |
-cilium.operator-suffix=-ci" | |
./test.test \ | |
--ginkgo.focus="${{ matrix.cliFocus }}" \ | |
--ginkgo.skip="${{ matrix.cliSkip }}" \ | |
--ginkgo.seed=1679952881 \ | |
--ginkgo.v -- \ | |
-cilium.provision=false \ | |
-cilium.image=quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/cilium-ci \ | |
-cilium.tag=${{ needs.setup-vars.outputs.SHA }} \ | |
-cilium.operator-image=quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/operator \ | |
-cilium.operator-tag=${{ needs.setup-vars.outputs.SHA }} \ | |
-cilium.hubble-relay-image=quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/hubble-relay-ci \ | |
-cilium.hubble-relay-tag=${{ needs.setup-vars.outputs.SHA }} \ | |
-cilium.kubeconfig=/root/.kube/config \ | |
-cilium.provision-k8s=false \ | |
-cilium.operator-suffix=-ci | |
- name: Fetch artifacts | |
if: ${{ !success() && steps.provision-vh-vms.outcome == 'success' }} | |
uses: cilium/little-vm-helper@9d758b756305e83718a51b792a5aeabd022a39ec # v0.0.16 | |
with: | |
provision: 'false' | |
cmd: | | |
cd /host | |
kubectl get pods --all-namespaces -o wide | |
tar -zcf "test_results-${{ env.job_name }}.tar.gz" /host/test/test_results | |
- name: Upload artifacts | |
if: ${{ !success() }} | |
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 | |
with: | |
name: cilium-sysdumps-${{ matrix.k8s-version }}-${{matrix.focus}} | |
path: | | |
cilium-sysdump-*.zip | |
bugtool-*.tar.gz | |
test_results-*.tar.gz | |
- name: Fetch JUnits | |
if: ${{ always() && steps.run-tests.outcome != 'skipped' }} | |
shell: bash | |
run: | | |
mkdir -p cilium-junits | |
cd test/ | |
junit_filename="${{ env.job_name }}.xml" | |
for filename in *.xml; do cp "${filename}" "../cilium-junits/${junit_filename}"; done; | |
- name: Upload JUnits [junit] | |
if: ${{ always() }} | |
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 | |
with: | |
name: cilium-junits-${{ matrix.k8s-version }}-${{matrix.focus}} | |
path: cilium-junits/*.xml | |
- name: Publish Test Results As GitHub Summary | |
if: ${{ always() }} | |
uses: aanm/junit2md@332ebf0fddd34e91b03a832cfafaa826306558f9 # v0.0.3 | |
with: | |
junit-directory: "cilium-junits" | |
merge-upload: | |
if: ${{ always() }} | |
name: Merge and Upload Artifacts | |
runs-on: ubuntu-latest | |
needs: setup-and-test | |
steps: | |
- name: Merge Sysdumps | |
if: ${{ needs.setup-and-test.result == 'failure' }} | |
uses: actions/upload-artifact/merge@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 | |
with: | |
name: cilium-sysdumps | |
pattern: cilium-sysdumps-* | |
retention-days: 5 | |
delete-merged: true | |
continue-on-error: true | |
- name: Merge JUnits | |
uses: actions/upload-artifact/merge@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 | |
with: | |
name: cilium-junits | |
pattern: cilium-junits-* | |
retention-days: 5 | |
delete-merged: true | |
commit-status-final: | |
if: ${{ always() }} | |
name: Commit Status Final | |
needs: setup-and-test | |
runs-on: ubuntu-latest | |
steps: | |
- name: Determine final commit status | |
id: commit-status | |
shell: bash | |
run: | | |
# When one of the prerequisites of setup-and-test fails, then that | |
# job gets skipped. Let's convert the status so that we correctly | |
# report that as a proper failure. | |
if [ "${{ needs.setup-and-test.result }}" != "skipped" ]; then | |
echo "status=${{ needs.setup-and-test.result }}" >> $GITHUB_OUTPUT | |
else | |
echo "status=failure" >> $GITHUB_OUTPUT | |
fi | |
- name: Set final commit status | |
uses: myrotvorets/set-commit-status-action@38f3f27c7d52fb381273e95542f07f0fba301307 # v2.0.0 | |
with: | |
sha: ${{ inputs.SHA || github.sha }} | |
status: ${{ steps.commit-status.outputs.status }} |