Before we plug security tools into anything, we need a repository, a pipeline, and a working build. In Part 2 of our GitHub DevSecOps series, Patrick Steger and I create a private GitHub repo for a small Java Spring Boot service, enable GitHub Actions, and wire up a two-workflow pipeline that compiles the code and runs the unit tests. This is the skeleton everything else in the series hangs on.
The Application We’re Building Around#
We use the same simple Java Spring Boot application throughout the series — a web service that returns “Spring is here!” plus a unit test that calls the service and verifies the response. Small enough to read in one screen, real enough to demonstrate every DevSecOps tool we will add over the next ten sessions.
Prerequisites and Licensing#
GitHub can be used as SaaS in the cloud or installed on premise via GitHub Enterprise. The thing to know up front: if you want a private repository and the Advanced Security features, you need an Enterprise license. We are going to use both, so that is what we run on. If you only need public repositories, the free tier covers a lot.
Creating the Repository#
Sign in, click New, and you get the option to import an existing repo or start fresh. We start fresh. Owner is our enterprise account. Repository name is DevSecOpsDemo. Visibility is private. We skip the README, .gitignore, and license templates for the demo, but in a real project you absolutely want them.
Once the repo exists, take a quick tour of the tabs:
- Code — the repository itself
- Issues — basic issue tracking; works for backlog management too
- Pull requests — covered in a later session
- Actions — where our pipelines live
- Projects — lightweight project management
- Wiki — code documentation
- Security — the tab we will use heavily for SAST, SCA, secret scanning
- Insights — contributor stats and the dependency graph
- Settings — repo configuration
Enabling Actions Safely#
If the Actions tab is missing, head to Settings → Actions → General and enable Actions there. Worth pausing here, because this is the first real security decision you make on a GitHub project.
Actions are small custom applications. They are usually code you did not write, running inside your pipeline, with potential access to secrets. You get four levels:
- Allow every action from the marketplace
- Allow only enterprise actions
- Allow enterprise actions plus a specific allowlist
- Disable actions
From a pure security standpoint, the safest model is “enterprise actions only” — review the community actions you want, copy them into your enterprise space, security-review them, and use those copies. For this demo we accept everything to keep moving, but in an enterprise environment you should not.
Importing the Code#
Back to the Code tab → Import code. We point GitHub at our existing project, wait a moment, and the source tree shows up: the Spring Boot application under src/main/java, the controller that returns “Spring is here!”, and the tests under src/test.
Two Workflows: Main Pipeline and Build Pipeline#
GitHub calls pipelines workflows, and they live in .github/workflows/. We split our pipeline into two files on purpose: a main pipeline that orchestrates everything, and a build pipeline it calls. Splitting workflows keeps each file small and lets you reuse the build pipeline from other workflows later.
Create .github/workflows/main-pipeline.yml. Tip: GitHub’s file editor lets you type slashes in the filename to create folders inline. The main pipeline gets a clear, numbered name (00 - Main CI/CD Pipeline), triggers on push to main (with sensible path-ignore filters) and on workflow_dispatch so we can run it manually, and defines a build job that calls our build.yml and forwards the secrets it needs.
Numbered names — 00 - Main, 10 - Build — sound trivial but they make the Actions UI readable when you have a dozen workflows running side by side. Recommended.
Next file: .github/workflows/build.yml. Name it 10 - Build Pipeline. Triggers are workflow_dispatch (run manually) and workflow_call (callable from another workflow — this is what main-pipeline uses).
The build job declares the permissions it needs, runs on ubuntu-latest, and chains a series of steps that each call an action. The actions: check out the source with actions/checkout@v3, set up Java, compile with Maven, prepare an output directory, run the tests, prepare the test result directory, upload the application binary as an artifact, upload the test results as a downloadable zip, and publish the test results into the GitHub UI.
Commit both files to main and head over to Actions.
Watching the Pipeline Run#
The Actions tab shows the main pipeline kicking off and the build pipeline running underneath it — the numbered names line them up neatly. Click in and you get a summary page: total duration, status, jobs executed, three tests found, the application binary and test results listed as artifacts (downloadable as zip), and the test results rendered inline. Click the build job and the full log is right there.
Where Actions Come From#
We used actions/checkout@v3 without much explanation. That comes from the GitHub Marketplace, the place to discover Actions. The Checkout action is provided by a verified creator — GitHub vouched for them. Verified creators are your safer choice. Even safer: copy a verified action’s source into your enterprise repo, security-review it, and consume it from there. That is the model you want when production code depends on it.
Key Takeaways#
Pick the licensing tier that matches what you want to build. Private repos plus Advanced Security need GitHub Enterprise. Decide upfront — it shapes everything else.
Enable Actions deliberately, not by default. The “allow everything from the marketplace” option is convenient and risky. In an enterprise context, “enterprise-only” plus a curated allowlist is the right baseline.
Workflows live in
.github/workflows/. That folder is the entire pipeline configuration surface. Knowing it exists is half the battle.Split workflows for orchestration and reuse. A main pipeline that calls a build pipeline (via
workflow_call) keeps each file small and lets you compose larger pipelines later without rewriting the build.Use a naming scheme like
00 - Main,10 - Build. It looks pedantic until you have ten workflows. Then it is the only thing that keeps the Actions UI readable.Use verified Actions, or import them into your enterprise. Marketplace Actions run inside your pipeline with access to your secrets. Treat them as third-party code. Verified creators are the floor; enterprise-imported and reviewed copies are the ceiling.
