Skip to main content
In this lesson we’ll convert the Solar System CI pipeline from Jenkins into a GitHub Actions workflow. This guide assumes you have basic familiarity with GitHub Actions; two concise workflow examples are provided first to illustrate syntax and common patterns. After that we walk through a minimal, practical conversion of the Jenkins pipeline and cover mapping considerations (tools, agents, credentials, and test runtime). Quick note: this is a manual, minimal conversion to get the CI pipeline running in GitHub Actions. Later lessons will show using the GitHub Actions importer to automate parts of this migration.
A dark-themed Jenkins dashboard showing a list of CI pipeline jobs with status icons, names, last success/failure times and durations. The left sidebar shows navigation items like New Item, Build History, Manage Jenkins, and build queue/executor status.

Two quick GitHub Actions examples

Example: minimal scripted-style workflow
Example: using shell commands and an external API inside a job

Locate the Jenkins pipeline and repository

The Jenkins job we’re migrating is a manual-trigger job (no SCM webhook triggers). It is stored in this GitHub repository:
  • Repository: https://github.com/jenkins-demo-org/solar-system
  • Branch: main
Open the repository in GitHub and create a new workflow file under .github/workflows/.
A dark-theme screenshot of a GitHub repository page for "solar-system" (jenkins-demo-org) showing the main branch file list (Dockerfile, Jenkinsfile, README.md, app.js, etc.). The right sidebar shows repository details like stars, forks, and language usage.

Review the Jenkinsfile: what to map

Inspect the Jenkinsfile to identify stages, tools, agents, and credentials. Here is a simplified excerpt showing the key structure and stages to map to Actions:

Key mapping considerations

  • Jenkins stages can be mapped to:
    • Separate GitHub Actions jobs — good for parallelism and isolation, and for using needs: to control ordering.
    • Steps inside a single job — keeps everything on the same runner sequentially, useful if you need a consistent environment between stages.
  • Jenkins tools and agent { docker { image } } choices:
    • Use actions/setup-node to install Node on the runner, or
    • Use container: node:24 at the job level to run all steps inside that Docker image (closer to Jenkins Docker agent behavior).
  • Jenkins credentials become GitHub Secrets (repository or org-level). Use secrets. in Actions to pass them as environment variables.
  • Test reports: in Jenkins the pipeline used junit. In Actions you can upload test-results.xml as an artifact and/or use community actions to parse JUnit output and annotate the run.

Minimal functional conversion

A minimal conversion that mirrors Jenkins “Installing Dependencies” and “Unit Testing” as steps in a single GitHub Actions job looks like this. Save as .github/workflows/solar-system-ci.yml:
Notes:
  • To run the job inside the same Node Docker image used by Jenkins, uncomment container: node:24. Then all steps execute inside that container.
  • The app’s unit tests may require MongoDB connection details. In Jenkins these were injected via credentials — in Actions you must supply equivalent secrets (see the callout below).
Store sensitive values like MONGO_URI, MONGO_USERNAME, and MONGO_PASSWORD as GitHub Secrets (Repository → Settings → Secrets & variables → Actions). Reference them in the workflow with env: or per-step env: using the secrets. context (for example env: MONGO_URI: ${{ secrets.MONGO_URI }}).

Example: passing secrets to the job

Common runtime failure: undefined DB URI

When this workflow was first executed, the npm test step failed because the MongoDB URI was not supplied. Example trimmed output:
Why this happened:
  • The tests attempt to connect to MongoDB via a URI provided by environment variables. The workflow did not inject those secrets, so mongoose.connect() received undefined and the test runner exited with a non-zero code.
How to fix this:
  • Add the required secrets to the repository or organization (recommended for real credentials), or
  • Use a GitHub Actions service container to run a temporary MongoDB instance for tests, or
  • Mock the database connections in tests so they do not require a running DB.
Example service container (run MongoDB as a service container for the job):

Converting remaining stages

Convert the remaining Jenkins stages (dependency scanning, coverage, image build & publish, Trivy scanning) into discrete jobs. Recommendations:
  • Model each logical Jenkins stage as an Actions job for clarity and failure isolation:
    • dependency-scan (uses language-specific scanners),
    • unit-test (JUnit reporting, upload test artifacts),
    • coverage (upload coverage artifacts, publish to coverage services),
    • build-and-publish-image (build Docker image, push to registry using secrets),
    • trivy-scan (scan image artifacts; fail on high-severity vulnerabilities).
  • Use needs: to preserve ordering (e.g., coverage should need: [unit-test], and build-and-publish-image should need: [coverage]).
  • Use actions/upload-artifact for test reports and coverage files, or use community actions to parse JUnit and produce GitHub annotations.
That’s all for this lesson. A follow-up article will show:
  • Wiring up repository/organization secrets,
  • Adding JUnit parsing and annotations,
  • Converting the remainder of the Jenkins pipeline with needs: and containerized jobs,
  • Using the GitHub Actions importer to help automate the migration.

Watch Video