From 43678bd0d99fcba9524871dbb614c558d79da6f1 Mon Sep 17 00:00:00 2001 From: Aleksander Zaruczewski Date: Mon, 11 Dec 2023 16:21:04 +0200 Subject: [PATCH] ci(acctest): proper concurrency support --- .github/workflows/acceptance-tests.yml | 40 ++++++++++++--- .github/workflows/test/README.md | 51 +++++++++++++++++++ .../workflows/test/acceptance-tests/README.md | 7 +++ .../acceptance-tests/setup_aiven_project.sh | 39 ++++++++++++++ .github/workflows/test/run_tests.sh | 3 ++ Makefile | 6 ++- 6 files changed, 138 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/test/README.md create mode 100644 .github/workflows/test/acceptance-tests/README.md create mode 100755 .github/workflows/test/acceptance-tests/setup_aiven_project.sh create mode 100755 .github/workflows/test/run_tests.sh diff --git a/.github/workflows/acceptance-tests.yml b/.github/workflows/acceptance-tests.yml index e5441a295..8d2b29879 100644 --- a/.github/workflows/acceptance-tests.yml +++ b/.github/workflows/acceptance-tests.yml @@ -9,13 +9,41 @@ permissions: contents: read concurrency: - group: ci-${{ github.ref }} + group: ci-${{ github.head_ref || github.ref }} cancel-in-progress: true jobs: - acceptance_tests: + setup_aiven_project: runs-on: ubuntu-latest + outputs: + selected_project_name: ${{ steps.set_project_name.outputs.project_name }} + steps: + - uses: actions/checkout@v4 + + - name: Fetch Aiven Projects + id: fetch_projects + run: | + response=$(curl -s -H "Authorization: Bearer ${{ secrets.AIVEN_TOKEN }}" https://api.aiven.io/v1/project) + echo "projects=$response" >> $GITHUB_OUTPUT + + - name: Select Project + id: set_project_name + run: | + projects=$(echo '${{ steps.fetch_projects.outputs.projects }}' | \ + jq --arg prefix "${{ secrets.AIVEN_PROJECT_NAME }}" \ + '[.projects[] | select(.project_name | startswith($prefix))]') + for project in $(echo "${projects}" | jq -r '.[].project_name'); do + services=$(curl -s -H "Authorization: Bearer ${{ secrets.AIVEN_TOKEN }}" \ + "https://api.aiven.io/v1/project/$project/service") + if [ "$(echo "$services" | jq '.services | length')" -eq 0 ]; then + echo "project_name=$project" >> $GITHUB_OUTPUT + break + fi + done + acceptance_tests: + needs: setup_aiven_project + runs-on: ubuntu-latest strategy: max-parallel: 5 fail-fast: false @@ -70,18 +98,16 @@ jobs: - run: make test-acc env: AIVEN_TOKEN: ${{ secrets.AIVEN_TOKEN }} - AIVEN_PROJECT_NAME: ${{ secrets.AIVEN_PROJECT_NAME }} + AIVEN_PROJECT_NAME: ${{ needs.setup_aiven_project.outputs.selected_project_name }} AIVEN_ORGANIZATION_NAME: ${{ secrets.AIVEN_ORGANIZATION_NAME }} AIVEN_ACCOUNT_NAME: ${{ secrets.AIVEN_ORGANIZATION_NAME }} PKG: ${{ matrix.pkg }} sweep: if: always() - needs: acceptance_tests - + needs: [acceptance_tests, setup_aiven_project] runs-on: ubuntu-latest steps: - - uses: softprops/turnstyle@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -112,6 +138,6 @@ jobs: command: make sweep env: AIVEN_TOKEN: ${{ secrets.AIVEN_TOKEN }} - AIVEN_PROJECT_NAME: ${{ secrets.AIVEN_PROJECT_NAME }} + AIVEN_PROJECT_NAME: ${{ needs.setup_aiven_project.outputs.selected_project_name }} AIVEN_ORGANIZATION_NAME: ${{ secrets.AIVEN_ORGANIZATION_NAME }} AIVEN_ACCOUNT_NAME: ${{ secrets.AIVEN_ORGANIZATION_NAME }} diff --git a/.github/workflows/test/README.md b/.github/workflows/test/README.md new file mode 100644 index 000000000..c98060bc3 --- /dev/null +++ b/.github/workflows/test/README.md @@ -0,0 +1,51 @@ +This directory contains the tests for some critical functionality of the GitHub Actions workflow. + +The tests are equivalent to the Bash scripts that are run in the workflow, but are atomic and can be run locally. + +## Structure + +The tests are organized into directories that correspond to the name of the workflow, +and the atomic Bash scripts have the name of the job that they test. + +```text +test +├── README.md +└── acceptance-tests + ├── README.md + └── setup_aiven_project.sh +└── ... +└── run_tests.sh +``` + +In the example above, the `acceptance-tests` directory contains the tests for the `acceptance-tests` workflow, +and the `setup_aiven_project.sh` script tests the `setup_aiven_project` job. + +If a workflow has multiple jobs, then there will be multiple scripts in the directory. + +Let's say that the `some-other-workflow` workflow has two jobs, `some_other_job` and `some_other_job_2`. +Then the directory structure would look like this: + +```text +some-other-workflow/ +├── README.md +└── some_other_job.sh +└── some_other_job_2.sh +``` + +The `README.md` file in each directory contains a brief description of the workflow and the job that it tests. + +## Running the tests + +To run the tests, you need to execute the `run_tests.sh` script in the root directory. + +```bash +./run_tests.sh +``` + +The script will run all the tests that are available. + +Alternatively, you can run the tests by running the `Makefile` in the root directory of this repository. + +```bash +make test-workflows +``` diff --git a/.github/workflows/test/acceptance-tests/README.md b/.github/workflows/test/acceptance-tests/README.md new file mode 100644 index 000000000..58c207531 --- /dev/null +++ b/.github/workflows/test/acceptance-tests/README.md @@ -0,0 +1,7 @@ +`acceptance-tests` is a directory that contains the tests for the `acceptance-tests` workflow. + +This workflow is responsible for running the acceptance tests for a specific branch. + +## Tests + +- `setup_aiven_project.sh` — This test sets up an Aiven project for the acceptance tests to run against. diff --git a/.github/workflows/test/acceptance-tests/setup_aiven_project.sh b/.github/workflows/test/acceptance-tests/setup_aiven_project.sh new file mode 100755 index 000000000..aeeca7446 --- /dev/null +++ b/.github/workflows/test/acceptance-tests/setup_aiven_project.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +show_help() { + echo "Usage: $0 -t AIVEN_TOKEN -p AIVEN_PROJECT_NAME" + echo " -t AIVEN_TOKEN Set the Aiven API token." + echo " -p AIVEN_PROJECT_NAME Set the Aiven Project Name prefix." + echo " -h Show help." +} + +while getopts 'ht:p:' flag; do + case "${flag}" in + t) AIVEN_TOKEN="${OPTARG}" ;; + p) AIVEN_PROJECT_NAME="${OPTARG}" ;; + h) show_help + exit 0 ;; + *) show_help + exit 1 ;; + esac +done + +if [ -z "$AIVEN_TOKEN" ] || [ -z "$AIVEN_PROJECT_NAME" ]; then + echo "Error: Aiven API token and Project Name prefix are required." + show_help + exit 1 +fi + +response=$(curl -s -H "Authorization: Bearer $AIVEN_TOKEN" https://api.aiven.io/v1/project) + +projects=$(echo "$response" | \ + jq --arg prefix "$AIVEN_PROJECT_NAME" '[.projects[] | select(.project_name | startswith($prefix))]') + +for project in $(echo "${projects}" | jq -r '.[].project_name'); do + services=$(curl -s -H "Authorization: Bearer $AIVEN_TOKEN" \ + "https://api.aiven.io/v1/project/$project/service") + if [ "$(echo "$services" | jq '.services | length')" -eq 0 ]; then + echo "Selected project: $project" + break + fi +done diff --git a/.github/workflows/test/run_tests.sh b/.github/workflows/test/run_tests.sh new file mode 100755 index 000000000..8ee6a3f70 --- /dev/null +++ b/.github/workflows/test/run_tests.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +./acceptance-tests/setup_aiven_project.sh diff --git a/Makefile b/Makefile index fe16508f1..c9ccfbf09 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: build build-dev debug test test-unit test-acc test-examples lint lint-go lint-test lint-docs fmt fmt-test fmt-imports clean clean-tools clean-examples sweep generate gen-go docs +.PHONY: build build-dev debug test test-unit test-acc test-examples test-workflows lint lint-go lint-test lint-docs fmt fmt-test fmt-imports clean clean-tools clean-examples sweep generate gen-go docs ################################################# # Global @@ -96,6 +96,10 @@ test-examples: build-dev clean-examples AIVEN_PROVIDER_PATH=$(BUILD_DEV_DIR) $(GO) test --tags=examples ./examples_tests/... \ -v -count $(TEST_COUNT) -parallel $(ACC_TEST_PARALLELISM) $(RUNARGS) $(TESTARGS) -timeout $(ACC_TEST_TIMEOUT) + +test-workflows: + cd .github/workflows/test && ./run_tests.sh + ################################################# # Lint #################################################