From 05648093f16fb8a4710891829bed8da3a2c61350 Mon Sep 17 00:00:00 2001 From: Victor Lyuboslavsky <2685025+getvictor@users.noreply.github.com> Date: Fri, 27 Feb 2026 07:53:57 -0600 Subject: [PATCH] Added dedicated Go test workflow for activity bounded context (#40653) --- .github/workflows/test-go-activity.yaml | 151 ++++++++++++++++++++++++ .github/workflows/test-go-suite.yaml | 12 ++ Makefile | 10 +- codecov.yml | 3 + 4 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/test-go-activity.yaml diff --git a/.github/workflows/test-go-activity.yaml b/.github/workflows/test-go-activity.yaml new file mode 100644 index 0000000000..962c690cd4 --- /dev/null +++ b/.github/workflows/test-go-activity.yaml @@ -0,0 +1,151 @@ +name: Go tests (activity) + +on: + push: + branches: + - main + - patch-* + - prepare-* + paths: + - 'server/activity/**.go' + - 'server/platform/**.go' + - 'server/contexts/**.go' + - 'server/ptr/**.go' + - 'go.mod' + - 'go.sum' + - '.github/workflows/test-go-activity.yaml' + - '.github/workflows/test-go-suite.yaml' + pull_request: + paths: + - 'server/activity/**.go' + - 'server/platform/**.go' + - 'server/contexts/**.go' + - 'server/ptr/**.go' + - 'go.mod' + - 'go.sum' + - '.github/workflows/test-go-activity.yaml' + - '.github/workflows/test-go-suite.yaml' + workflow_dispatch: # Manual + schedule: + - cron: '0 4 * * *' + +# This allows a subsequently queued workflow run to interrupt previous runs +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id}} + cancel-in-progress: true + +defaults: + run: + # fail-fast using bash -eo pipefail. See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference + shell: bash + +permissions: + contents: read + +jobs: + # ────────────────────────────────────────────────────────────────────────── + # Activity suite: always-run versions (every push/PR + cron). + # make sure to update supported versions docs when MySQL versions change + # ────────────────────────────────────────────────────────────────────────── + test-go-activity: + strategy: + matrix: + mysql: ["mysql:8.0.36", "mysql:9.5.0"] + uses: ./.github/workflows/test-go-suite.yaml + with: + suite: activity + mysql: ${{ matrix.mysql }} + cover_pkg: 'github.com/fleetdm/fleet/v4/server/activity/...' + generate_go: false + is_cron: ${{ github.event_name == 'schedule' }} + secrets: inherit + + # ────────────────────────────────────────────────────────────────────────── + # Extended MySQL coverage: only on the nightly cron schedule. + # Tests the same suite against older/intermediate versions. + # ────────────────────────────────────────────────────────────────────────── + test-go-activity-extended-mysql: + if: github.event_name == 'schedule' + strategy: + matrix: + mysql: ["mysql:8.0.32", "mysql:8.4.7"] + uses: ./.github/workflows/test-go-suite.yaml + with: + suite: activity + mysql: ${{ matrix.mysql }} + cover_pkg: 'github.com/fleetdm/fleet/v4/server/activity/...' + generate_go: false + is_cron: true + secrets: inherit + + # We upload all backend coverage in one step so that we're less likely to end up with a partial coverage report. + upload-coverage: + needs: [test-go-activity, test-go-activity-extended-mysql] + # Run even if extended-mysql was skipped (non-cron) or individual suites failed. + if: always() + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + with: + egress-policy: audit + + - name: Checkout Code + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Download artifacts + uses: actions/download-artifact@9c19ed7fe5d278cd354c7dfd5d3b88589c7e2395 # v4.1.6 + with: + pattern: '*-coverage' + - name: Upload to Codecov + uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + with: + token: ${{ secrets.CODECOV_TOKEN }} + flags: backend-activity + + # Our Go test suites are run with continue-on-error: true, so they don't contribute to the workflow pass/fail. + # This job explicitly checks if any Go test suites have failed and marks the overall workflow with the proper pass/fail status. + aggregate-result: + needs: [test-go-activity, test-go-activity-extended-mysql] + # Run even if extended-mysql was skipped (non-cron) or individual suites failed. + if: always() + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + with: + egress-policy: audit + + - name: Download artifacts + uses: actions/download-artifact@9c19ed7fe5d278cd354c7dfd5d3b88589c7e2395 # v4.1.6 + with: + pattern: '*-status' + + - name: Check for failures + run: | + failed_tests="" + status_count=0 + # Find all status files (they are in directories like 'activity-mysql8.0.36-status/status') + for status_file in $(find ./ -type f -name 'status'); do + status_count=$((status_count + 1)) + # Extract test name from parent directory (e.g., 'activity-mysql8.0.36-status') + test_dir=$(basename $(dirname "$status_file")) + # Remove '-status' suffix to get the test name + test_name="${test_dir%-status}" + status_content=$(cat "$status_file") + echo "Processing: $status_file (Test: $test_name) with status content: $status_content" + if grep -q "fail" "$status_file"; then + echo " ❌ Test failed: $test_name" + failed_tests="${failed_tests}${test_name}, " + else + echo " ✅ Test passed: $test_name" + fi + done + if [[ $status_count -eq 0 ]]; then + echo "❌ ERROR: No status files found! This indicates a workflow issue." + exit 1 + fi + if [[ -n "$failed_tests" ]]; then + echo "❌ One or more test jobs failed: ${failed_tests%, }" + exit 1 + fi + echo "✅ All test jobs succeeded." diff --git a/.github/workflows/test-go-suite.yaml b/.github/workflows/test-go-suite.yaml index 0076e1a462..977a10adad 100644 --- a/.github/workflows/test-go-suite.yaml +++ b/.github/workflows/test-go-suite.yaml @@ -14,6 +14,16 @@ on: required: false type: string default: '' + cover_pkg: + description: 'Go coverage package pattern (e.g., "github.com/fleetdm/fleet/v4/server/activity/..."). Defaults to all fleet packages.' + required: false + type: string + default: '' + generate_go: + description: 'Whether to run make generate-go before tests. Disable for suites that do not need generated static files.' + required: false + type: boolean + default: true is_cron: description: 'Whether this is a scheduled (cron) run. Enables race detector and longer timeouts.' required: false @@ -122,6 +132,7 @@ jobs: run: sudo apt update && sudo apt install -y zsh - name: Generate static files + if: ${{ inputs.generate_go }} run: | export PATH=$PATH:~/go/bin make generate-go @@ -233,6 +244,7 @@ jobs: AWS_REGION=us-east-1 \ NETWORK_TEST_GITHUB_TOKEN=${{ secrets.FLEET_RELEASE_GITHUB_PAT }} \ CI_TEST_PKG="${{ env.CI_TEST_PKG }}" \ + COVER_PKG="${{ inputs.cover_pkg || 'github.com/fleetdm/fleet/v4/...' }}" \ make test-go 2>&1 | tee /tmp/gotest.log - name: Save coverage diff --git a/Makefile b/Makefile index 152ef3c57c..2ca1ed02a6 100644 --- a/Makefile +++ b/Makefile @@ -261,6 +261,7 @@ dump-test-schema: test-schema # GO_TEST_EXTRA_FLAGS: Used to specify other arguments to `go test`. # GO_TEST_MAKE_FLAGS: Internal var used by other targets to add arguments to `go test`. PKG_TO_TEST := "" +COVER_PKG ?= github.com/fleetdm/fleet/v4/... go_test_pkg_to_test := $(addprefix ./,$(PKG_TO_TEST)) # set paths for packages to test dlv_test_pkg_to_test := $(addprefix github.com/fleetdm/fleet/v4/,$(PKG_TO_TEST)) # set URIs for packages to debug .run-go-tests: @@ -268,7 +269,7 @@ ifeq ($(PKG_TO_TEST), "") @echo "Please specify one or more packages to test. See '$(TOOL_CMD) help run-go-tests' for more info."; else @echo Running Go tests with command: - go test -tags full,fts5,netgo -run=${TESTS_TO_RUN} ${GO_TEST_MAKE_FLAGS} ${GO_TEST_EXTRA_FLAGS} -parallel 8 -coverprofile=coverage.txt -covermode=atomic -coverpkg=github.com/fleetdm/fleet/v4/... $(go_test_pkg_to_test) + go test -tags full,fts5,netgo -run=${TESTS_TO_RUN} ${GO_TEST_MAKE_FLAGS} ${GO_TEST_EXTRA_FLAGS} -parallel 8 -coverprofile=coverage.txt -covermode=atomic -coverpkg=$(COVER_PKG) $(go_test_pkg_to_test) endif # This is the base command to debug Go tests. @@ -330,6 +331,7 @@ MYSQL_PKGS_TO_TEST := ./server/datastore/mysql/... SCRIPTS_PKGS_TO_TEST := ./orbit/pkg/scripts SERVICE_PKGS_TO_TEST := ./server/service VULN_PKGS_TO_TEST := ./server/vulnerabilities/... +ACTIVITY_PKGS_TO_TEST := ./server/activity/... ifeq ($(CI_TEST_PKG), main) # This is the bucket of all the tests that are not in a specific group. We take a diff between DEFAULT_PKG_TO_TEST and all the specific *_PKGS_TO_TEST. CI_PKG_TO_TEST=$(shell /bin/bash -c "comm -23 <(go list ${DEFAULT_PKGS_TO_TEST} | sort) <({ \ @@ -338,7 +340,8 @@ ifeq ($(CI_TEST_PKG), main) go list $(MYSQL_PKGS_TO_TEST) && \ go list $(SCRIPTS_PKGS_TO_TEST) && \ go list $(SERVICE_PKGS_TO_TEST) && \ - go list $(VULN_PKGS_TO_TEST) \ + go list $(VULN_PKGS_TO_TEST) && \ + go list $(ACTIVITY_PKGS_TO_TEST) \ ;} | sort) | sed -e 's|github.com/fleetdm/fleet/v4/||g'") else ifeq ($(CI_TEST_PKG), fast) CI_PKG_TO_TEST=$(FAST_PKGS_TO_TEST) @@ -352,6 +355,8 @@ else ifeq ($(CI_TEST_PKG), service) CI_PKG_TO_TEST=$(SERVICE_PKGS_TO_TEST) else ifeq ($(CI_TEST_PKG), vuln) CI_PKG_TO_TEST=$(VULN_PKGS_TO_TEST) +else ifeq ($(CI_TEST_PKG), activity) + CI_PKG_TO_TEST=$(ACTIVITY_PKGS_TO_TEST) else CI_PKG_TO_TEST=$(DEFAULT_PKGS_TO_TEST) endif @@ -371,6 +376,7 @@ endif @echo " mysql" @echo " fleetctl" @echo " vuln" + @echo " activity" @echo " main (all tests not included in other bundles)" test-go: make .run-go-tests PKG_TO_TEST="$(CI_PKG_TO_TEST)" diff --git a/codecov.yml b/codecov.yml index 43499025e2..bb7ad25d8d 100644 --- a/codecov.yml +++ b/codecov.yml @@ -19,6 +19,9 @@ flag_management: - server/ - ee/ - orbit/ + - name: backend-activity + paths: + - server/activity/ - name: frontend paths: - frontend/