Creating multiple plans using Bamboo Java Specs linked to a single repository
Platform notice: Server and Data Center only. This article only applies to Atlassian products on the Server and Data Center platforms.
Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.
*Except Fisheye and Crucible
Summary
You have many Plans in Bamboo linked to the same repository and want to move from native Bamboo Plan format to Java Specs format.
You want to optionally enable Repository Stored Specs (RSS) in Bamboo for the same repository.
Environment
This applies to any Bamboo version since Bamboo 6.2 which introduced support for storing Bamboo Specs within a repository.
Solution
Moving to Java Specs
Export your Plan in Java Spec format
The first thing you need to do is export your Plan in a Java Spec format.
Create a plan using Maven Archetype
You'll have to use Maven Archetype to create a project base for each Plan you have and then use it to push your changes to your Bamboo Server.
- Tutorial: Create a simple plan with Bamboo Java Specs
- Notice: During the initial plan creation, you will have to replace the generated Java specs with the ones you just exported from the previous step
- If you are planning to have multiple Plans on the same Java Specs, you can use the same project base as well. Refer to "Running multiple Bamboo Spec Plans from the same repository" below
Manage your Bamboo Specs plans from a linked-repository
Storing Bamboo Specs in a repository allows you to keep your project configuration together with the code and automatically publish any code changes. It also gives you access to the history of plan specifications and makes it easy to revert to a particular moment in time.
Multiple files
Running multiple Bamboo Spec Plans from the same repository
If you are looking into running multiple projects and plans from a single repository you can add multiple Plans to the same codebase and invoke them as the examples listed in this session.
You can have multiple files containing java classes in your Specs project. This allows you to have more flexibility as you can make your code modular and allow other developers to have independent control over their builds. At the same time, you will need to make sure your classes names are not duplicated.
Notice that the .linkedRepositories("MyProjectRepo") shown below, is the same on both files, meaning both plans are using the same linked Repository.
Plan 1 of My Project:
package myproduct;
import com.atlassian.bamboo.specs.api.BambooSpec;
import com.atlassian.bamboo.specs.api.builders.BambooKey;
import com.atlassian.bamboo.specs.api.builders.BambooOid;
import com.atlassian.bamboo.specs.api.builders.permission.PermissionType;
import com.atlassian.bamboo.specs.api.builders.permission.Permissions;
import com.atlassian.bamboo.specs.api.builders.permission.PlanPermissions;
import com.atlassian.bamboo.specs.api.builders.plan.Job;
import com.atlassian.bamboo.specs.api.builders.plan.Plan;
import com.atlassian.bamboo.specs.api.builders.plan.PlanIdentifier;
import com.atlassian.bamboo.specs.api.builders.plan.Stage;
import com.atlassian.bamboo.specs.api.builders.plan.branches.BranchCleanup;
import com.atlassian.bamboo.specs.api.builders.plan.branches.PlanBranchManagement;
import com.atlassian.bamboo.specs.api.builders.plan.configuration.ConcurrentBuilds;
import com.atlassian.bamboo.specs.api.builders.project.Project;
import com.atlassian.bamboo.specs.builders.task.CheckoutItem;
import com.atlassian.bamboo.specs.builders.task.ScriptTask;
import com.atlassian.bamboo.specs.builders.task.VcsCheckoutTask;
import com.atlassian.bamboo.specs.util.BambooServer;
@BambooSpec
public class Plan1Spec {
public Plan plan() {
final Plan plan = new Plan(new Project()
.key(new BambooKey("MY"))
.name("MyProject")
.description("My Project"),
"Plan1",
new BambooKey("PRO1"))
.description("My Plan 1")
.pluginConfigurations(new ConcurrentBuilds())
.stages(new Stage("Stage 1")
.jobs(new Job("Hello World!",
new BambooKey("HELO"))
.description("Hello Cruel World")
.tasks(new VcsCheckoutTask()
.description("Checkout Default Repository")
.checkoutItems(new CheckoutItem().defaultRepository()),
new ScriptTask()
.description("Hello world")
.inlineBody("echo \"Hello World\""))),
new Stage("Stage 2")
.jobs(new Job("Goodbye World!",
new BambooKey("GBYE"))
.description("Goodbye Lovely World")
.tasks(new VcsCheckoutTask()
.description("Checkout Default Repository")
.checkoutItems(new CheckoutItem().defaultRepository()),
new ScriptTask()
.description("Goodbye World")
.inlineBody("echo \"Goodbye World\""))))
.linkedRepositories("MyProject")
.planBranchManagement(new PlanBranchManagement()
.delete(new BranchCleanup())
.notificationForCommitters());
return plan;
}
public static void main(String... argv) {
//By default credentials are read from the '.credentials' file.
BambooServer bambooServer = new BambooServer("https://bamboo.myproject.com");
final Plan1Spec planSpec = new Plan1Spec();
final Plan plan = planSpec.plan();
bambooServer.publish(plan);
}
}
Plan 2 of My Project:
package myproduct;
import com.atlassian.bamboo.specs.api.BambooSpec;
import com.atlassian.bamboo.specs.api.builders.BambooKey;
import com.atlassian.bamboo.specs.api.builders.BambooOid;
import com.atlassian.bamboo.specs.api.builders.permission.PermissionType;
import com.atlassian.bamboo.specs.api.builders.permission.Permissions;
import com.atlassian.bamboo.specs.api.builders.permission.PlanPermissions;
import com.atlassian.bamboo.specs.api.builders.plan.Job;
import com.atlassian.bamboo.specs.api.builders.plan.Plan;
import com.atlassian.bamboo.specs.api.builders.plan.PlanIdentifier;
import com.atlassian.bamboo.specs.api.builders.plan.Stage;
import com.atlassian.bamboo.specs.api.builders.plan.branches.BranchCleanup;
import com.atlassian.bamboo.specs.api.builders.plan.branches.PlanBranchManagement;
import com.atlassian.bamboo.specs.api.builders.plan.configuration.ConcurrentBuilds;
import com.atlassian.bamboo.specs.api.builders.project.Project;
import com.atlassian.bamboo.specs.builders.task.CheckoutItem;
import com.atlassian.bamboo.specs.builders.task.ScriptTask;
import com.atlassian.bamboo.specs.builders.task.VcsCheckoutTask;
import com.atlassian.bamboo.specs.util.BambooServer;
@BambooSpec
public class Plan2Spec {
public Plan plan() {
final Plan plan = new Plan(new Project()
.key(new BambooKey("MY"))
.name("MyProject")
.description("My Project"),
"Plan2",
new BambooKey("PRO2"))
.description("My Plan 2")
.pluginConfigurations(new ConcurrentBuilds())
.stages(new Stage("Stage 1")
.jobs(new Job("Hello World!",
new BambooKey("HELO"))
.description("Hello World")
.tasks(new VcsCheckoutTask()
.description("Checkout Default Repository")
.checkoutItems(new CheckoutItem().defaultRepository()),
new ScriptTask()
.description("Hello world")
.inlineBody("echo \"Hello World\""))))
.linkedRepositories("MyProjectRepo")
.planBranchManagement(new PlanBranchManagement()
.delete(new BranchCleanup())
.notificationForCommitters());
return plan;
}
public static void main(String... argv) {
//By default credentials are read from the '.credentials' file.
BambooServer bambooServer = new BambooServer("https://bamboo.myproject.com");
final Plan2Spec planSpec = new Plan2Spec();
final Plan plan = planSpec.plan();
bambooServer.publish(plan);
}
}
Single file
You can also use a single file that would contain all your plans. Please be mindful that this is just an example and you may have to adapt the code to your needs.
package myproduct;
import com.atlassian.bamboo.specs.api.BambooSpec;
import com.atlassian.bamboo.specs.api.builders.BambooKey;
import com.atlassian.bamboo.specs.api.builders.BambooOid;
import com.atlassian.bamboo.specs.api.builders.permission.PermissionType;
import com.atlassian.bamboo.specs.api.builders.permission.Permissions;
import com.atlassian.bamboo.specs.api.builders.permission.PlanPermissions;
import com.atlassian.bamboo.specs.api.builders.plan.Job;
import com.atlassian.bamboo.specs.api.builders.plan.Plan;
import com.atlassian.bamboo.specs.api.builders.plan.PlanIdentifier;
import com.atlassian.bamboo.specs.api.builders.plan.Stage;
import com.atlassian.bamboo.specs.api.builders.plan.branches.BranchCleanup;
import com.atlassian.bamboo.specs.api.builders.plan.branches.PlanBranchManagement;
import com.atlassian.bamboo.specs.api.builders.plan.configuration.ConcurrentBuilds;
import com.atlassian.bamboo.specs.api.builders.project.Project;
import com.atlassian.bamboo.specs.builders.task.CheckoutItem;
import com.atlassian.bamboo.specs.builders.task.ScriptTask;
import com.atlassian.bamboo.specs.builders.task.VcsCheckoutTask;
import com.atlassian.bamboo.specs.util.BambooServer;
@BambooSpec
public class PlanSpec {
public Plan plan1() {
final Plan plan = new Plan(new Project()
.key(new BambooKey("MY"))
.name("MyProject")
.description("My Project"),
"Plan1",
new BambooKey("PRO1"))
.description("My Plan 1")
.pluginConfigurations(new ConcurrentBuilds())
.stages(new Stage("Stage 1")
.jobs(new Job("Hello World!",
new BambooKey("HELO"))
.description("Hello World")
.tasks(new VcsCheckoutTask()
.description("Checkout Default Repository")
.checkoutItems(new CheckoutItem().defaultRepository()),
new ScriptTask()
.description("Hello world")
.inlineBody("echo \"Hello World\""))),
new Stage("Stage 2")
.jobs(new Job("Goodbye World!",
new BambooKey("GBYE"))
.description("Goodbye World")
.tasks(new VcsCheckoutTask()
.description("Checkout Default Repository")
.checkoutItems(new CheckoutItem().defaultRepository()),
new ScriptTask()
.description("Goodbye World")
.inlineBody("echo \"Goodbye World\""))))
.linkedRepositories("MyProjectRepo")
.planBranchManagement(new PlanBranchManagement()
.delete(new BranchCleanup())
.notificationForCommitters());
return plan;
}
public Plan plan2() {
final Plan plan = new Plan(new Project()
.key(new BambooKey("MY"))
.name("MyProject")
.description("My Project"),
"Plan2",
new BambooKey("PRO2"))
.description("My Plan 2")
.pluginConfigurations(new ConcurrentBuilds())
.stages(new Stage("Stage 1")
.jobs(new Job("Hello World!",
new BambooKey("HELO"))
.description("Hello World")
.tasks(new VcsCheckoutTask()
.description("Checkout Default Repository")
.checkoutItems(new CheckoutItem().defaultRepository()),
new ScriptTask()
.description("Hello world")
.inlineBody("echo \"Hello World\""))))
.linkedRepositories("MyProjectRepo")
.planBranchManagement(new PlanBranchManagement()
.delete(new BranchCleanup())
.notificationForCommitters());
return plan;
}
public static void main(String... argv) {
//By default credentials are read from the '.credentials' file.
BambooServer bambooServer = new BambooServer("https://bamboo.myproject.com");
final PlanSpec planSpec = new PlanSpec();
final Plan plan1 = planSpec.plan1();
bambooServer.publish(plan1);
final Plan plan2 = planSpec.plan2();
bambooServer.publish(plan2);
}
}