Skip to content

feat: Add GitHub Actions CI workflow with unit and categorized integ(AST-222) #531

feat: Add GitHub Actions CI workflow with unit and categorized integ(AST-222)

feat: Add GitHub Actions CI workflow with unit and categorized integ(AST-222) #531

Workflow file for this run

name: Continuous Integration Tests
on:
pull_request:
jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 #v4.0.0
- name: Set up Go version
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 #v4
with:
go-version-file: go.mod
- run: go version
- name: go test with coverage
run: |
sudo chmod +x ./internal/commands/.scripts/up.sh
./internal/commands/.scripts/up.sh
- name: Check if total coverage is greater then 77.7
shell: bash
run: |
CODE_COV=$(go tool cover -func cover.out | grep total | awk '{print substr($3, 1, length($3)-1)}')
EXPECTED_CODE_COV=77.7
var=$(awk 'BEGIN{ print "'$CODE_COV'"<"'$EXPECTED_CODE_COV'" }')
if [ "$var" -eq 1 ];then
echo "Your code coverage is too low. Coverage precentage is: $CODE_COV"
exit 1
else
echo "Your code coverage test passed! Coverage precentage is: $CODE_COV"
exit 0
fi
integration-tests:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
# Group 1: Scan creation and management tests (largest group, uses getRootProject)
- group: scan-create
name: "Scan Creation"
pattern: "^Test(CreateScan|ScanCreate|Scan_|ScanTypeApi|ValidateScanTypes|ScanGenerating|ScanWithPolicy|ScanList|ScanTimeout|ScanASCA|ExecuteASCAScan)"
# Group 2: Scan operations - E2E, incremental, cancel, filters
- group: scan-ops
name: "Scan Operations"
pattern: "^Test(ScansE2E|ScansUpdate|FastScan|LightQueries|RecommendedExclusions|IncrementalScan|BranchPrimary|CancelScan|ScanCreateInclude|ScanCreateWith|ScanCreateIgnore|ScanCreateFilter|ScanWorkflow|ScanLogs|InvalidSource|ScanShow|RequiredScan|ScaResolver|BrokenLink|PartialScan|FailedScan|RunKics|RunSca|ScanGLReport)"
# Group 3: Results and reports tests (uses getRootScan - read-only)
- group: results
name: "Results & Reports"
pattern: "^Test(Result|CodeBashing|RiskManagement)"
# Group 4: PR decoration tests (uses getRootScan)
- group: pr-decoration
name: "PR Decoration"
pattern: "^TestPR"
# Group 5: Project management tests
- group: projects
name: "Projects"
pattern: "^Test(Project|CreateEmpty|CreateAlready)"
# Group 6: Predicates and BFL tests (uses getRootScan)
- group: predicates
name: "Predicates & BFL"
pattern: "^Test(Predicate|Bfl|Triage)"
# Group 7: Container-specific tests (from scan_test.go and container files)
- group: containers
name: "Container Tests"
pattern: "^Test(Container|EmptyFolder|ImagesValidation|EdgeCase)"
# Group 8: Realtime scanning tests (IaC, OSS, Secrets, ASCA) and engine tests
- group: realtime
name: "Realtime Scanning"
pattern: "^Test(IacRealtime|OssRealtime|Secrets_Realtime|Containers_Realtime|EngineNameResolution)"
# Group 9: Auth, config, tenant, root tests
- group: auth-config
name: "Auth & Config"
pattern: "^Test(Auth|Config|Tenant|Root|Log|SetLog|FeatureFlag|RateLimit|FailProxy)"
# Group 10: SCM user count tests (GitHub, GitLab, Azure, Bitbucket)
- group: user-count
name: "User Count"
pattern: "^Test(GitHub|GitLab|Azure|Bitbucket)(UserCount|Count)"
# Group 11: Misc tests (chat, import, telemetry, remediation, pre-commit, pre-receive)
- group: misc
name: "Miscellaneous"
pattern: "^Test(Chat|Import|Learn|Telemetry|Mask|Sca?Remediation|Kics?Remediation|PreCommit|Pre_?Receive|Pre_Receive|Get)"
name: Integration - ${{ matrix.name }}
steps:
- name: Checkout the repository
uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 #v4.0.0
- name: Set up Go version
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 #v4
with:
go-version-file: go.mod
- run: go version
- name: Go Build
run: go build -o ./bin/cx ./cmd
- name: Start Squid proxy
run: |
docker run \
--name squid \
-d \
-p 3128:3128 \
-v $(pwd)/internal/commands/.scripts/squid/squid.conf:/etc/squid/squid.conf \
-v $(pwd)/internal/commands/.scripts/squid/passwords:/etc/squid/passwords \
ubuntu/squid:5.2-22.04_beta
- name: Download ScaResolver
run: |
wget https://sca-downloads.s3.amazonaws.com/cli/latest/ScaResolver-linux64.tar.gz
tar -xzvf ScaResolver-linux64.tar.gz -C /tmp
rm -rf ScaResolver-linux64.tar.gz
- name: Run ${{ matrix.name }} tests
shell: bash
env:
CX_BASE_URI: ${{ secrets.CX_BASE_URI }}
CX_CLIENT_ID: ${{ secrets.CX_CLIENT_ID }}
CX_CLIENT_SECRET: ${{ secrets.CX_CLIENT_SECRET }}
CX_BASE_AUTH_URI: ${{ secrets.CX_BASE_AUTH_URI }}
CX_AST_USERNAME: ${{ secrets.CX_AST_USERNAME }}
CX_AST_PASSWORD: ${{ secrets.CX_AST_PASSWORD }}
CX_APIKEY: ${{ secrets.CX_APIKEY }}
CX_TENANT: ${{ secrets.CX_TENANT }}
CX_SCAN_SSH_KEY: ${{ secrets.CX_SCAN_SSH_KEY }}
CX_ORIGIN: "cli-tests"
PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
PROXY_HOST: localhost
PROXY_PORT: 3128
PROXY_USERNAME: ${{ secrets.PROXY_USER }}
PROXY_PASSWORD: ${{ secrets.PROXY_PASSWORD }}
PR_GITHUB_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
PR_GITHUB_NAMESPACE: "checkmarx"
PR_GITHUB_REPO_NAME: "ast-cli"
PR_GITHUB_NUMBER: 983
PR_GITLAB_TOKEN: ${{ secrets.PR_GITLAB_TOKEN }}
PR_GITLAB_NAMESPACE: ${{ secrets.PR_GITLAB_NAMESPACE }}
PR_GITLAB_REPO_NAME: ${{ secrets.PR_GITLAB_REPO_NAME }}
PR_GITLAB_PROJECT_ID: ${{ secrets.PR_GITLAB_PROJECT_ID }}
PR_GITLAB_IID: ${{ secrets.PR_GITLAB_IID }}
AZURE_ORG: ${{ secrets.AZURE_ORG }}
AZURE_PROJECT: ${{ secrets.AZURE_PROJECT }}
AZURE_REPOS: ${{ secrets.AZURE_REPOS }}
AZURE_TOKEN: ${{ secrets.AZURE_TOKEN }}
AZURE_PR_NUMBER: 1
BITBUCKET_WORKSPACE: ${{ secrets.BITBUCKET_WORKSPACE }}
BITBUCKET_REPOS: ${{ secrets.BITBUCKET_REPOS }}
BITBUCKET_USERNAME: ${{ secrets.BITBUCKET_USERNAME }}
BITBUCKET_PASSWORD: ${{ secrets.BITBUCKET_PASSWORD }}
GITLAB_TOKEN: ${{ secrets.GITLAB_TOKEN }}
GITHUB_ACTOR: ${{ github.actor }}
PR_BITBUCKET_TOKEN: ${{ secrets.PR_BITBUCKET_TOKEN }}
PR_BITBUCKET_NAMESPACE: "AstSystemTest"
PR_BITBUCKET_REPO_NAME: "cliIntegrationTest"
PR_BITBUCKET_ID: 1
run: |
set -o pipefail # Preserve exit code from go test, not tee
echo "Running test group: ${{ matrix.name }}"
echo "Pattern: ${{ matrix.pattern }}"
# Run tests matching the pattern with coverage
go test \
-tags integration \
-v \
-timeout 90m \
-run "${{ matrix.pattern }}" \
-coverpkg github.com/checkmarx/ast-cli/internal/commands,github.com/checkmarx/ast-cli/internal/services,github.com/checkmarx/ast-cli/internal/wrappers \
-coverprofile cover-${{ matrix.group }}.out \
github.com/checkmarx/ast-cli/test/integration 2>&1 | tee test_output_${{ matrix.group }}.log
# Check for failed tests and rerun them once
if grep -q "^--- FAIL:" test_output_${{ matrix.group }}.log; then
echo "Some tests failed, attempting rerun..."
FAILED_TESTS=$(grep -E "^--- FAIL: " test_output_${{ matrix.group }}.log | awk '{print $3}' | tr '\n' '|' | sed 's/|$//')
if [ -n "$FAILED_TESTS" ]; then
echo "Rerunning failed tests: $FAILED_TESTS"
go test \
-tags integration \
-v \
-timeout 30m \
-run "^($FAILED_TESTS)$" \
-coverpkg github.com/checkmarx/ast-cli/internal/commands,github.com/checkmarx/ast-cli/internal/services,github.com/checkmarx/ast-cli/internal/wrappers \
-coverprofile cover-${{ matrix.group }}-rerun.out \
github.com/checkmarx/ast-cli/test/integration
fi
fi
- name: Stop Squid proxy
if: always()
run: docker stop squid || true && docker rm squid || true
- name: Upload coverage artifact
uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 #v4
with:
name: coverage-${{ matrix.group }}
path: cover-*.out
- name: Upload test logs
if: always()
uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 #v4
with:
name: test-logs-${{ matrix.group }}
path: test_output_*.log
merge-coverage:
runs-on: ubuntu-latest
needs: integration-tests
steps:
- name: Checkout the repository
uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 #v4.0.0
- name: Set up Go version
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 #v4
with:
go-version-file: go.mod
- name: Install gocovmerge
run: go install github.com/wadey/gocovmerge@latest
- name: Download all coverage artifacts
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 #v4
with:
pattern: coverage-*
path: coverage-files
merge-multiple: true
- name: Merge coverage files
run: |
echo "Merging coverage files..."
ls -la coverage-files/
gocovmerge coverage-files/cover-*.out > cover.out
go tool cover -html=cover.out -o coverage.html
- name: Coverage report
uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 #v4
with:
name: ${{ runner.os }}-coverage-latest
path: coverage.html
- name: Check if total coverage is greater then 75
shell: bash
run: |
CODE_COV=$(go tool cover -func cover.out | grep total | awk '{print substr($3, 1, length($3)-1)}')
EXPECTED_CODE_COV=75
var=$(awk 'BEGIN{ print "'$CODE_COV'"<"'$EXPECTED_CODE_COV'" }')
if [ "$var" -eq 1 ];then
echo "Your code coverage is too low. Coverage precentage is: $CODE_COV"
exit 1
else
echo "Your code coverage test passed! Coverage precentage is: $CODE_COV"
exit 0
fi
- name: Run cleandata to clean up projects
env:
CX_BASE_URI: ${{ secrets.CX_BASE_URI }}
CX_CLIENT_ID: ${{ secrets.CX_CLIENT_ID }}
CX_CLIENT_SECRET: ${{ secrets.CX_CLIENT_SECRET }}
CX_BASE_AUTH_URI: ${{ secrets.CX_BASE_AUTH_URI }}
CX_APIKEY: ${{ secrets.CX_APIKEY }}
CX_TENANT: ${{ secrets.CX_TENANT }}
run: |
go test -v github.com/checkmarx/ast-cli/test/cleandata || true
lint:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 #v4.0.0
- name: Set up Go version
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 #v4
with:
go-version-file: go.mod
- run: go version
- run: go mod tidy
- name: golangci-lint
uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc #v3
with:
skip-pkg-cache: true
version: v1.64.2
args: -c .golangci.yml
--timeout 5m
only-new-issues: true
govulncheck:
runs-on: ubuntu-latest
name: govulncheck
steps:
- id: govulncheck
uses: golang/govulncheck-action@7da72f730e37eeaad891fcff0a532d27ed737cd4 #v1
continue-on-error: true
with:
go-version-file: go.mod
go-package: ./...
checkDockerImage:
runs-on: ubuntu-latest
name: scan Docker Image with Trivy
steps:
- name: Checkout code
uses: actions/checkout@722adc63f1aa60a57ec37892e133b1d319cae598 #2.0.0
- name: Set up Docker
uses: docker/setup-buildx-action@cf09c5c41b299b55c366aff30022701412eb6ab0 #v1.0.0
- name: Log in to Docker Hub
uses: docker/login-action@49ed152c8eca782a232dede0303416e8f356c37b #v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build the project
run: go build -o ./cx ./cmd
- name: Build Docker image
run: docker build -t ast-cli:${{ github.sha }} .
- name: Run Trivy scanner without downloading DBs
uses: aquasecurity/trivy-action@915b19bbe73b92a6cf82a1bc12b087c9a19a5fe2 #v0.28.0
with:
scan-type: 'image'
image-ref: ast-cli:${{ github.sha }}
format: 'table'
exit-code: '1'
ignore-unfixed: true
vuln-type: 'os,library'
output: './trivy-image-results.txt'
env:
TRIVY_SKIP_JAVA_DB_UPDATE: true
- name: Inspect action report
if: always()
shell: bash
run: cat ./trivy-image-results.txt