Skip to content

CI pipelines: deploy markers, test results and scans

From a CI job, the shield360 CLI can:

  • Record a deploy marker (shield360 ci release). This is a shield360.deploy span that carries the app, its release (service.version), the environment, the commit and the CI run’s URL.
  • Send test results (shield360 ci tests). It reads JUnit XML reports and sends them as one trace: a span for the run, a span for each suite and a span for each test case (at most 5,000), with the OpenTelemetry test.* attributes.
  • Scan the code (shield360 scan). It covers dependencies, misconfigurations and secrets. See shield360 scan for its flags, such as --fail-on high.

Every command sends to your project with an API key. Create one in Settings → API keys and store it as a CI secret named SHIELD360_API_KEY. Never write the key in a workflow file.

Use the Shield360 CI action, ThinkfleetAI/shield360-action@v1. The v1 tag moves with compatible releases; pin v1.0.0 or a commit SHA if you prefer a fixed version.

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm test -- --reporters=default --reporters=jest-junit
- uses: ThinkfleetAI/shield360-action@v1
if: always() # send results when tests fail too
with:
api-key: ${{ secrets.SHIELD360_API_KEY }}
url: https://app.shield360.ai
app: checkout
test-results: junit.xml
scan: true
deploy:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./deploy.sh
- uses: ThinkfleetAI/shield360-action@v1
with:
api-key: ${{ secrets.SHIELD360_API_KEY }}
app: checkout
environment: production
release: true
InputDefaultMeaning
api-keyrequiredThe project’s API key, from a secret
urlhttps://app.shield360.aiYour Shield360 URL
apppackage.json or pyproject.toml name, else the directory nameThe app’s name in Shield360
environmentproduction for release, ci for test resultsThe environment
versionThe tag, else the commit’s first 12 charactersThe release
releasefalseRecord a deploy marker
release-descriptionA short note on the release
test-resultsJUnit XML paths or globs, separated by spaces or new lines (** matches any depth)
failure-messagesfalseAlso send failure messages, secret-redacted and cut to 1,000 characters
scanfalseRun shield360 scan
scan-argsExtra arguments for shield360 scan, separated by spaces
working-directory.Where the commands run

The action installs the CLI from your Shield360 server with the same checked install script as Install the CLI. It works on Linux, macOS and Windows runners.

variables:
SHIELD360_URL: https://app.shield360.ai
# SHIELD360_API_KEY: set it in Settings → CI/CD → Variables, masked and protected
.shield360: &shield360
- curl -fsSL "$SHIELD360_URL/api/cli/install-cli.sh" | sh
- export PATH="$HOME/.shield360/bin:$PATH"
test:
script:
- npm ci && npm test
after_script:
- *shield360
- shield360 ci tests junit.xml --app checkout
artifacts:
reports:
junit: junit.xml
deploy:
stage: deploy
script:
- ./deploy.sh
- *shield360
- shield360 ci release --app checkout --env production

after_script runs when the tests fail too. The CLI reads the commit, branch or tag, and pipeline URL from GitLab’s own variables (CI_COMMIT_SHA, CI_COMMIT_REF_NAME, CI_COMMIT_TAG, CI_PIPELINE_URL).

Install the CLI, set SHIELD360_URL and SHIELD360_API_KEY, and run the same commands:

Terminal window
curl -fsSL https://app.shield360.ai/api/cli/install-cli.sh | sh
shield360 ci tests 'build/test-results/**/*.xml' --app orders --version "$GIT_COMMIT"
shield360 ci release --app orders --version 2.4.0 --env staging

Outside GitHub Actions and GitLab CI, pass --version, because no commit is detected.

CommandSpanAttributes
ci releaseshield360.deployservice.name, service.version, deployment.environment, vcs.ref.head.revision, vcs.ref.head.name, cicd.pipeline.run.url.full, shield360.deploy.description
ci testsshield360.test.run, then one span per suite and per casetest.suite.name, test.suite.run.status, test.case.name, test.case.result.status, error.type, code.file.path, and the run’s totals (shield360.test.total, passed, failed, skipped)

The CLI never sends standard output or standard error captured in a report. It sends failure messages only with --failure-messages. ci tests exits 0 once the results are sent, even when tests failed, so your test step stays the one that fails the build. Find the spans in Traces: filter on the app and on span name shield360.test.run or shield360.deploy.