A workflow is made up of one or more jobs, using the jobs keyword.
Jobs run in parallel by default.
To run jobs sequentially, define dependencies on other jobs using the jobs.<job_id>.needs keyword.
You can run an unlimited number of jobs as long as you are within the workflow usage limits.
jobs: my-job: steps: - name: My step env: SERVER: development uses: docker://alpine:3.18 run: echo "Hello $SERVER" #prints "Hello development"
jobs.<job_id>
Use jobs.<job_id> to assign a unique identifier to a workflow job. Replace <job_id> with a string that uniquely identifies the job within the jobs object. Reference this identifier in other jobs as needed.
The <job_id> must start with a letter and may include only alphanumeric characters, hyphens (-), or underscores (_).
jobs.<job_id>.delegates
Use jobs.<job_id>.delegates to designate a custom job to execute the workflow job.
|
When referring to a file within a repository, the repository clone URL and the repository-internal path must be separated by a double slash For example: https://github.com/myorg/myrepo//path/to/my/file.yaml However, for backward compatibility the double slash |
<job-name>: delegates: <path to any custom job> with: < Use `with` to provide custom job input values>
|
A single workflow job must contain only one of the following execution syntax terms: |
jobs.<job_id>.env
Use jobs.<job_id>.env to define env variables for all steps in a standard job.
Usage example
Use env to set variables for an entire workflow or individual step.
|
env variables with the same name follow specificity precedence. In the following example, the environment variable SERVER: development defined in a step overrides SERVER: production defined in my-job, while the step executes.
my-job: env: SERVER: production steps: - name: My first step env: SERVER: development uses: docker://alpine:3.18 run: echo "Hello $SERVER" #prints "Hello development" - name: My second step uses: docker://alpine:3.18 run: echo "Hello $SERVER" #prints "Hello production"
jobs.<job_id>.vars
When a job calls a reusable workflow using uses:, you can optionally set jobs.<job_id>.vars to inherit to make the caller job’s variables available to the reusable workflow.
Usage example
In the following example:
-
caller-jobinvokes a reusable workflow withuses:. -
vars: inheritexposes all vars in the caller job’s scope to the reusable workflow (including any environment-scoped vars that apply to the caller job). -
The caller also passes
env-prodas an input so the reusable workflow can select an environment for its own jobs. -
Inside the reusable workflow, a job may set its
environmentfrom the input; if that environment defines vars with the same names, those values take precedence.
jobs: caller-job: uses: .cloudbees/workflows/a-reusable-workflow.yaml #Calls a reusable workflow from the current repository. vars: inherit #Inherits **all caller vars** into the reusable workflow’s context. inputs: var-1: ${{ vars.var-A }} #Optionally passes a specific value via `inputs` (useful if you want an explicit parameter alongside inheritance). env-prod: production #Provides the environment name for the reusable workflow to use.
|
jobs.<job_id>.secrets
When a job calls a reusable workflow using uses:, you can control which secrets the called workflow can access by configuring jobs.<job_id>.secrets:
-
inherit— Make all secrets in the caller job’s scope available to the reusable workflow. -
Mapping — Expose only specific secrets by mapping them one-by-one.
Use inherit with trusted reusable workflows only. If a job in the reusable workflow runs in an environment, environment-scoped secrets for that job are resolved and can override inherited or mapped values.
|
If a job sets |
Inherit all secrets
In this example, caller-job invokes a reusable workflow and inherits all secrets from its scope.
jobs: caller-job: uses: .cloudbees/workflows/a-reusable-workflow.yaml #Calls a reusable workflow from the current repository. secrets: inherit #Inherits *all* secrets from the caller job’s scope. inputs: env-prod: production #Passes an environment name as input to the reusable workflow (optional).
Map specific secrets
In this example, only two secrets are exposed to the reusable workflow. No other caller secrets are available.
jobs: caller-job: uses: .cloudbees/workflows/a-reusable-workflow.yaml secrets: #Uses *mapping* instead of inheritance. secret-1: ${{ secrets.SECRET_A }} #Maps caller secret `SECRET_A` to `secret-1` for the reusable workflow. secret-2: ${{ secrets.SECRET_B }} #Maps caller secret `SECRET_B` to `secret-2`. inputs: env-prod: production
|
jobs.<job_id>.environment
Use jobs.<job_id>.environment to define the environment that the job references.
|
Provide the environment as the environment name—either as a literal string or as an expression that resolves to a name:
environment: dev
environment: ${{ inputs.target_env }}
If you use the Register an artifact deployed to an environment action in a workflow run, its target-environment value overrides jobs.<job_id>.environment.
|
Use job.environment in called workflows
Use job.environment to pass the current job’s evaluated environment name to a reusable workflow, avoiding hard-coded strings.
deploy: uses: org/repo/reusable.yaml environment: QA secrets: asecret: ${{ secrets.secret1 }} with: aninput: ${{ vars.avalue }} artifactName: ${{ inputs.artifactName }} artifactVersion: ${{ inputs.artifactVersion }} environment: ${{ job.environment }} #Resolves to "QA".
deploy: uses: org/repo/reusable.yaml environment: ${{ inputs.target_env }} #For example: "QA","staging","prod". with: environment: ${{ job.environment }} #Returns the evaluated name.
jobs.<job_id>.if
Use jobs.<job_id>.if to skip a job, not to force running it if an upstream job failed.
You can use any supported context and expression to create a conditional.
When you use expressions in an if conditional, you may omit the ${{ }} expression syntax because CloudBees automatically evaluates the if conditional as an expression.
However, this rule does not apply everywhere.
You must use the ${{ }} expression syntax or escape with '', "", or () when the expression starts with !, since ! is reserved notation in YAML format.
Using the ${{ }} expression syntax turns the contents into a string, and strings are truthy.
For example, if: true && ${{ false }} evaluates to true.
CloudBees strongly recommends that you avoid mixing use of the ${{ }} expression with other logic, as you may get unexpected results.
|
Contexts
Conditionals can be at both the job and step level. A conditional within a job cannot reference any step outputs, because some steps have not yet run.
jobs.<job_id>.needs
Enter a string or array of strings in jobs.<job_id>.needs to specify that a specific job or jobs must complete successfully before this job runs.
By definition, a job that fails or is skipped is not a successful job completion, and all jobs that need it to complete are skipped, unless explicitly continued by use of a conditional expression.
jobs.<job_id>.outputs
Map outputs for a job with jobs.<job_id>.outputs.
All jobs that depend on this job to run also have these outputs available to them.
outputs specifications:
-
Enter
outputsas Unicode strings up to 4 kB maximum. -
The total of all outputs in a workflow is not to exceed 1 MB.
-
If an output contains a secret, it is redacted and not sent to CloudBees.
-
Job
outputsmapping is evaluated at the end of the job.
Using jobs.<job_id>.outputs is NOT supported in a reusable workflow job.
|
jobs.<job_id>.permissions
Use jobs.<job_id>.permissions to set job-level permissions. Grant only the minimum required permissions (PoLP). Each permission key accepts exactly one scope value. If a key value is unspecified in the job, then the workflow-level value is applied.
For scope and best-practice information, refer to Permissions.
Usage example
The cloudbees.api.token is an OpenID Connect (OIDC) token for accessing CloudBees Unify and third-party APIs.
It does not provide Git repository access.
For key and value details, refer to Permission Scope.
-
Permissions are defined by specifying values for the available scopes within the
permissionsblock:permissions: scm-token-own: read|none scm-token-org: read|none id-token: write|none -
All scopes can be disabled by assigning an empty block:
permissions: {} -
The following example defines permissions for the job
stale. Thescm-token-orgscope is grantedreadaccess, while all other scopes remainnone.jobs: stale: permissions: scm-token-org: read steps: - uses: actions/stale@v5
jobs.<job_id>.timeout-minutes
Use jobs.<job_id>.timeout-minutes to set the number of minutes a job runs before the CloudBees Unify automatically cancels the job.
The total time allowed for a workflow run is 5760 minutes (4 days). All jobs and approvals must be completed within this time.
|
Job type |
Maximum time allowed |
Default value |
Standard |
|
|
Custom |
|
|
|
The |
jobs.<job_id>.uses
Use jobs.<job_id>.uses to specify the path for a
Reusable workflows job. Call a workflow by setting uses: to the repository path of the reusable workflow YAML file.
|
A single workflow job must contain only one of the following execution syntax terms: |
Reusable workflow job usage example
Here’s the example of a job that uses a reusable workflow to perform a deployment.
|
When referring to a file within a repository, the repository clone URL and the repository-internal path must be separated by a double slash For example: https://github.com/myorg/myrepo//path/to/my/file.yaml However, for backward compatibility the double slash |