Clean up setup experience cancellation behavior #33871
Workflow file for this run
This file contains hidden or 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: Go Tests | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - patch-* | |
| - prepare-* | |
| paths: | |
| - '**.go' | |
| - 'go.mod' | |
| - 'go.sum' | |
| - '.github/workflows/test-go.yaml' | |
| - '.github/workflows/test-go-suite.yaml' | |
| - 'tools/osquery/in-a-box/docker-compose.yml' | |
| - 'tools/osquery/in-a-box/osquery/docker-compose.yml' | |
| - 'server/authz/policy.rego' | |
| - 'docker-compose.yml' | |
| - 'frontend/templates/enroll-ota.html' | |
| - 'frontend/templates/windowsTOS.html' | |
| pull_request: | |
| paths: | |
| - '**.go' | |
| - 'go.mod' | |
| - 'go.sum' | |
| - '.github/workflows/test-go.yaml' | |
| - '.github/workflows/test-go-suite.yaml' | |
| - 'tools/osquery/in-a-box/docker-compose.yml' | |
| - 'tools/osquery/in-a-box/osquery/docker-compose.yml' | |
| - 'server/authz/policy.rego' | |
| - 'docker-compose.yml' | |
| - 'frontend/templates/enroll-ota.html' | |
| - 'frontend/templates/windowsTOS.html' | |
| 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: | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Suites that do NOT need MySQL: run once with no database dimension. | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| test-go-no-db: | |
| strategy: | |
| matrix: | |
| suite: ["fast", "scripts"] | |
| uses: ./.github/workflows/test-go-suite.yaml | |
| with: | |
| suite: ${{ matrix.suite }} | |
| is_cron: ${{ github.event_name == 'schedule' }} | |
| secrets: inherit | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Suites that need MySQL: always-run versions (every push/PR + cron). | |
| # make sure to update supported versions docs when MySQL versions change | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| test-go: | |
| strategy: | |
| matrix: | |
| suite: ["integration-core", "integration-enterprise", "integration-mdm", "fleetctl", "main", "mysql", "service", "vuln"] | |
| mysql: ["mysql:8.0.44", "mysql:9.5.0"] | |
| uses: ./.github/workflows/test-go-suite.yaml | |
| with: | |
| suite: ${{ matrix.suite }} | |
| mysql: ${{ matrix.mysql }} | |
| is_cron: ${{ github.event_name == 'schedule' }} | |
| secrets: inherit | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Extended MySQL coverage: only on the nightly cron schedule. | |
| # Tests the same DB-dependent suites against older/intermediate versions. | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| test-go-extended-mysql: | |
| if: github.event_name == 'schedule' | |
| strategy: | |
| matrix: | |
| suite: ["integration-core", "integration-enterprise", "integration-mdm", "fleetctl", "main", "mysql", "service", "vuln"] | |
| mysql: ["mysql:8.0.42", "mysql:8.4.8"] | |
| uses: ./.github/workflows/test-go-suite.yaml | |
| with: | |
| suite: ${{ matrix.suite }} | |
| mysql: ${{ matrix.mysql }} | |
| is_cron: true | |
| secrets: inherit | |
| # Based on https://github.com/micromdm/nanomdm/blob/main/.github/workflows/on-push-pr.yml#L87 | |
| test-go-nanomdm: | |
| runs-on: 'ubuntu-latest' | |
| services: | |
| mysql: | |
| image: mysql:8.0.44 | |
| env: | |
| MYSQL_RANDOM_ROOT_PASSWORD: yes | |
| MYSQL_DATABASE: testdb | |
| MYSQL_USER: testuser | |
| MYSQL_PASSWORD: testpw | |
| ports: | |
| - 3800:3306 | |
| options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3 | |
| env: | |
| MYSQL_PWD: testpw | |
| PORT: 3800 | |
| RACE_ENABLED: true | |
| GO_TEST_TIMEOUT: 20m | |
| 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: Install Go | |
| uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 | |
| with: | |
| go-version-file: 'go.mod' | |
| - name: Install gotestsum | |
| run: go install gotest.tools/gotestsum@latest | |
| - name: verify mysql | |
| run: | | |
| while ! mysqladmin ping --host=localhost --port=$PORT --protocol=TCP --silent; do | |
| sleep 1 | |
| done | |
| - name: mysql schema | |
| run: | | |
| mysql --version | |
| mysql --user=testuser --host=localhost --port=$PORT --protocol=TCP testdb < ./server/mdm/nanomdm/storage/mysql/schema.sql | |
| - name: set test dsn | |
| run: echo "NANOMDM_MYSQL_STORAGE_TEST_DSN=testuser:testpw@tcp(localhost:$PORT)/testdb" >> $GITHUB_ENV | |
| - name: Run Go tests | |
| run: | | |
| gotestsum --format=testdox --jsonfile=/tmp/test-output.json -- \ | |
| -v -parallel 8 -race=$RACE_ENABLED -timeout=$GO_TEST_TIMEOUT \ | |
| -coverprofile=coverage.txt -covermode=atomic -coverpkg=github.com/fleetdm/fleet/v4/server/mdm/nanomdm/... \ | |
| ./server/mdm/nanomdm/storage/mysql 2>&1 | tee /tmp/gotest.log | |
| - name: Save coverage | |
| uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 | |
| with: | |
| name: nanomdm-coverage | |
| path: ./coverage.txt | |
| if-no-files-found: error | |
| - name: Generate summary of errors | |
| if: failure() | |
| run: | | |
| c1grep() { grep "$@" || test $? = 1; } | |
| c1grep -oP 'FAIL: .*$' /tmp/gotest.log > /tmp/summary.txt | |
| c1grep 'test timed out after' /tmp/gotest.log >> /tmp/summary.txt | |
| c1grep 'fatal error:' /tmp/gotest.log >> /tmp/summary.txt | |
| c1grep -A 10 'panic: runtime error: ' /tmp/gotest.log >> /tmp/summary.txt | |
| c1grep ' FAIL\t' /tmp/gotest.log >> /tmp/summary.txt | |
| GO_FAIL_SUMMARY=$(head -n 5 /tmp/summary.txt | sed ':a;N;$!ba;s/\n/\\n/g') | |
| echo "GO_FAIL_SUMMARY=$GO_FAIL_SUMMARY" | |
| if [[ -z "$GO_FAIL_SUMMARY" ]]; then | |
| GO_FAIL_SUMMARY="unknown, please check the build URL" | |
| fi | |
| GO_FAIL_SUMMARY=$GO_FAIL_SUMMARY envsubst < .github/workflows/config/slack_payload_template.json > ./payload.json | |
| - name: Slack Notification | |
| if: github.event.schedule == '0 4 * * *' && failure() | |
| uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 | |
| with: | |
| payload-file-path: ./payload.json | |
| env: | |
| JOB_STATUS: ${{ job.status }} | |
| EVENT_URL: ${{ github.event.pull_request.html_url || github.event.head.html_url }} | |
| RUN_URL: https://github.com/fleetdm/fleet/actions/runs/${{ github.run_id }}\n${{ github.event.pull_request.html_url || github.event.head.html_url }} | |
| SLACK_WEBHOOK_URL: ${{ secrets.SLACK_G_HELP_ENGINEERING_WEBHOOK_URL }} | |
| SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK | |
| - name: Upload test log | |
| if: always() | |
| uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 | |
| with: | |
| name: nanomdm-test-log | |
| path: /tmp/gotest.log | |
| if-no-files-found: error | |
| - name: Upload summary test log | |
| if: always() | |
| uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 | |
| with: | |
| name: nanomdm-summary-test-log | |
| path: /tmp/summary.txt | |
| - name: Upload JSON test output | |
| if: always() | |
| uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 | |
| with: | |
| name: nanomdm-test-json | |
| path: /tmp/test-output.json | |
| if-no-files-found: warn | |
| # We upload all backend coverage in one step so that we're less like to end up in a situation with a partial coverage report. | |
| upload-coverage: | |
| needs: [test-go-no-db, test-go, test-go-extended-mysql, test-go-nanomdm] | |
| # 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 | |
| # 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-no-db, test-go, test-go-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 'fleetctl-mysql8.0.44-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., 'fleetctl-mysql8.0.44-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." |