Author, edit, debug, and review the OpenVINO GitHub Actions CI infrastructure — regular (non-agentic) workflows under .github/workflows, reusable job_*.yml workflows, custom composite actions under .github/actions, CI helper scripts under .github/scripts, Dockerfiles under .github/dockerfiles, and the Smart CI / labeler / components configuration. Use when a user wants to add or change a build/test job or step, create or modify a reusable workflow, write or fix a custom action, adjust runners/containers/caches, wire up Smart CI for a component, pin action versions, fix workflow permissions/security, or debug a failing CI workflow's YAML. Do NOT use for gh-aw agentic workflows (*.md with gh-aw frontmatter — use ov-agentic-workflows), for diagnosing a specific product/test failure's root cause in C++/Python code, or for non-CI GitHub configuration.
76
96%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Guides changes to the regular GitHub Actions CI in this repository: validation and reusable workflows, custom actions, CI scripts, Dockerfiles, and the Smart CI configuration that drives them.
Read the CI developer docs under docs/dev/ci/github_actions first — they are the authoritative, repo-specific reference and this skill is a checklist on top of them. Keep them in sync when behavior changes (see Skill self-improvement). The key pages:
| Topic | Doc |
|---|---|
| Big picture, workflow structure, triggers, results/artifacts/logs | overview.md |
Reusable job_*.yml workflows | reusable_workflows.md |
| Custom composite actions | custom_actions.md |
| Smart CI (skip unaffected jobs) | smart_ci.md |
Runners (runs-on) | runners.md |
Docker images / handle_docker | docker_images.md |
| Caches (GHA / shared drive / sccache) | caches.md |
| Adding tests (step / job / workflow) | adding_tests.md |
| OpenVINO Provider (prebuilt artifacts) | openvino_provider.md |
| Workflow security | security.md |
For framework syntax, use the official GitHub Actions documentation. If user requires an out-of-scope feature, consult the official documentation.
Out of scope: gh-aw agentic workflows (.github/workflows/*.md + *.lock.yml, e.g. ci-doctor)
— use the ov-agentic-workflows skill instead.
.github/workflows/
ubuntu_22.yml,
windows_vs2022_release.yml, mac_arm64.yml, linux_arm64.yml, android.yml. Entry points with
on: triggers; they wire together Build + test jobs.job_*.yml (e.g. job_python_unit_tests.yml, job_cxx_unit_tests.yml).
Called via uses: ./.github/workflows/job_*.yml with on: workflow_call: inputs. Not triggered
directly..github/actions/ (composite action.yml): setup_python, system_info,
smart-ci, handle_docker, openvino_provider, store_artifacts/restore_artifacts, cache, etc..github/scripts/ (Python helpers: workflow_rerun/, external_pr_labeller.py,
check_copyright.py, ...)..github/dockerfiles/ov_build/** and ov_test/**, plus the docker_tag file..github/labeler.yml (path globs → component/label) and
.github/components.yml (component dependency graph).workflows_scans.yml (CodeQL actions + semgrep on workflow changes),
dependency_review.yml../.github/actions/* are referenced by path, not pinned.
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2permissions:. Start from permissions: read-all (workflow level) and grant the
minimum extra scope at the job level only where needed. Never widen without a reason.pull_request_target, never hard-code secrets, and treat all github.* /
github.event.* user-controlled values as untrusted (route them through env: or action inputs, never
interpolate directly into run: shell). Ping the CI task force for anything involving secrets or
elevated triggers.job_*.yml, not copy-paste. If the same job appears in more
than one validation workflow, it should be a workflow_call reusable workflow parameterized by
runner, image/container, and affected-components.fromJSON(needs.smart_ci.outputs.affected_components).<COMPONENT>.{build,test} and list Smart_CI in
needs. Do not make an expensive job run unconditionally.handle_docker, not hard-coded tags. Reference build/test images
as ${{ fromJSON(needs.docker.outputs.images).ov_build.<name> }} and add Docker to needs. Plain
passthrough images must use the ACR mirror openvinogithubactions.azurecr.io/..., never docker.io..github/** is owned by
@openvinotoolkit/openvino-ci-maintainers and changes there are label category: CI
(workflows also get github_actions).runs-on) — self-hosted Azure pools aks-{os}-{cores}-cores-{ram}gb[-arm] for
heavy build/test; GitHub-hosted (ubuntu-22.04, ...) for light jobs (labelers, style). GPU jobs use
[ self-hosted, gpu|igpu|dgpu ] and must run in Docker. Azure aks-* runners are required to
pull from the ACR / use custom images. Match cores to parallelism (see runners.md).container:. Mount the shared drive with
volumes: [ /mount:/mount ] and add ${{ github.workspace }}:${{ github.workspace }} where the
workspace must be identical inside/outside the container.actions/cache, ≤10 GB) for small deps; shared drive (/mount/..., e.g.
PIP_CACHE_PATH: /mount/caches/pip/linux) for large assets on Linux self-hosted; sccache → Azure
Blob for C/C++ build cache (needs SCCACHE_AZURE_* env + CMAKE_*_COMPILER_LAUNCHER: sccache +
SCCACHE_AZURE_KEY_PREFIX).Build job packs and uploads; test jobs needs: Build and download. Follow the
existing store_artifacts/restore_artifacts actions and artifact-name conventions in the workflow.timeout-minutes — always set a sensible per-job timeout.Follow adding_tests.md:
name + run step, gate with
if: fromJSON(inputs.affected-components).<COMPONENT>.test when component-specific.job_*.yml); set needs: [Build, Smart_CI],
runs-on, container, timeout-minutes, and a Smart CI if:.job_*.yml)on: workflow_call: with typed inputs (runner, image, affected-components,
python-version, ...) and permissions: read-all.uses: ./.github/workflows/job_<name>.yml with with: and
needs: [ Build, Smart_CI ].description:..github/labeler.yml ('category: X': [globs])..github/components.yml under revalidate: (build+test) / build: (build
only); use [] for none, or 'all' to force full validation. Dependencies are not transitive.Smart_CI to the validating job's needs and gate with
if: fromJSON(needs.smart_ci.outputs.affected_components).<COMPONENT>.{build,test}. Keep the same
condition on every step/job in the dependency chain — a skipped step feeding an ungated dependent
leaves it running against missing outputs.Overall_Status job (it needs: the real jobs and reports one required
check). A workflow that must be required cannot use a paths: filter — a filtered-out run reports
no status and blocks the merge queue; rely on Smart CI + Overall_Status instead.action.yml under .github/actions/<name>/. Declare inputs (with description,
required, default) and runs: using: composite. Every run step needs an explicit shell:.env: inside the step, not inline interpolation.requirements.txt, it must pin the full dependency tree, not just
top-level packages. Generate it from a clean environment with pip freeze:
python3 -m venv /tmp/act-env && . /tmp/act-env/bin/activate
pip install <top-level-deps> # only the packages you directly import
pip freeze > .github/actions/<name>/requirements.txt@actions/* toolkit gives first-class typed access to it. The bundled
.github/actions/cache action is the reference example of a
JS-based action.Follow docker_images.md: add a Dockerfile under
.github/dockerfiles/{ov_build,ov_test}/<platform>/, ensure a Docker job runs handle_docker with the
image path in images:, add Docker to consumers' needs, and set
image: ${{ fromJSON(needs.docker.outputs.images).<group>.<name> }}. When adding a new env-setup script,
add it under category: docker_env in labeler.yml, exclude it from .dockerignore, and bump
.github/dockerfiles/docker_tag (handle_docker prompts you).
Pick the pool from runners.md; keep container
volumes/options (shared drive, sccache) consistent with sibling jobs. GPU → Docker + self-hosted label.
actionlint if available (actionlint .github/workflows/<file>.yml); otherwise
sanity-check YAML parses. Mirror what workflows_scans.yml (CodeQL actions + semgrep) and
dependency_review.yml enforce — those run on any .github/workflows/** change.uses: is a full SHA + version comment.Smart_CI is in needs.docker_tag/labeler/components edits unless required.*.lock.yml — those belong to agentic workflows.run: — ${{ github.event.* }} interpolated into shell is an injection vector;
route through env:.permissions: — especially write scopes at workflow level.if: whose
dependent step/job lacks the same condition runs against missing outputs/artifacts. Gate the whole
chain consistently.paths: filter on a required workflow — filtered-out runs report no status and hang the merge
queue; use Smart CI + Overall_Status instead of paths:.docker.io / non-ACR image on aks-* — pulls fail or hit rate limits; use the ACR
mirror or handle_docker output.Docker/Smart_CI/Build in needs — races or missing artifacts/inputs.job_*.yml input contract without updating every caller's with: block.docker_tag bump — the image won't rebuild; handle_docker fails the check.timeout-minutes — a hung job can occupy a runner indefinitely.Keep this skill and the CI docs in sync with reality. When a change reveals a new rule, pattern, or footgun:
docs/dev/ci/github_actions/..agents/skills/ and .claude/skills/ (the former is a symlink to
the latter), so a single edit updates both — do not create a duplicate copy.f766feb
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.