CI/CD Integration
Skylos fits into CI in three different ways. The right choice depends on whether you want local-only exit codes, cloud-managed policy, or GitHub-native hard enforcement.
Here, local-only means the analysis runs on the CI worker without a Skylos Cloud upload. It does not promise an offline run: dependency checks can query OSV or package registries, and direct image scans contact a registry through Trivy.
Choose a CI Mode
| Goal | Use this | Notes |
|---|---|---|
| Local-only CI gate | skylos . --danger --secrets --quality --ai-defects --gate | Explicit analyzers; no cloud state required |
| Kubernetes or GPU source/build proof | skylos . --select RULES --gate | Exact source/config correlation with an independent Reliability threshold |
| Built GPU artifact gate | skylos preflight build/app | Exact artifact report: exit 0 PASS, 1 FAIL, 2 UNKNOWN |
| Workflow security review | skylos . --danger | Scans .github/workflows/* and local action metadata |
| Cloud upload with dashboard policy | skylos . --upload | Uses project policy, suppressions, and cloud history |
| Cloud gate in one line on other CI systems | skylos cloud --gate | Every check, upload, and exit 1 when the Skylos Cloud gate fails; set SKYLOS_TOKEN |
| GitHub required checks | skylos cicd init plus branch protection | PR quality gate and Done run without Cloud credentials; the GitHub App provides a separate Cloud-managed PR gate |
GitHub Actions Workflow Security
skylos . --danger also scans GitHub Actions workflows and local action
metadata. It flags CI/CD supply-chain risks such as privileged triggers, broad
GITHUB_TOKEN permissions, unpinned actions, unsafe checkout credentials,
template injection, secret overexposure, mutable containers, OIDC release risk,
and missing timeouts on privileged jobs.
The same --danger invocation also runs deployment/runtime contract analysis.
Kubernetes and GPU results whose category is Reliability stay in the separate
reliability JSON bucket and gate threshold; they do not inflate Security
counts. JSON output, uploads, GitHub annotations, and PR review formatting
preserve this category.
See GitHub Actions Security for setup guidance and the full scanner scope.
--danger also checks .gitlab-ci.yml for GitLab CI misconfigurations
(SKY-D314 to SKY-D323 in the rules reference), plus
Dependabot config, Dockerfiles, Docker Compose files and systemd units.
It does not parse Jenkins, CircleCI, Bitbucket Pipelines, Azure Pipelines or Buildkite configuration for misconfiguration rules. Those CIs still run the Skylos pull request gate; see Other CI Providers.
GitHub Actions with OIDC
Run PR scans and tests without Cloud credentials. Upload full scans only on pushes to the default branch, using GitHub OIDC. Generate this workflow with:
python -m pip install --upgrade "skylos>=4.46.0"
skylos cicd init
The onboarding generator, Done discovery and options below require Skylos
4.46.0 or newer. Skylos 4.45.0 does not include this generated workflow or
the --no-upload, --done and --default-branch options.
See the first gated PR guide
for setup and branch protection. Use skylos cicd init --no-upload if you
do not use Cloud.
Preconditions:
- the Skylos project is bound to the GitHub repository
- the Skylos GitHub App is installed on that repository
- only the default-branch upload job has
id-token: write
The example below assumes a Python project with pytest and one Cloud project
for the repository. Replace main with your default branch and edit the Done
dependency step for your project. Use the App's per-root workflow for multiple
monorepo projects.
skylos cicd init detects your branch and whether to add Done automatically.
name: Skylos Analysis
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
skylos:
if: github.event_name == 'pull_request'
name: Skylos Quality Gate
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
with:
python-version: '3.12'
- run: python -I -m pip install "skylos>=4.46.0"
- name: Scan changed code
run: |
pr_base_ref="origin/$GITHUB_BASE_REF"
skylos . --danger --secrets --quality --ai-defects --sca --no-upload --diff-base "$pr_base_ref" --diff "$pr_base_ref" --json -o skylos-results.json
- name: Quality gate
if: always()
run: skylos cicd gate --input skylos-results.json --summary
done:
if: github.event_name == 'pull_request'
name: Skylos Done
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
with:
python-version: '3.12'
- run: python -I -m pip install "skylos>=4.46.0"
- name: Install project test dependencies
run: python -I -m pip install -e . pytest
- name: Run tests and check the change is finished
run: skylos done --base "origin/$GITHUB_BASE_REF"
cloud-upload:
if: github.event_name == 'push' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
name: Skylos Cloud upload
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
with:
python-version: '3.12'
- run: python -I -m pip install "skylos>=4.46.0"
- run: skylos sync pull
- run: skylos . --danger --secrets --quality --ai-defects --sca --upload
env:
SKYLOS_COMMIT: ${{ github.sha }}
SKYLOS_BRANCH: ${{ github.ref_name }}
The generated workflow also adds annotations and PR review comments. The
example above shows the scan, test and upload jobs without those optional
reporting steps. When dependency checks (--sca) are selected, a workflow
generated by a Skylos version that has --review-upgrades also passes it to
the pull request scan, so each upgraded npm or PyPI package is compared with
its previous release (see Upgrade Review).
Done reads its settings from the base branch, runs your
tests, and writes a receipt to the job summary. A skipped or unfinished
blocking check cannot pass.
The GitHub App's Cloud-managed PR workflow is a separate path. It scans PR code in an unprivileged job, then publishes through an isolated trusted job. Adding OIDC permission or a stored token to an ordinary PR test job does not turn it into that workflow.
In the App-generated Done job, Python test dependencies share the scanner's
Python environment. Keep them compatible with the selected Skylos version;
the job stops before Done runs if installation replaces that version. If your
Python build backend creates local artifacts such as *.egg-info/, add
narrow patterns to the reviewed base .gitignore before requiring the check.
The clean-checkout guard still rejects source changes; do not ignore all
untracked files to make a receipt pass.
The App workflow uses pull_request_target. GitHub's default event
policy
applies to public repositories without an existing applicable event policy.
It currently evaluates this trigger; enforcement starts November 2, 2026
for affected repositories using that default policy before general
availability. Check that your applicable policy permits the App workflow
before requiring its check.
How OIDC works:
- GitHub Actions issues a short-lived OIDC token
- Skylos verifies it
- Cloud verifies the repository and App binding, then resolves the project, using the project subpath when supplied
- the upload proceeds with no
SKYLOS_TOKEN
OIDC failure modes
OIDC upload fails when:
- no project matches the verified repository and requested project subpath
- several projects match because the request omits a subpath or duplicates exist for that repository and subpath
- the GitHub App is not installed on the repository
- the upload job is missing
id-token: write - an ordinary PR job tries to upload instead of a default-branch push job
GitHub Actions with SKYLOS_TOKEN
Use this for explicit secret management. Keep the stored token in a trusted
default-branch upload job; PR scans and tests do not need it. A local API key
upload is stored as unverified and cannot pass the Cloud GitHub gate.
Put SKYLOS_TOKEN in a GitHub environment named skylos-security and
restrict that environment to your default branch.
name: Skylos Cloud upload
on:
push:
branches: [main]
permissions:
contents: read
jobs:
cloud-upload:
if: github.event_name == 'push' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
runs-on: ubuntu-latest
timeout-minutes: 15
environment: skylos-security
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
with:
python-version: '3.12'
- run: python -I -m pip install skylos
- name: Run Skylos
env:
SKYLOS_TOKEN: ${{ secrets.SKYLOS_TOKEN }}
run: skylos . --danger --secrets --quality --ai-defects --upload
Replace main with your default branch.
Use SKYLOS_TOKEN for:
- CI providers without OIDC
- explicit project selection in a trusted CI job
- local policy sync or upload
For GitHub OIDC, skylos sync pull uses the same accepted CI identity as the
upload. It does not require a stored token in the default-branch upload job.
Advisory Quality Checks
When adopting standards-backed quality checks in an existing repository, run them as advisory first. The workflow should warn, annotate, and write a summary, but return exit code 0 until legacy findings are under control.
Recommended advisory bundle:
- Ruff for Python lint policy
- mypy or pyright for Python type-check policy
- TypeScript compile/build scripts for packages with
tsconfig.json - Rustfmt and Clippy for Rust crates
- diff-aware Skylos scans using
--diff-baseand--diff
- name: Skylos advisory scan
run: skylos . --danger --secrets --quality --ai-defects --no-upload --diff-base origin/main --diff origin/main --json -o skylos-results.json
- name: Advisory quality summary
if: always()
run: skylos cicd gate --input skylos-results.json --summary --advisory
Use a hard gate later, after findings are diff-aware, baseline-aware, or low enough to enforce.
Pull Request Review Comments
Skylos can post inline GitHub pull request review comments for findings on changed lines. Use this when you want reviewers to see Skylos findings directly on the PR diff instead of only in the Actions log or job summary.
The generated workflow from skylos cicd init includes this review step. If you
use the Skylos GitHub Action directly, set its mode input to review. If you
write your own workflow, grant pull-requests: write, expose GH_TOKEN, and run
skylos cicd review after creating a JSON report.
name: Skylos PR Review
on:
pull_request:
permissions:
contents: read
jobs:
skylos:
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
with:
python-version: '3.12'
- run: python -I -m pip install skylos
- name: Run Skylos on changed code
run: |
pr_base_ref="origin/${GITHUB_BASE_REF:-main}"
skylos . --danger --quality --secrets --ai-defects --no-upload --diff-base "$pr_base_ref" --diff "$pr_base_ref" --json -o skylos-results.json
- name: Post GitHub annotations
if: always()
run: skylos cicd annotate --input skylos-results.json
- name: Post PR review comments
if: always() && github.event.pull_request.head.repo.full_name == github.repository
env:
GH_TOKEN: ${{ github.token }}
run: |
pr_base_ref="origin/${GITHUB_BASE_REF:-main}"
skylos cicd review --input skylos-results.json --diff-base "$pr_base_ref" --max-comments 25
skylos cicd review auto-detects the PR number and repository in GitHub
Actions. Outside CI, pass them explicitly:
skylos cicd review --input skylos-results.json --pr 42 --repo owner/repo
Use --summary-only when you want a single PR summary comment without inline
comments. Use --max-comments to cap review noise on large diffs.
Fork PRs still get the scan and annotations; the comment step is skipped
because their GitHub token has read-only permissions.
Pulling Policy in CI
The generated default-branch upload job pulls policy with its GitHub OIDC identity before scanning:
- name: Pull Skylos policy
run: skylos sync pull
In a trusted job that uses an API key instead, provide SKYLOS_TOKEN:
- name: Pull Skylos policy
env:
SKYLOS_TOKEN: ${{ secrets.SKYLOS_TOKEN }}
run: skylos sync pull
That writes .skylos/config.yaml and .skylos/suppressions.json in the checkout.
Keep policy sync and its credentials out of ordinary PR test jobs.
Generated Workflow Helpers
skylos cicd init
Use skylos cicd init from Skylos 4.46.0 or newer to scaffold the workflow
described here. On GitLab CI, Jenkins, Bitbucket Pipelines, Azure Pipelines
and CircleCI it sets up that CI's gate instead (Skylos 5.1.0 or newer); see
Other CI Providers.
Examples:
skylos cicd init
skylos cicd init --no-upload
skylos cicd init --done
skylos cicd init --defend
The generated workflow has:
- Skylos Quality Gate on PRs: a changed-line scan, gate summary, annotations and review comments
- Skylos Done on PRs when pytest tests or a configured test command are found: tests and a completion receipt
- Skylos Cloud upload on default-branch pushes: policy sync and a full scan using GitHub OIDC
Upload is on by default; --no-upload omits it. --done and --no-done
override test discovery. --default-branch overrides branch detection, and
--scan-path changes the scanned directory. The generated workflow pins
the installed Skylos version, so regenerate it after upgrading Skylos.
For multiple Cloud projects in a monorepo, use the GitHub App's generated
per-root workflow. CLI --scan-path does not route the generated
skylos sync pull step: it sends no GitHub project-subpath header and can
fail when several projects match the repository.
skylos sync setup
skylos sync setup asks for an API key to connect the local repository and
scaffold optional hooks and workflow files.
Current behavior:
- it asks for a token
- it can scaffold pre-push hooks, pre-commit config, and a GitHub Actions workflow
- its generated CI workflow scans PRs locally and uploads default-branch pushes with GitHub OIDC
- use
skylos cicd initfor the PR gate and discovered Done job described above
GitHub App Enforcement
The GitHub App is the GitHub-native enforcement layer.
Recommended order:
- get uploads working first
- save the exact GitHub repo URL on the project
- install the GitHub App: in the project's Settings, step 1 of Merge blocking on GitHub is Connect GitHub
- open or update a pull request so the Skylos Quality Gate check runs on it
- require the check: in the project's Settings, step 4 of Merge blocking on GitHub has Download ruleset
Require the check with a ruleset
The ruleset Skylos gives you requires Skylos Quality Gate from the Skylos App on your default branch. A workflow job with the same name can't pass it.
- In the project's Settings, select Download ruleset.
- On GitHub, open the repository's Settings -> Rules -> Rulesets, select New ruleset -> Import a ruleset, choose the file, then select Create.
- Back in Skylos, select Check again. The step shows Done.
If you connected a GitHub organization, the repository also shows Enforcing under Repository coverage on the Posture page.
Skylos offers the file only after the check has run on a pull request, so the rule never waits for a check that can't arrive. Direct pushes to the default branch need a passing check too. To let admins skip it, add them to the ruleset's bypass list on GitHub.
"Merge anyway" in Skylos (Workspace and Enterprise plans) updates the same check, so it still works with the ruleset.
If the repository uses a merge queue, Skylos doesn't offer the ruleset yet: Skylos doesn't check merge-queue commits, so the queue would wait forever.
Skylos only reads branch protection and rulesets; it never changes them. The auto-configure toggle in the project settings (Workspace and Enterprise plans, off by default) only opens the workflow pull request after you connect GitHub.
Other CI Providers
Skylos runs on any CI. skylos cicd init finds the CI your repository uses and
sets up the pull request gate for it. CIs other than GitHub Actions need
Skylos 5.1.0 or newer; check with skylos --version.
| Repository has | skylos cicd init sets up |
|---|---|
.github/workflows/ | GitHub Actions: writes .github/workflows/skylos.yml |
.gitlab-ci.yml | GitLab CI |
Jenkinsfile | Jenkins |
bitbucket-pipelines.yml | Bitbucket Pipelines |
azure-pipelines.yml | Azure Pipelines |
.circleci/config.yml | CircleCI |
.buildkite/, .travis.yml, .drone.yml, .woodpecker.yml, .teamcity/ | prints the commands to add |
| no CI file | the CI of origin's host (github.com, gitlab.com, bitbucket.org, dev.azure.com), else GitHub Actions |
If the CI file does not exist yet, Skylos writes it. If it exists, Skylos does
not edit it: it prints the block to add and where it goes. Pick a CI with
--ci github|gitlab|jenkins|bitbucket|azure|circleci|other.
A repository with .github/workflows/ gets the GitHub workflow, as before.
Skylos also names any other CI file it found and the --ci command for it.
Without .github/workflows/, two or more of the GitLab, Jenkins, Bitbucket,
Azure and CircleCI files and no --ci make Skylos write nothing and ask you
to pick.
Every generated config runs the same gate on the lines the pull request changes, and fails the build when the gate fails:
skylos . --danger --quality --ai-defects --secrets --sca --review-upgrades --baseline --gate --diff
--review-upgrades downloads the old and new release of each npm or PyPI
package the pull request upgrades and fails the gate when the new one adds
install-time or start-up code (see Upgrade Review).
It is added whenever --sca is selected. Configs written by Skylos versions
without this flag leave it out.
The review fails closed: when it cannot check an upgrade, the gate stops
with exit 2 instead of passing. That happens when a registry cannot be
reached, when more than 100 package versions change (adding a lockfile or
switching package manager usually does), when a changed lockfile is over
64 MB or cannot be read, and when a private package is neither in
internal_packages nor downloaded from a host in private_registries. List
private packages and registries under [tool.skylos.supply_chain] on the
default branch. See Upgrade Review.
--baseline hides findings saved in .skylos/baseline.json. Commit one with
skylos baseline . if you want that. Without the file, Skylos prints "No
baseline found" and checks every changed line. For agent-config and
publish-job rules, malware, SKY-SCA-UPG001, SKY-SCA-HRD001 and
SKY-SCA-AGE001, a baseline entry counts only when the base branch's
.skylos/baseline.json has it too, so a pull request cannot excuse its own
findings by editing the baseline (see
Baselines).
The config installs the Skylos version you ran skylos cicd init with, for
example skylos[dart]==5.1.1. Change that pin when you upgrade.
Then:
- Commit the file, or the block Skylos printed, on a branch and open a pull request.
- Check that the Skylos gate runs on it.
- Make that check required before merging, in your code host's branch protection.
skylos doctor shows which CI files run Skylos. Run in CI, it also shows which
branch --diff compares with.
To upload to Skylos Cloud from a CI other than GitHub Actions, use
skylos cloud --gate. It runs every check, uploads the findings, and exits 1 when the Skylos
Cloud gate (your project's policy in Skylos Cloud) fails. That is not the local
skylos . --gate, which uses [tool.skylos.gate] and uploads nothing. Set
SKYLOS_TOKEN to a project token as a secret in a trusted job, and select
Mark for CI on that token in the project's Settings. Without the mark, its
uploads are unverified: they show in Skylos Cloud but don't publish a check or
mark issues fixed.
skylos cloud --gate
GitLab CI
The skylos job runs in merge request pipelines with GIT_DEPTH: "0", fetches
the target branch and runs the gate. If your .gitlab-ci.yml declares
stages:, it needs a test stage. For the merge request Code Quality widget,
see GitLab Code Quality.
Jenkins
The Skylos stage runs only in pull request builds (when { changeRequest() })
of a Multibranch Pipeline job. It installs Skylos in a virtualenv under
$WORKSPACE_TMP, outside the checkout, so the install is not part of the diff.
The agent needs python3 3.10 or newer.
The stage fetches the target branch only when the clone does not have it. If that fetch fails on a private repository, the shell step has no Git credentials. Use the "merge with the target branch" pull request strategy, which fetches it during checkout, or give the step credentials.
Jenkins does not own the pull request; your code host does. Make the Jenkins status check required there.
Bitbucket Pipelines
The step runs in pull request pipelines with clone: depth: full and fetches
the destination branch before the scan.
Azure Pipelines
The pipeline checks out with fetchDepth: 0, which brings in the target branch.
It does not run its own git fetch, because Azure does not keep checkout
credentials for later steps. For Azure Repos, add the pipeline as the target
branch's Build validation policy.
CircleCI
The job skips builds without an open pull request. CircleCI does not expose the
pull request's target branch, so the job compares with your default branch:
the --default-branch you pass, else origin's HEAD, else main. Change the
branch in the file if pull requests go elsewhere.
Other CIs
skylos cicd init --ci other prints the three commands to add to a pull
request build step. The step needs Python 3.10 or newer. With Skylos 5.1.1
and main as the default branch, they are:
python -I -m pip install skylos==5.1.1
git fetch --no-tags origin "+refs/heads/main:refs/remotes/origin/main"
skylos . --danger --quality --ai-defects --secrets --sca --baseline --gate --diff origin/main
Skylos versions that have --review-upgrades print it after --sca in the
last command.
Dart files
The Jenkins and "other CI" commands install plain skylos. Dart support,
skylos[dart], is built from source and needs a C compiler, which many Jenkins
agents do not have. To scan Dart files, install skylos[dart] on an agent that
has one.
Without it, Skylos skips the Dart files and reports coverage as incomplete. The
gate still decides on the other files. It stops with exit 2 only when most of
the files in scope could not be analyzed, or when you add --strict or set
require_complete = true under [tool.skylos.gate.coverage].
The GitLab, Bitbucket, CircleCI and Azure configs run on images with a compiler
and install skylos[dart].
Which branch --diff compares with
With no value, --diff compares with the pull request's target branch:
| CI | Target branch from | Pull request build when |
|---|---|---|
| GitHub Actions | GITHUB_BASE_REF | GITHUB_BASE_REF is set |
| GitLab CI | CI_MERGE_REQUEST_TARGET_BRANCH_NAME | GITLAB_CI=true and the variable is set |
| Jenkins | CHANGE_TARGET | CHANGE_ID is set (Multibranch Pipeline) in a Jenkins build: JENKINS_URL, JENKINS_HOME or a jenkins- BUILD_TAG |
| Bitbucket Pipelines | BITBUCKET_PR_DESTINATION_BRANCH | the variable is set |
| Azure Pipelines | SYSTEM_PULLREQUEST_TARGETBRANCH | SYSTEM_PULLREQUEST_PULLREQUESTID is set |
| Buildkite | BUILDKITE_PULL_REQUEST_BASE_BRANCH | BUILDKITE_PULL_REQUEST is a number |
| Travis CI | TRAVIS_BRANCH | TRAVIS_PULL_REQUEST is a number |
| Drone | DRONE_TARGET_BRANCH | DRONE_BUILD_EVENT=pull_request |
| Woodpecker | CI_COMMIT_TARGET_BRANCH | CI=woodpecker and CI_PIPELINE_EVENT=pull_request |
Each variable counts only inside its own CI and only on a pull request build.
Anywhere else, --diff compares with origin/main. On CircleCI, TeamCity and
other CIs, pass the branch: --diff origin/develop.
The target branch has to be in the clone. Many CIs clone only the pull request branch, or only recent history. When it is missing, Skylos stops with exit 2 and prints the command to run first, for example:
On Jenkins, run this before the scan: git fetch --no-tags origin +refs/heads/develop:refs/remotes/origin/develop
In a shallow clone that command includes --unshallow.
Uploading to Skylos Cloud from other CIs
skylos cicd init adds Cloud uploads only for GitHub Actions, through GitHub
OIDC. On other CIs, add a separate full scan with --upload and a
SKYLOS_TOKEN secret.
Diff-scoped reports cannot be uploaded. A scan with --upload and --diff or
--diff-base stops with "diff-scoped results cannot be uploaded as a full
scan". Keep the gate step and the upload step separate.
Use a project token made for CI, not the one skylos login saved on a laptop.
Until an owner or admin selects Mark for CI on that token (project
Settings, Project tokens), its uploads are unverified. Unverified scans
are stored and shown, but they don't post a pull request check or status,
mark issues fixed, or become the baseline. Tokens saved by skylos login
can't be marked.
For Bitbucket and Azure pull request checks, see Bitbucket and Azure Pipelines. For GitLab, see GitLab managed uploads. Skylos Cloud posts merge request comments on GitLab only on the Workspace and Enterprise plans.
GitLab CI:
skylos:
image: python:3.11
script:
- pip install skylos
- skylos . --danger --quality --ai-defects --upload
variables:
SKYLOS_TOKEN: $SKYLOS_TOKEN
CircleCI:
- run:
name: Skylos Scan
command: skylos . --danger --quality --ai-defects --upload
environment:
SKYLOS_TOKEN: $SKYLOS_TOKEN
Jenkins:
stage('Skylos Scan') {
environment {
SKYLOS_TOKEN = credentials('skylos-token')
}
steps {
sh 'pip install skylos'
sh 'skylos . --danger --quality --ai-defects --upload'
}
}
Local Gate vs Cloud Gate in CI
Local gate
skylos . --danger --secrets --quality --ai-defects --gate
Use this when you only want CLI exit codes from local config. A bare --gate
does not enable every analyzer.
For a narrow source/config release proof:
# Kubernetes exposure path
skylos . --select SKY-DEP001,SKY-DEP002,SKY-DEP003 --gate
# CUDA image, build-architecture, and TensorRT packaging intent
skylos . --select SKY-GPU001,SKY-GPU002,SKY-GPU003 --gate
GPU leaf selection automatically retains SKY-GPU000 so a missing or invalid
target contract fails closed. Reliability uses max_reliability = 0 by
default. See Release Reliability for contract setup.
After producing the local GPU artifact, gate that exact output separately:
skylos preflight build/app
Preflight uses its own result contract: 0 is PASS, 1 is a proved
FAIL, and 2 is UNKNOWN or invalid input. Treat 2 as a blocked release
in CI. See Built Artifact Preflight.
Cloud gate
skylos . --upload
Use this when you want the cloud project to evaluate:
- dashboard policy
- suppressions
- baseline history
- strict mode
- AI assurance
- PR-diff-aware new issue detection when available
Troubleshooting
OIDC upload says the repo is not linked
Set the exact GitHub repo URL on the Skylos project.
OIDC upload says the repo binding is ambiguous
Make sure the request identifies the intended project subpath and only one
project matches that repository and subpath. Use the App's per-root workflow
for multiple monorepo projects; CLI --scan-path alone does not route policy
sync.
skylos sync pull fails in CI
sync pull accepts GitHub OIDC in an authorized default-branch upload job.
Check id-token: write, the project repo URL and the App installation.
For local use or a provider without OIDC, use a saved API key or
SKYLOS_TOKEN. Do not move policy sync into an ordinary PR test job.
The workflow generated by sync setup still wants a token
sync setup asks for a token to connect your local repository. Its generated
default-branch upload uses GitHub OIDC. An older workflow that references
SKYLOS_TOKEN can be replaced with skylos cicd init; review the generated
file before committing it.
Upload works but there is no GitHub-native PR status
Basic upload is not the same thing as GitHub App enforcement. Save the repo URL, install the GitHub App, and configure branch protection.