From 5380a7067afc1f726ad44ecefc5f7cc42527820e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=BCchinger=20Dominic?= Date: Thu, 26 Dec 2024 16:52:28 +0100 Subject: [PATCH] build: Added basic CI support --- .busted | 13 ++++- .github/workflows/lint.yml | 30 +++++++++++ .github/workflows/sast.yml | 28 ++++++++++ .github/workflows/tests.yml | 36 +++++++++++++ .gitignore | 3 ++ .luacov | 13 ++--- BACKLOG.md | 1 + Makefile | 51 ++++++++++++++----- .../kong-plugin-testing-0.1.0-0.rockspec | 2 + 9 files changed, 157 insertions(+), 20 deletions(-) create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/sast.yml create mode 100644 .github/workflows/tests.yml diff --git a/.busted b/.busted index 74bfc4b..019d0c8 100644 --- a/.busted +++ b/.busted @@ -1,10 +1,19 @@ +-- luacheck: ignore 631 +local current_folder = debug.getinfo(1).source:match("@?(.*/)"):sub(1, -2) + return { _all = { + ROOT = {current_folder .. "/spec"}, verbose = false, - coverage = false, + ["coverage-config-file"] = current_folder .. "/.luacov", + }, + default = { output = "gtest", }, ci = { - ["exclude-tags"] = "postgres", + output = "junit", + -- First argument is the path to the output file + -- https://github.com/lunarmodules/busted/blob/a144124839f027a2d0a95791936c478d047126fc/busted/outputHandlers/junit.lua#L34C34-L34C43 + Xoutput = current_folder .. "/test-results/busted-junit.xml", }, } diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..dd3f909 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,30 @@ +name: Lint + +on: [push, pull_request] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + lua-check: + timeout-minutes: ${{ fromJSON(vars.GHA_DEFAULT_TIMEOUT || 10) }} + name: Lua Check + runs-on: ubuntu-24.04 + permissions: + contents: read + issues: read + checks: write + pull-requests: write + if: (github.actor != 'dependabot[bot]') + + steps: + - name: Checkout source code + uses: actions/checkout@v3 + + - name: Lua Check + uses: Kong/public-shared-actions/code-check-actions/lua-lint@0ccacffed804d85da3f938a1b78c12831935f992 # v2.8.0 + with: + additional_args: '--no-default-config --config .luacheckrc' + action_fail: true + print_results: true diff --git a/.github/workflows/sast.yml b/.github/workflows/sast.yml new file mode 100644 index 0000000..6b25c1e --- /dev/null +++ b/.github/workflows/sast.yml @@ -0,0 +1,28 @@ +name: SAST + +on: + pull_request: {} + push: + branches: + - master + - main + workflow_dispatch: {} + + +jobs: + semgrep: + timeout-minutes: ${{ fromJSON(vars.GHA_DEFAULT_TIMEOUT || 10) }} + name: Semgrep SAST + runs-on: ubuntu-latest + permissions: + # required for all workflows + security-events: write + # only required for workflows in private repositories + actions: read + contents: read + + if: (github.actor != 'dependabot[bot]') + + steps: + - uses: actions/checkout@v3 + - uses: Kong/public-shared-actions/security-actions/semgrep@33449c46c6766a3d3c8f167cc383381225862b36 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..e17a7d6 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,36 @@ +name: Test + +on: [push, pull_request] + +jobs: + tests: + timeout-minutes: ${{ fromJSON(vars.GHA_DEFAULT_TIMEOUT || 10) }} + name: Busted Tests + + runs-on: ubuntu-24.04 + permissions: + checks: write + pull-requests: write + + steps: + - name: Checkout source code + uses: actions/checkout@main + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Run tests + run: make test-unit DOCKER_RUN_FLAGS_TTY='' BUSTED_COVERAGE=true BUSTED_RUN_PROFILE=ci + - name: Publish Test Results + uses: EnricoMi/publish-unit-test-result-action@v2 + if: always() + with: + files: | + test-results/**/*.xml + - name: Setup LCOV + uses: hrishikesh-kadam/setup-lcov@v1 + - name: Report code coverage + uses: zgosalvez/github-actions-report-lcov@v4 + with: + coverage-files: test-results/lcov.info + artifact-name: code-coverage-report + github-token: ${{ secrets.GITHUB_TOKEN }} + update-comment: true diff --git a/.gitignore b/.gitignore index d6fc268..131fcfe 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,9 @@ luacov.report.out /lua_modules/ /.luarocks +# LuaCov and Busted test results +/test-results/ + /.docker/ # Local folder for scratch files diff --git a/.luacov b/.luacov index 07c19d8..90df3e9 100644 --- a/.luacov +++ b/.luacov @@ -1,7 +1,8 @@ -include = { - "%/kong%-plugin%/kong%/.+$", +return { + statsfile = "/kong-plugin/test-results/luacov.stats.out", + reportfile = "/kong-plugin/test-results/luacov.report.out", + runreport = false, + include = { + "%/kong%-plugin%/kong%/.+$", + } } - -statsfile = "/kong-plugin/luacov.stats.out" -reportfile = "/kong-plugin/luacov.report.out" -runreport = true diff --git a/BACKLOG.md b/BACKLOG.md index 4514ac9..dd84c9f 100644 --- a/BACKLOG.md +++ b/BACKLOG.md @@ -14,3 +14,4 @@ ## Cleanup - [ ] The OpenFGA store id in the sqlite database is fixed. Make it dynamic when loading the data. +- [ ] Test with PostgreSQL as database backend. diff --git a/Makefile b/Makefile index bc61594..feb49c4 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,8 @@ ROCK_FILE := kong-plugin-$(KONG_PLUGIN_NAME)-$(KONG_PLUGIN_VERSION)-$(KONG_PLUGI SERVROOT_PATH := servroot +TEST_RESULTS_PATH := test-results + # Overwrite if you want to use `docker` with sudo DOCKER ?= docker @@ -20,19 +22,30 @@ _docker_is_podman = $(shell $(DOCKER) --version | grep podman 2>/dev/null) # - set username/UID to executor DOCKER_USER ?= $$(id -u) DOCKER_USER_OPT = $(if $(_docker_is_podman),--userns keep-id,--user $(DOCKER_USER)) -DOCKER_RUN_FLAGS ?= --rm --interactive --tty $(DOCKER_USER_OPT) +DOCKER_RUN_FLAGS_TTY ?= --tty +DOCKER_RUN_FLAGS ?= --rm --interactive $(DOCKER_RUN_FLAGS_TTY) $(DOCKER_USER_OPT) + +DOCKER_MOUNT_IN_CONTAINER := /kong-plugin DOCKER_NO_CACHE := BUILDKIT_PROGRESS := +BUSTED_RUN_PROFILE := default BUSTED_FILTER := -BUSTED_ARGS = --config-file /kong-plugin/.busted --run ci --filter '$(BUSTED_FILTER)' +BUSTED_EXCLUDE_TAGS := postgres +BUSTED_COVERAGE := false + +BUSTED_ARGS = --config-file $(DOCKER_MOUNT_IN_CONTAINER)/.busted --run '$(BUSTED_RUN_PROFILE)' --exclude-tags='$(BUSTED_EXCLUDE_TAGS)' --filter '$(BUSTED_FILTER)' ifdef BUSTED_NO_KEEP_GOING BUSTED_ARGS += --no-keep-going endif +ifneq ($(BUSTED_COVERAGE), false) + BUSTED_ARGS += --coverage +endif + KONG_SMOKE_TEST_DEPLOYMENT_PATH := _build/deployment/kong-smoke-test CONTAINER_CI_KONG_TOOLING_IMAGE_PATH := _build/images/kong-tooling @@ -126,10 +139,10 @@ CONTAINER_CI_KONG_SMOKE_TEST_BUILD = DOCKER_BUILDKIT=1 BUILDKIT_PROGRESS=$(BUILD . CONTAINER_CI_KONG_TOOLING_RUN := MSYS_NO_PATHCONV=1 $(DOCKER) run $(DOCKER_RUN_FLAGS) \ - -v '$(PWD):/kong-plugin' \ + -v '$(PWD):$(DOCKER_MOUNT_IN_CONTAINER)' \ -e KONG_SPEC_TEST_REDIS_HOST='$(CONTAINER_CI_REDIS_NAME)' \ -e KONG_SPEC_TEST_LIVE_HOSTNAME='$(CONTAINER_CI_OPENFGA_NAME)' \ - -e KONG_LICENSE_PATH=/kong-plugin/kong-license.json \ + -e KONG_LICENSE_PATH=$(DOCKER_MOUNT_IN_CONTAINER)/kong-license.json \ -e KONG_DNS_ORDER='LAST,A,SRV' \ --network='$(CONTAINER_CI_NETWORK_NAME)' \ '$(CONTAINER_CI_KONG_TOOLING_IMAGE_NAME)' @@ -148,7 +161,7 @@ CONTAINER_CI_KONG_SMOKE_TEST_RUN_SERVER := MSYS_NO_PATHCONV=1 $(DOCKER) run $(DO -e KONG_VITALS=off \ -e KONG_NGINX_HTTP_INCLUDE=/kong/smoke-test.nginx.conf \ -e KONG_DECLARATIVE_CONFIG=/kong/kong.yaml \ - -e KONG_LICENSE_PATH=/kong-plugin/kong-license.json \ + -e KONG_LICENSE_PATH=$(DOCKER_MOUNT_IN_CONTAINER)/kong-license.json \ -e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \ -e KONG_ADMIN_GUI_URL=http://localhost:8002/ \ --env-file .env \ @@ -178,7 +191,10 @@ $(ROCKSPEC_FILE): kong-plugin.rockspec # Rebuild the rock file every time the rockspec or the kong/**/.lua files change $(ROCK_FILE): container-ci-kong-tooling $(ROCKSPEC_FILE) $(PLUGIN_FILES) - $(CONTAINER_CI_KONG_TOOLING_RUN) sh -c '(cd /kong-plugin; luarocks make --pack-binary-rock --deps-mode none $(ROCKSPEC_FILE))' + $(CONTAINER_CI_KONG_TOOLING_RUN) sh -c '(cd $(DOCKER_MOUNT_IN_CONTAINER); luarocks make --pack-binary-rock --deps-mode none $(ROCKSPEC_FILE))' + +test-results: + mkdir -p $(TEST_RESULTS_PATH) .PHONY: tail-logs tail-logs: @@ -254,15 +270,21 @@ stop-services: stop-service-redis stop-service-openfga stop-service-postgres .PHONY: lint lint: container-ci-kong-tooling - $(CONTAINER_CI_KONG_TOOLING_RUN) sh -c '(cd /kong-plugin; luacheck .)' + $(CONTAINER_CI_KONG_TOOLING_RUN) sh -c '(cd $(DOCKER_MOUNT_IN_CONTAINER); luacheck --no-default-config --config .luacheckrc .)' .PHONY: format-code format-code: container-ci-kong-tooling - $(CONTAINER_CI_KONG_TOOLING_RUN) sh -c '(cd /kong-plugin; stylua --check . || stylua --verify .)' + $(CONTAINER_CI_KONG_TOOLING_RUN) sh -c '(cd $(DOCKER_MOUNT_IN_CONTAINER); stylua --check . || stylua --verify .)' .PHONY: test-unit -test-unit: container-ci-kong-tooling clean-servroot service-openfga - $(CONTAINER_CI_KONG_TOOLING_RUN) busted $(BUSTED_ARGS) /kong-plugin/spec +test-unit: clean-test-results test-results container-ci-kong-tooling clean-servroot service-openfga + $(CONTAINER_CI_KONG_TOOLING_RUN) busted $(BUSTED_ARGS) + @if [ -f $(TEST_RESULTS_PATH)/luacov.stats.out ]; then \ + $(CONTAINER_CI_KONG_TOOLING_RUN) sh -c '(cd $(DOCKER_MOUNT_IN_CONTAINER)/$(TEST_RESULTS_PATH); luacov-console $(DOCKER_MOUNT_IN_CONTAINER)/kong; luacov-console -s);' ;\ + $(CONTAINER_CI_KONG_TOOLING_RUN) sh -c '(cd $(DOCKER_MOUNT_IN_CONTAINER)/$(TEST_RESULTS_PATH); luacov -r html; mv luacov.report.out luacov.report.html);' ;\ + echo "Coverage report: file://$(PWD)/$(TEST_RESULTS_PATH)/luacov.report.html" ;\ + $(CONTAINER_CI_KONG_TOOLING_RUN) sh -c "(cd $(DOCKER_MOUNT_IN_CONTAINER)/$(TEST_RESULTS_PATH); luacov -r lcov; sed -i -e 's|/kong-plugin/||' -e 's/^\(DA:[0-9]\+,[0-9]\+\),[^,]*/\1/' luacov.report.out > lcov.info)" ;\ + fi .PHONY: tooling-shell tooling-shell: container-ci-kong-tooling @@ -284,8 +306,12 @@ smoke-test-run-test: container-network-ci .PHONY: lua-language-server-add-kong lua-language-server-add-kong: container-ci-kong-tooling -mkdir -p .luarocks - $(CONTAINER_CI_KONG_TOOLING_RUN) cp -r /usr/local/share/lua/5.1/. /kong-plugin/.luarocks - $(CONTAINER_CI_KONG_TOOLING_RUN) cp -r /kong /kong-plugin/.luarocks + $(CONTAINER_CI_KONG_TOOLING_RUN) cp -rv /usr/local/share/lua/5.1/. $(DOCKER_MOUNT_IN_CONTAINER)/.luarocks + $(CONTAINER_CI_KONG_TOOLING_RUN) cp -rv /kong $(DOCKER_MOUNT_IN_CONTAINER)/.luarocks + +.PHONY: clean-test-results +clean-test-results: + -$(RMDIR) test-results .PHONY: clean-servroot clean-servroot: @@ -328,6 +354,7 @@ clean-container-smoke-test-network: -$(DOCKER) network rm '$(CONTAINER_CI_NETWORK_NAME)' .PHONY: clean +clean: clean-test-results clean: clean-rock clean-rockspec clean: clean-servroot clean: clean-container-ci-kong-tooling clean-container-ci-kong-smoke-test clean-container-smoke-test-network diff --git a/_build/images/kong-plugin-testing-0.1.0-0.rockspec b/_build/images/kong-plugin-testing-0.1.0-0.rockspec index 230f850..7456904 100644 --- a/_build/images/kong-plugin-testing-0.1.0-0.rockspec +++ b/_build/images/kong-plugin-testing-0.1.0-0.rockspec @@ -14,6 +14,8 @@ dependencies = { "busted-hjtest = 0.0.5", "luacheck = 1.2.0", "luacov = 0.16.0", + "luacov-reporter-lcov = 0.2", + "luacov-console = 1.1.0", "lua-llthreads2 = 0.1.6", "http = 0.4", }