Creating multiple plans using Bamboo Java Specs linked to a single repository

Still need help?

The Atlassian Community is here for you.

Ask the community


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.

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:

<project-name>/bamboo-specs/src/main/java/myproduct/Plan1Spec.java
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:

<project-name>/bamboo-specs/src/main/java/myproduct/Plan2Spec.java
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.

<project-name>/bamboo-specs/src/main/java/myproduct/PlanSpec.java
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);
    }
}

Official Bamboo Specs documentation:


Last modified on Aug 30, 2021

Was this helpful?

Yes
No
Provide feedback about this article
Powered by Confluence and Scroll Viewport.