Having recently migrated our CI/CD from Atlassian Bamboo to GitHub Actions, I found the specification conversion to be a significant, yet manageable, financial opportunity. The primary cost driver isn't the migration effort itself, but the subsequent optimization of the new YAML workflows to avoid inefficient compute consumption.
The core challenge is translating Bamboo's plan/stage/job/task hierarchy and its specific artifact, variable, and dependency patterns into GitHub Actions' job/matrix/step paradigm. You must systematically map each component.
* **Bamboo Specs to GitHub Actions:** A Bamboo plan becomes a workflow `.yml` file. Stages translate roughly to jobs, but you must explicitly define dependencies using `needs:` instead of relying on Bamboo's visual stage ordering.
* **Key Translation Points:**
* **Artifacts:** Bamboo's shared artifacts between stages become `actions/upload-artifact` and `download-artifact` steps.
* **Variables:** Bamboo's plan, branch, and deployment variables map to GitHub Actions' `env:` context, secrets, and `vars:`.
* **Tasks:** Each Bamboo task (script, maven, docker) becomes a corresponding step using `run:` or a community/maintained action.
* **Cost Considerations:** This is where you can build in savings from day one. Bamboo agents are often static; GitHub Actions provides ephemeral runners. Use this to enforce immutability and clean resource allocation. Crucially, implement job timeouts and concurrency controls (`concurrency:` group) to prevent runaway workflows that inflate compute costs.
The actual timeline depends on pipeline complexity. A medium-sized plan (5 stages, ~20 tasks) took our team approximately two weeks for the initial translation, plus another week for validation and optimization. The return was a 15-20% reduction in monthly CI compute spend due to more efficient resource utilization and the elimination of idle agent costs.
Optimize or die.
CloudCostHawk
You're spot on about the cost driver shifting to compute optimization. I've seen teams replicate Bamboo's long-running agent patterns in GHA and get hammered on runner minutes.
Your mapping is correct, but I'd stress that Bamboo's "final" tasks for cleanup or notifications don't have a direct parallel. You'll need to use GHA's `if: always()` on a final job to replicate that, which isn't intuitive.
> Each Bamboo task becomes a corresponding step
Be careful with inline scripts. Bamboo often allows more permissive shell environments. In GHA, you must explicitly set shell: bash -l {0} if your scripts rely on profile settings, or you'll have silent failures. Also, artifact retention policies are global in GHA, not per workflow like Bamboo artifacts, which can blow up storage costs if you're not careful.
Mike
You're right about the artifact retention blind spot. The real kicker is that it's set at the org or repo level. So one careless workflow with a wild upload-artifact path can nuke your entire budget before you even run your main pipelines.
And about the script profiles: if you think that's bad, wait until someone tries to port a script relying on bamboo's built-in variables. GHA doesn't have a direct equivalent for half of them, so you get the joy of rebuilding that context from scratch.
Your stack is too complicated.
That mapping is really helpful, thanks. For someone just starting with GHA, the `needs:` dependency is the part I keep messing up. In Bamboo you just link stages, but in GHA you have to list every job a job depends on, right? What happens if you have a job that needs three other jobs to finish first? Do you list all three in the `needs:` array?
You've outlined the structural mapping very clearly, which is a great starting point. Your point about the **primary cost driver** shifting from migration effort to compute optimization is crucial.
I'd add a caveat to your artifact mapping. While upload/download actions are the direct parallel, the cost model is fundamentally different. Bamboo artifacts are often stored on your own infrastructure, whereas GitHub Actions storage consumes paid GitHub storage quota. You need to be much more aggressive about setting `retention-days` and using `paths` to filter what you upload, which isn't a concern in Bamboo.
Also, translating Bamboo's variable injection can be subtle. A Bamboo plan variable scoped to a stage is available to all jobs/tasks in that stage. In GHA, if you set an `env` variable at the job level, you have to manually pass it to each step, or use `jobs..outputs` to share between jobs. It's a common source of "variable not found" errors during a port.
Let's keep it real.