ci(test): test parallel CT runs on self-hosted runners
This commit is contained in:
parent
d1a5dcd222
commit
25b6a1c158
|
@ -10,26 +10,77 @@ on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
run_proper_test:
|
prepare:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
container: emqx/build-env:erl23.3.4.9-3-ubuntu20.04
|
container: emqx/build-env:erl23.3.4.9-3-ubuntu20.04
|
||||||
|
outputs:
|
||||||
|
ct_apps: ${{ steps.run_find_apps.outputs.ct_apps }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: set git credentials
|
with:
|
||||||
|
path: source
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: git credentials
|
||||||
run: |
|
run: |
|
||||||
if make emqx-ee --dry-run > /dev/null 2>&1; then
|
if make emqx-ee --dry-run > /dev/null 2>&1; then
|
||||||
echo "https://ci%40emqx.io:${{ secrets.CI_GIT_TOKEN }}@github.com" > $HOME/.git-credentials
|
echo "https://ci%40emqx.io:${{ secrets.CI_GIT_TOKEN }}@github.com" > $HOME/.git-credentials
|
||||||
git config --global credential.helper store
|
git config --global credential.helper store
|
||||||
fi
|
fi
|
||||||
- name: proper
|
- name: find_ct_apps
|
||||||
run: make proper
|
working-directory: source
|
||||||
|
id: run_find_apps
|
||||||
|
# emqx_plugin_libs doesn't have a test suite -> excluded from app list
|
||||||
|
run: |
|
||||||
|
ct_apps="$(./scripts/find-apps.sh --json | jq -c 'del (.[] | select (. == "apps/emqx_plugin_libs"))')"
|
||||||
|
echo "ct-apps: $ct_apps"
|
||||||
|
echo "ct_apps=$ct_apps" >> $GITHUB_OUTPUT
|
||||||
|
- name: get_all_deps
|
||||||
|
working-directory: source
|
||||||
|
run: |
|
||||||
|
make deps-all
|
||||||
|
./rebar3 as test compile
|
||||||
|
cd ..
|
||||||
|
zip -ryq source.zip source/* source/.[^.]*
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: source
|
||||||
|
path: source.zip
|
||||||
|
|
||||||
run_common_test:
|
eunit_and_proper:
|
||||||
runs-on: ${{ matrix.runs-on }}
|
needs: prepare
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
container: emqx/build-env:erl23.3.4.9-3-ubuntu20.04
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
task:
|
||||||
|
- eunit
|
||||||
|
- proper
|
||||||
|
steps:
|
||||||
|
- uses: AutoModality/action-clean@v1
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: source
|
||||||
|
path: .
|
||||||
|
- name: unzip source code
|
||||||
|
run: unzip -o -q source.zip
|
||||||
|
# produces eunit.coverdata and proper.coverdata
|
||||||
|
- name: eunit and proper
|
||||||
|
working-directory: source
|
||||||
|
run: make ${{ matrix.task }}
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: cover-${{ matrix.task }}
|
||||||
|
path: source/_build/test/cover
|
||||||
|
|
||||||
|
ct:
|
||||||
|
needs: prepare
|
||||||
|
runs-on: ${{ matrix.runs-on }}
|
||||||
|
strategy:
|
||||||
|
max-parallel: 12
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
app_name: ${{ fromJson(needs.prepare.outputs.ct_apps) }}
|
||||||
runs-on:
|
runs-on:
|
||||||
- aws-amd64
|
- aws-amd64
|
||||||
- ubuntu-20.04
|
- ubuntu-20.04
|
||||||
|
@ -41,13 +92,20 @@ jobs:
|
||||||
- runs-on: aws-amd64
|
- runs-on: aws-amd64
|
||||||
use-self-hosted: false
|
use-self-hosted: false
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: AutoModality/action-clean@v1
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: source
|
||||||
|
path: .
|
||||||
|
- name: unzip source code
|
||||||
|
run: unzip -q source.zip
|
||||||
# to avoid dirty self-hosted runners
|
# to avoid dirty self-hosted runners
|
||||||
- name: stop containers
|
- name: stop containers
|
||||||
run: |
|
run: |
|
||||||
docker rm -f $(docker ps -qa) || true
|
docker rm -f $(docker ps -qa) || true
|
||||||
docker network rm $(docker network ls -q) || true
|
docker network rm $(docker network ls -q) || true
|
||||||
- name: docker compose up
|
- name: docker compose up
|
||||||
|
working-directory: source
|
||||||
if: endsWith(github.repository, 'emqx')
|
if: endsWith(github.repository, 'emqx')
|
||||||
env:
|
env:
|
||||||
MYSQL_TAG: 8
|
MYSQL_TAG: 8
|
||||||
|
@ -66,7 +124,9 @@ jobs:
|
||||||
-f .ci/docker-compose-file/docker-compose-pgsql-tcp.yaml \
|
-f .ci/docker-compose-file/docker-compose-pgsql-tcp.yaml \
|
||||||
-f .ci/docker-compose-file/docker-compose-redis-single-tcp.yaml \
|
-f .ci/docker-compose-file/docker-compose-redis-single-tcp.yaml \
|
||||||
up -d --build
|
up -d --build
|
||||||
|
docker exec -i erlang bash -c "git config --global --add safe.directory /emqx"
|
||||||
- name: docker compose up
|
- name: docker compose up
|
||||||
|
working-directory: source
|
||||||
if: endsWith(github.repository, 'emqx-enterprise')
|
if: endsWith(github.repository, 'emqx-enterprise')
|
||||||
env:
|
env:
|
||||||
MYSQL_TAG: 8
|
MYSQL_TAG: 8
|
||||||
|
@ -111,12 +171,8 @@ jobs:
|
||||||
!= $(docker ps -a --filter name=client | wc -l) ]; do
|
!= $(docker ps -a --filter name=client | wc -l) ]; do
|
||||||
sleep 5
|
sleep 5
|
||||||
done
|
done
|
||||||
- name: run eunit
|
|
||||||
run: |
|
|
||||||
docker exec -i erlang bash -c "make eunit"
|
|
||||||
- name: run common test
|
- name: run common test
|
||||||
run: |
|
run: docker exec -i erlang bash -c "make ${{ matrix.app_name }}-ct-pipeline"
|
||||||
docker exec -i erlang bash -c "make ct"
|
|
||||||
- name: run cover
|
- name: run cover
|
||||||
run: |
|
run: |
|
||||||
printenv > .env
|
printenv > .env
|
||||||
|
@ -125,19 +181,57 @@ jobs:
|
||||||
docker exec --env-file .env -i erlang bash -c "make coveralls"
|
docker exec --env-file .env -i erlang bash -c "make coveralls"
|
||||||
- name: cat rebar.crashdump
|
- name: cat rebar.crashdump
|
||||||
if: failure()
|
if: failure()
|
||||||
|
working-directory: source
|
||||||
run: if [ -f 'rebar3.crashdump' ];then cat 'rebar3.crashdump'; fi
|
run: if [ -f 'rebar3.crashdump' ];then cat 'rebar3.crashdump'; fi
|
||||||
- uses: actions/upload-artifact@v1
|
- name: set log file name
|
||||||
|
if: failure()
|
||||||
|
run: echo "LOGFILENAME=logs-$(echo ${{ matrix.app_name }} | tr '/' '_')" >> $GITHUB_ENV
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: logs
|
name: ${{ env.LOGFILENAME }}
|
||||||
path: _build/test/logs
|
path: source/_build/test/logs
|
||||||
- uses: actions/upload-artifact@v1
|
if-no-files-found: warn
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: cover
|
name: cover
|
||||||
path: _build/test/cover
|
path: source/_build/test/cover
|
||||||
|
if-no-files-found: warn
|
||||||
|
|
||||||
|
make_cover:
|
||||||
|
needs:
|
||||||
|
- eunit_and_proper
|
||||||
|
- ct
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
container: emqx/build-env:erl23.3.4.9-3-ubuntu20.04
|
||||||
|
steps:
|
||||||
|
- uses: AutoModality/action-clean@v1
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: source
|
||||||
|
path: .
|
||||||
|
- name: unzip source code
|
||||||
|
run: unzip -q source.zip
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
name: download cover data
|
||||||
|
with:
|
||||||
|
name: cover
|
||||||
|
path: source/_build/test/cover
|
||||||
|
- name: make cover
|
||||||
|
working-directory: source
|
||||||
|
run: make cover
|
||||||
|
- name: send to coveralls
|
||||||
|
working-directory: source
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: make coveralls
|
||||||
|
- name: get coveralls logs
|
||||||
|
working-directory: source
|
||||||
|
if: failure()
|
||||||
|
run: cat rebar3.crashdump
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
needs: run_common_test
|
needs: make_cover
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- name: Coveralls Finished
|
- name: Coveralls Finished
|
||||||
|
|
8
Makefile
8
Makefile
|
@ -61,6 +61,14 @@ $1-ct: $(REBAR)
|
||||||
endef
|
endef
|
||||||
$(foreach app,$(APPS),$(eval $(call gen-app-ct-target,$(app))))
|
$(foreach app,$(APPS),$(eval $(call gen-app-ct-target,$(app))))
|
||||||
|
|
||||||
|
## app/name-ct-pipeline targets are used in pipeline -> make cover data for each app
|
||||||
|
.PHONY: $(APPS:%=%-ct-pipeline)
|
||||||
|
define gen-app-ct-target-pipeline
|
||||||
|
$1-ct-pipeline: $(REBAR)
|
||||||
|
$(REBAR) ct --name 'test@127.0.0.1' -c -v --cover_export_name $(PROFILE)-$(subst /,-,$1) --suite $(shell $(CURDIR)/scripts/find-suites.sh $1)
|
||||||
|
endef
|
||||||
|
$(foreach app,$(APPS),$(eval $(call gen-app-ct-target-pipeline,$(app))))
|
||||||
|
|
||||||
## apps/name-prop targets
|
## apps/name-prop targets
|
||||||
.PHONY: $(APPS:%=%-prop)
|
.PHONY: $(APPS:%=%-prop)
|
||||||
define gen-app-prop-target
|
define gen-app-prop-target
|
||||||
|
|
|
@ -5,6 +5,29 @@ set -euo pipefail
|
||||||
# ensure dir
|
# ensure dir
|
||||||
cd -P -- "$(dirname -- "$0")/.."
|
cd -P -- "$(dirname -- "$0")/.."
|
||||||
|
|
||||||
|
help() {
|
||||||
|
echo
|
||||||
|
echo "-h|--help: To display this usage info"
|
||||||
|
echo "--json: Print apps in json"
|
||||||
|
}
|
||||||
|
|
||||||
|
WANT_JSON='no'
|
||||||
|
while [ "$#" -gt 0 ]; do
|
||||||
|
case $1 in
|
||||||
|
-h|--help)
|
||||||
|
help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
--json)
|
||||||
|
WANT_JSON='yes'
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "unknown option $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
if [ "$(./scripts/get-distro.sh)" = 'windows' ]; then
|
if [ "$(./scripts/get-distro.sh)" = 'windows' ]; then
|
||||||
# Otherwise windows may resolve to find.exe
|
# Otherwise windows may resolve to find.exe
|
||||||
FIND="/usr/bin/find"
|
FIND="/usr/bin/find"
|
||||||
|
@ -17,17 +40,26 @@ find_app() {
|
||||||
"$FIND" "${appdir}" -mindepth 1 -maxdepth 1 -type d
|
"$FIND" "${appdir}" -mindepth 1 -maxdepth 1 -type d
|
||||||
}
|
}
|
||||||
|
|
||||||
# append emqx application first
|
EM="emqx"
|
||||||
echo 'emqx'
|
CE="$(find_app 'apps')"
|
||||||
|
|
||||||
find_app 'apps'
|
|
||||||
if [ -f 'EMQX_ENTERPRISE' ]; then
|
if [ -f 'EMQX_ENTERPRISE' ]; then
|
||||||
find_app 'lib-ee'
|
LIB="$(find_app 'lib-ee')"
|
||||||
else
|
else
|
||||||
find_app 'lib-ce'
|
LIB="$(find_app 'lib-ce')"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
## find directories in lib-extra
|
## find directories in lib-extra
|
||||||
find_app 'lib-extra'
|
LIBE="$(find_app 'lib-extra')"
|
||||||
|
|
||||||
## find symlinks in lib-extra
|
## find symlinks in lib-extra
|
||||||
"$FIND" 'lib-extra' -mindepth 1 -maxdepth 1 -type l -exec test -e {} \; -print
|
LIBES="$("$FIND" 'lib-extra' -mindepth 1 -maxdepth 1 -type l -exec test -e {} \; -print)"
|
||||||
|
|
||||||
|
APPS_ALL="$(echo -e "${EM}\n${CE}\n${LIB}\n${LIBE}\n${LIBES}")"
|
||||||
|
|
||||||
|
if [ "$WANT_JSON" = 'yes' ]; then
|
||||||
|
echo "${APPS_ALL}" | xargs | tr -d '\n' | jq -R -s -c 'split(" ")'
|
||||||
|
else
|
||||||
|
echo "${APPS_ALL}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue