Use a GitHub Actions workflow file as your pipeline configuration Preview
| GitHub Actions workflow support is in Preview. This feature is in its early stages and you may encounter bugs, unexpected behavior, or incomplete features. Post all feedback to The CircleCI ideas board. |
A CircleCI pipeline is generally defined by a CircleCI configuration file. You can instead use an existing GitHub Actions workflow file as your pipeline configuration. CircleCI runs your GitHub Actions workflow on CircleCI compute. Your workflow file stays where it is, in .github/workflows/, and you do not need to translate it into CircleCI syntax.
Running your GitHub Actions workflow as it is helps when you want to move work onto CircleCI without rewriting your configuration first. It also lets you compare the two platforms using the same workflow. A subset of GitHub Actions features is supported. Before you start, check the GitHub Actions Feature Support section to confirm your workflow uses supported features.
| If you would rather convert your workflow into CircleCI syntax, see the Migrate From GitHub Actions page and the CircleCI configuration translator. |
Prerequisites
-
A CircleCI Cloud organization integrated with GitHub using the CircleCI GitHub App.
-
A GitHub repository with a GitHub Actions workflow file.
-
A workflow that runs on Linux. CircleCI does not support macOS or Windows for GitHub Actions workflows. For macOS and Windows builds you can migrate to use CircleCI YAML config. See the Migrate From GitHub Actions page for more information.
To use the CircleCI CLI steps on this page, you also need the following:
-
CircleCI CLI v1.0 or later, authenticated with
circleci auth login. Runcircleci auth meto confirm. See the CircleCI CLI page. -
The GitHub CLI (
gh), used to look up your repository ID. Any other method of finding the repository ID works too.
Set up a new project with a GitHub Actions workflow file
To set up a new project with a GitHub Actions workflow file, follow the steps in the web app or the CircleCI CLI.
-
Web app
-
CircleCI CLI
When you create a project, CircleCI asks where to get build instructions for your repository. Choose your existing GitHub Actions workflow file at that point.
-
In the CircleCI web app, select Home in the sidebar.
-
Select Create Project at the top of the page, or anywhere in the Create a project card if this is your first project.
-
Give your project a descriptive name and then select Next: Set up a pipeline.
-
Next, set up your first pipeline for your project. Pipelines define the executable commands and scripts for your CI/CD processes. The first step is to name your pipeline. Use a name that describes the purpose of the pipeline, for example,
build-and-test. Then select Next: Choose a repo. -
Choose a repo for your pipeline. CircleCI checks out the code from this repo when your pipeline runs.
If you already have a connection, select your repo from the list. To connect an additional provider, select + Add and then choose its tile.
If you have no connection yet, select your provider’s tile and follow that provider’s instructions. Granting access applies to any project in your organization, and you can update repo access at any time.
Select the GitHub Cloud tile if you do not already have a connection. CircleCI redirects you to GitHub, where you install and authorize the CircleCI GitHub App. Installing the app is a one-time step.
-
On the Select your config source step, select Use existing GitHub Actions workflow file, enter the path to the GitHub Actions workflow file, then select Continue.
-
Set up the triggers for your pipeline. CircleCI adds one trigger by default, to build your project on every commit. You can Add More Triggers at this point. Select Next: review and finish setup
-
Review what you have set up, then select Finish setup.
Your pipelines page opens. The next time your trigger fires, CircleCI runs the jobs from your GitHub Actions workflow file.
Run these commands from your repository directory. Every command below resolves your project from the git remote, so you do not need to pass a project slug.
-
Create the project. CircleCI names it after the current repository.
circleci project create --jsonIf you belong to more than one organization, add
--org <org-slug>. Runcircleci org listto find it, then usegh/<org-name>for a GitHub organization orcircleci/<org-id>for acirclecitype organization. -
Find the numeric ID of your GitHub repository. You need this ID for both the pipeline definition and the trigger.
gh api /repos/<owner>/<repo> --jq .id -
Create the pipeline definition, pointing it at your workflow file.
circleci pipeline create \ --name "github-actions-ci" \ --config-provider github_app \ --config-repo-id <github-repo-id> \ --config-file .github/workflows/ci.yml \ --config-file-type github-actions \ --checkout-provider github_app \ --checkout-repo-id <github-repo-id> \ --json--config-file-type github-actionsis the flag that makes this work, and it is simple to miss when following a general onboarding flow.Leave it out and CircleCI reads your workflow file as CircleCI configuration syntax. The failure is confusing rather than obvious, and looks similar to the following:
jobs referenced in workflows that have not been defined: buildNote the pipeline definition ID returned by this command. You need it in the next two steps.
-
Follow the project, so that it appears on your dashboard. This step is required for OAuth organizations, with slugs beginning
gh/orbb/, and is worth doing for any organization.circleci project follow -
Add a trigger to connect your pipeline definition to a Git event.
circleci project trigger create \ --pipeline-definition-id <definition-id> \ --repo-id <github-repo-id> \ --event-preset all-pushes \ --jsonOther presets include
only-open-prsanddefault-branch-pushes. Runcircleci help triggersfor the full list, or see the GitHub Trigger Event Options page. -
Trigger a run to check your setup. Targeting the definition directly bypasses the trigger, so you do not need to push a commit.
circleci pipeline run --definition-id <definition-id> --branch main --json circleci run watch <run-id> --failfast
Check what actually ran, rather than trusting a green result. Because some GitHub Actions features are accepted without taking effect, a passing run does not prove that every step did what your workflow file asks for. Use circleci run get <run-id> --json to list workflow and job IDs, circleci job get <job-id> --json to list steps, and circleci job output get <job-id> --step-num <n> --strip-ansi to read the raw step output.
|
Add a GitHub Actions pipeline to an existing project
A project can have more than one pipeline, so you can add a GitHub Actions pipeline alongside pipelines that use CircleCI configuration.
-
Web app
-
CircleCI CLI
-
In the CircleCI web app, select your org from the org cards on your user homepage.
-
Select Projects from the sidebar and locate your project from the list. You can use the search to help.
-
Select the ellipsis
next to your project and select Project Settings.
You can also access project settings from each project overview page using the Settings button. -
Select Project Setup in the sidebar.
-
Select Add Pipeline, or select the pencil icon (
) next to an existing pipeline to change it.
-
Give your pipeline a descriptive name, for example
github-actions-ci. -
Under Config source, select the repository that holds your GitHub Actions workflow file.
-
Under Config filepath, select the GitHub Actions workflow file checkbox, then enter the path to your workflow file, for example
.github/workflows/ci.yml. -
Under Checkout source, select the repository to check out when your workflow runs. For most projects this is the same repository you selected as the config source.
-
Select Save.
Connect your new pipeline to a trigger before it can run. See the Set Up Triggers page.
Run these commands from your repository directory, so your project resolves from the git remote.
-
Find the numeric ID of your GitHub repository.
gh api /repos/<owner>/<repo> --jq .id -
Create the pipeline definition in your existing project, pointing it at your workflow file. Include
--config-file-type github-actions, or CircleCI reads your workflow file as CircleCI configuration syntax and the run fails.circleci pipeline create \ --name "github-actions-ci" \ --config-provider github_app \ --config-repo-id <github-repo-id> \ --config-file .github/workflows/ci.yml \ --config-file-type github-actions \ --checkout-provider github_app \ --checkout-repo-id <github-repo-id> \ --jsonNote the pipeline definition ID returned by this command.
-
Add a trigger to connect your new pipeline definition to a Git event.
circleci project trigger create \ --pipeline-definition-id <definition-id> \ --repo-id <github-repo-id> \ --event-preset all-pushes \ --json -
Trigger a run to check your setup.
circleci pipeline run --definition-id <definition-id> --branch main --json circleci run watch <run-id> --failfast
| The CLI cannot tear these down. The CLI has no command to delete a project or a pipeline definition, and no command to delete or disable a trigger. Check your flags before you create anything, and remove unwanted pipelines and triggers in the web app. |
How it works
When you set up a pipeline to use a GitHub Actions workflow file, CircleCI does the following:
-
CircleCI reads your workflow file from the config source repository, at the path you gave the pipeline.
-
CircleCI translates the workflow into a CircleCI workflow. Each GitHub Actions job becomes a CircleCI job, and
needs:relationships becomerequires:relationships, so your workflow graph is preserved. -
CircleCI runs your GitHub Actions jobs. Your steps run with GitHub Actions semantics. This covers
run:anduses:steps,${{ }}expression evaluation, step and job outputs, and secret masking.
Your workflow file is never rewritten, and you do not maintain a CircleCI configuration file alongside it. You get CircleCI compute and the pipelines dashboard, running the workflow definition you already have.
CircleCI implements GitHub Actions semantics rather than calling GitHub, so only a subset of features is available. See GitHub Actions Feature Support.
How CircleCI triggers your workflow
Your CircleCI trigger decides whether the pipeline runs. You configure it in CircleCI, in the same way as any other pipeline. See the Set Up Triggers page.
|
The filters under A workflow with |
CircleCI does read on: for two things: the inputs declared under on.workflow_dispatch.inputs, and the interface declared under on.workflow_call. A workflow that declares only unsupported events is skipped.
The following table shows how CircleCI translates its own events into the github.event_name your workflow sees. It describes the value in the GitHub Actions context rather than a second gate on whether the workflow runs.
| GitHub Actions event | CircleCI event | Notes |
|---|---|---|
|
Push |
CircleCI builds a partial event payload from the pipeline values. |
|
Pull request |
The payload includes the base and head SHA, and the branch. |
|
Schedule |
Set the schedule on your CircleCI trigger. The |
|
API |
The |
|
Not applicable |
Defines a reusable workflow interface for other local workflows to call. |
|
Custom webhook |
The event name is mapped, but the event payload is not populated. |
Any other event |
Not applicable |
Not mapped. A workflow that declares only unsupported events is skipped. |
What to expect when your workflow runs on CircleCI
Your workflow runs on CircleCI compute, so some values your workflow reads at runtime differ from the values GitHub would report.
-
Jobs run on Linux x86-64. The
runner.oscontext reportsLinux,runner.archreportsX64, andrunner.environmentreportsself-hosted. -
All standard
GITHUB_*andRUNNER_*environment variables are set, with the exception ofACTIONS_RUNTIME_TOKEN. -
OIDC tokens are issued by CircleCI. See OIDC Tokens.
-
Set the secrets your workflow reads as project environment variables, rather than as GitHub repository secrets. See the Set an Environment Variable in a Project page.
GitHub Actions feature support
If a feature does not appear in this section, treat it as unsupported.
Support levels
| Level | Meaning |
|---|---|
Supported |
Works as it does on GitHub Actions. |
Partial |
Works within the limits described in the table. |
No effect |
The syntax is accepted and your workflow still runs, but the feature does nothing. Read these rows carefully. A workflow that depends on one of these features for correctness or safety behaves differently on CircleCI. |
Not supported |
Rejected, or outside the supported set. |
Workflow and job structure
| Feature | Support | What to know |
|---|---|---|
Jobs, |
Supported |
Static job dependencies, matrix fan-out and fan-in, job results, and job outputs all work. Dependency graphs can be up to 20 levels deep. |
|
Partial |
Use |
|
Supported |
Retained at workflow and job level. Job names can use matrix values. |
|
Supported |
Accepts literal booleans and expressions, at job and step level. |
|
Partial |
Enforced at job and step level, defaulting to 360 minutes. A warning in the build output may state that this key has no effect. That warning is wrong, and the timeout is enforced. |
|
Partial |
Workflow, job, and step values use normal precedence, so the most specific value wins. |
|
No effect |
CircleCI emits a warning. Concurrent runs are not serialized, so a workflow that relies on a concurrency group to prevent overlapping deploys is not protected. |
|
Partial |
CircleCI inserts an approval job before any job that declares |
|
Partial |
CircleCI starts a long-lived container and runs your |
Matrix strategies
| Feature | Support | What to know |
|---|---|---|
|
Supported |
Up to 256 instances per job. |
|
Partial |
Literal combinations work. An |
|
No effect |
A failing matrix instance does not cancel its siblings. |
|
No effect |
Use CircleCI concurrency controls instead. |
|
Not supported |
The context is not populated and resolves to null. Use |
Steps, shells, and expressions
| Feature | Support | What to know |
|---|---|---|
|
Partial |
Use |
Operators and comparisons |
Supported |
The full set of GitHub Actions operators is available in conditions and in string interpolation. |
|
Supported |
Available in conditions and in string interpolation. |
|
Partial |
Available in conditions, without arguments. Not available in string interpolation. |
|
Partial |
Available in step conditions and workflow steps, not in job conditions. |
|
Supported |
Available in conditions and in string interpolation. Takes predicate and value pairs followed by a fallback, as in |
Environment files |
Supported |
|
Log grouping and annotations |
Supported |
The |
|
Not supported |
Disabled for security reasons, following CVE-2020-15228. CircleCI logs a warning and does not apply the value. Use the |
|
No effect |
Deprecated by GitHub, and silently consumed here. Use |
|
No effect |
Silently consumed. |
|
Not supported |
Not implemented. |
For the contexts available in job conditions and step conditions, see Available Contexts.
Actions
| Feature | Support | What to know |
|---|---|---|
Local actions ( |
Partial |
Resolved relative to the workspace, or relative to the path of the composite action calling them. |
Public actions ( |
Partial |
Downloaded from GitHub and cached on disk. |
Private actions |
Not supported |
Private action sources cannot be reached. |
JavaScript actions |
Supported |
The |
Composite actions |
Partial |
Nesting is limited to 10 levels. Secrets are not available inside composite action children. |
Docker actions |
Partial |
Linux only. A Dockerfile is built before the action runs. Prebuilt images are pulled anonymously, so private images are not available. |
|
Partial |
Accepted as a direct step, as on GitHub Actions. |
Pre and post steps |
Supported |
The |
Environment approval gates
When a job declares environment:, CircleCI inserts an approval job before it. Someone must approve the job in the CircleCI web app before the gated job starts.
The gate is a hold on the pipeline rather than a reproduction of GitHub’s environment protection rules. Read these limits before you rely on it:
-
Reviewer identity is not checked. Any project member with write access to the CircleCI project can approve. Named reviewers, team restrictions, and self-approval prevention are not enforced.
-
Every environment is gated. An environment with no protection rules in GitHub still holds the pipeline until someone approves it.
-
A false
if:condition still holds the pipeline. The gated job runs once approved and then reports as skipped, so the pipeline waits for input either way. -
A matrix job gets one gate. A single approval covers the whole fan-out.
-
The object form needs a name. An
environment:block that sets onlyurl:has no environment name to gate on, so CircleCI emits a warning and inserts no approval job. -
wait_timeranddeployment_branch_policyare not translated. Neither are deployment status URLs.
Environment-scoped secrets and variables are not resolved separately from your other secrets and variables.
Actions that set the path
Some widely used setup actions, including actions/setup-python, put a tool on the path by calling the add-path workflow command. That command is disabled, so the action itself succeeds, but later run: steps do not pick up the version it installed and fall back to whatever is already on the path.
That silent difference is the most common way a workflow passes on CircleCI while doing something other than what you expect. If your workflow pins a tool version through a setup action, add the tool to GITHUB_PATH yourself, or set the full path in the steps that need it.
Checkout, artifacts, and caching
CircleCI intercepts these actions and handles them natively, so they work without needing GitHub’s storage services.
| Action | Support | What to know |
|---|---|---|
|
Partial |
All versions are intercepted. The |
|
Partial |
The |
|
Partial |
Restoring and saving both work. The |
|
Partial |
Subject to the same limits as |
ACTIONS_RUNTIME_TOKEN is not set. An action that expects this variable, such as the upstream JavaScript client behind actions/cache, does not find it.
|
Reusable workflows
| Feature | Support | What to know |
|---|---|---|
Local calls ( |
Supported |
Resolved from your repository. |
Public calls ( |
Partial |
Resolved from GitHub when the workflow runs. |
Inputs |
Supported |
Static |
Call outputs |
Not supported |
A called workflow cannot return outputs to its caller. A workflow that declares call outputs is rejected when it is parsed. |
|
Not supported |
Pass secrets explicitly instead. |
Private reusable workflows |
Not supported |
Only local paths and public references are resolved. |
Dynamic workflow paths |
Not supported |
The path to a called workflow must be static. |
Secrets, variables, and tokens
| Feature | Support | What to know |
|---|---|---|
|
Partial |
Resolved from the job environment, matching names without regard to case. Set these values as project environment variables, as described in Set an Environment Variable in a Project. Contexts are not used yet, because the translation cannot tell which context holds a given secret. Secrets are not available in |
|
Partial |
Resolved from a single flat set of values. The organization, repository, and environment scoping that GitHub applies is not reproduced. |
|
Partial |
A GitHub App installation token, scoped to the job. Injected when |
|
Partial |
Only |
GitHub Packages, Releases, Checks, and Deployments |
Not supported |
These GitHub services are not emulated. |
OIDC tokens
A job that declares permissions: id-token: write, or permissions: write-all, can request an OIDC token.
|
The tokens are issued by CircleCI, not by GitHub. A trust policy that trusts GitHub’s issuer rejects them. Migrate the OIDC trust relationship on your cloud provider, whether that is AWS IAM, Google Cloud Workload Identity, or Microsoft Entra ID. For the token format and the claims to trust, see the Using OpenID Connect Tokens in Jobs page. |
OIDC tokens are not available to Docker action steps, or to any job that sets a job-level container: key. In both cases the step runs in a container that cannot reach the token endpoint on the host.
Service containers
Service containers work as they do on GitHub Actions. CircleCI starts them on a per-job Docker network before your steps run.
| Feature | Support | What to know |
|---|---|---|
|
Supported |
The |
Health checks |
Supported |
A service with a Docker health check must report healthy before your steps run. |
Port mapping |
Supported |
Published ports are available through the |
Registry credentials |
Supported |
CircleCI logs in to your registry before pulling the image. |
Available contexts
Contexts are available in different places depending on whether you use them in a job condition or a step condition. The table below shows where each context can be used, not how completely it is populated. The github and github.event contexts are both partial, so read GitHub Context Values and Event Payload Values before relying on a specific key.
| Context | Job if |
Step if |
|---|---|---|
|
Yes |
Yes |
|
Yes |
Yes |
|
Yes |
Yes |
|
Yes |
Yes |
|
Yes |
Yes |
|
Yes |
Yes |
|
Yes |
Yes |
|
Yes |
Yes |
|
No |
Yes |
|
No |
Yes |
|
No |
Yes |
|
No |
No |
|
No |
No |
GitHub context values
CircleCI derives the github context from your pipeline, so most keys hold the value you would expect and a few differ.
| Key | Value |
|---|---|
|
Your repository, its owner, and its ID. |
|
The |
|
The full 40-character SHA of the commit CircleCI checked out. |
|
The tag when the pipeline was triggered by a tag, and the branch otherwise. |
|
The base and head branches. Populated for pull request events only. |
|
The GitHub user who triggered the pipeline. Both hold the same value. |
|
The translated event name. See How CircleCI Triggers Your Workflow. |
|
The |
|
The CircleCI pipeline ID and pipeline number. |
|
Always the |
|
The |
The following keys have no CircleCI equivalent and keep their default values: github.actor_id, github.repository_owner_id, github.ref_protected, github.run_attempt, and github.secret_source. github.retention_days is always 90.
Four differences can change how a workflow behaves:
-
github.event_namecan be empty. CircleCI does not guess an event name it cannot translate, so a condition such asif: github.event_name == 'push'is false rather than wrongly true on those pipelines. Handle the empty value if your workflow branches on the trigger. -
github.run_idis a UUID, not a number. CircleCI’s pipeline ID is a UUID and has no numeric equivalent, so a workflow that does arithmetic ongithub.run_iddoes not work here. -
On a pull request, the refs describe the head branch. GitHub sets
github.reftorefs/pull/<number>/mergeandgithub.shato an ephemeral merge commit. CircleCI checks out the head branch instead, sogithub.refisrefs/heads/<head-branch>andgithub.shais the head SHA. Usegithub.event_name == 'pull_request'withgithub.base_refandgithub.head_refrather than testing forrefs/pull/. -
The GitHub URLs are always
github.com. GitHub Enterprise Server is not supported.
Event payload values
For push and pull request pipelines, CircleCI builds a partial event payload and writes it to the path in GITHUB_EVENT_PATH. Both ${{ github.event.* }} expressions and shell steps that read the file see real values. For schedule, API, and custom webhook pipelines there is no payload, and github.event.* returns an empty string.
-
Push events populate
ref,after, andsender.login. -
Pull request events populate
action,number,sender.login, andpull_request.number,.title,.url,.draft,.head.ref,.head.sha,.base.ref, and.base.sha.
A field whose value is absent is left out of the payload rather than set to an empty value. A condition such as if: github.event.pull_request.draft == false therefore works on a pull request that does not supply the field.
Everything else is unavailable. That includes commits, head_commit, before, and pusher on a push, and body, state, labels, user.login, mergeable, requested_reviewers, and the repository sub-objects on a pull request.