Skip to main content
In this lesson we expand a simple GitHub Actions workflow to demonstrate:
  • manual triggers (workflow_dispatch),
  • transferring files between jobs using artifacts,
  • avoiding race conditions by ordering jobs with needs,
  • and how to skip CI when pushing changes.
This guide walks through the workflow step-by-step with practical YAML examples and troubleshooting tips.

1. Initial demo workflow (manual trigger)

This workflow, named Demo-2, runs only when manually triggered from the Actions tab (workflow_dispatch). It contains a single build job that creates hello.txt:
After committing and pushing this file you must manually trigger it from the Actions tab because it does not run on push or other events.

2. Understanding existing CI workflows and skipping CI on push

If your repository already has another workflow that triggers on push, pushing commits can inadvertently trigger that existing workflow. To avoid triggering push-based workflows while you push changes, include [skip CI] or [ci skip] in your commit message.
Include [skip CI] (or [ci skip]) in the commit message to prevent workflows that trigger on push from running for that commit.
A common CI workflow configuration that supports both push and manual dispatch looks like this:

3. Adding a second job (and the inter-job file-sharing problem)

Next, we add a test job that expects to read hello.txt created by the build job:
Because each job runs on its own runner (a separate virtual machine), files produced in one job are not automatically available in another. The test job will typically fail with:

4. Use artifacts to transfer files between jobs

To share files between jobs, use actions/upload-artifact in the producing job and actions/download-artifact in the consuming job. These actions are available in the GitHub Marketplace (search for “artifact”).
A screenshot of the GitHub Marketplace in dark mode showing search results for "artifact" under Actions, with action cards like Cache, Upload a Build Artifact, and Download a Build Artifact. The page header reads "Enhance your workflow with extensions" and includes a prominent search box.
Example: upload the file in build and download it in test:
Notes:
  • actions/upload-artifact@v4 creates a named artifact (hello-file) that persists for the run.
  • actions/download-artifact@v4 finds that artifact by name and restores the file(s) into the runner workspace.

5. Race condition when jobs run in parallel

By default, jobs that have no explicit dependency may run in parallel. If test starts before build has finished uploading the artifact, the download will fail with an artifact-not-found error:
This failure usually happens because the test job started before build finished:
A dark-mode GitHub Actions run details page for a workflow named "Demo-2 #3" showing the overall run marked Failure. The build job passed but the test job failed with an artifact-not-found error.

6. Make one job depend on another with needs

To ensure test runs only after build completes, add the needs keyword to the test job:
  • needs: build guarantees test will not start until build has completed (and the artifact is uploaded).
  • needs accepts an array when a job depends on multiple jobs, for example: needs: [build, job-xyz].
  • If you specify a non-existent job in needs, the workflow will fail to parse or run.
Do not reference job names that don’t exist in needs (for example: needs: [build, job-xyz] where job-xyz is not defined). That causes the workflow to fail to parse or execute.

7. Successful artifact download logs (example)

When test runs after build finishes, the download-artifact step will find and download the artifact. Example logs show the download flow and the restored file:

Summary and quick reference

  • Jobs run on separate runners and do not share the filesystem by default.
  • Use actions/upload-artifact@v4 to upload files from a job.
  • Use actions/download-artifact@v4 to download artifacts in subsequent jobs.
  • Use needs to serialize jobs so a job waits for one or more other jobs to finish.
  • Use [skip CI] or [ci skip] in commit messages to avoid triggering push-based workflows.
Quick reference table:
FeaturePurposeExample
Manual triggerRun workflow from Actions UIon: workflow_dispatch
Upload artifactPersist files from a jobuses: actions/upload-artifact@v4
Download artifactRestore files in another jobuses: actions/download-artifact@v4
Job dependencyEnsure job orderneeds: build or needs: [build, job-xyz]
Skip CI on pushPrevent push workflows from runninginclude [skip CI] in commit message
That covers uploading/downloading artifacts between jobs and controlling job order using needs.

Watch Video