NAV Navbar
Logo
Java

Introduction

You are reading reference documentation for the Bamboo Specs library. The Bamboo Specs library allows you to define plan configuration as code and send it to Bamboo to have correspoding plans created or updated automatically. You can read more information about Bamboo Specs feature here. In case you are looking for detailed documentation about specific method or class, you can find it in Bamboo Specs JavaDocs.

Version information

This reference documentation is based on Bamboo Specs library version 6.0.1, which is intended for Bamboo version 6.0.1 and higher.

See older versions of documentation

Feedback

In case you found a bug, would like to suggest an improvement or just would like to share your impression about this documentation, please do not hesitate to report it our issue tracker.

Project

Project project = new Project()
    .key("PROA")
    .name("Project A")
    .description("My Project A with all A-plans");

A project is a collection of plans. Projects enable you to easily group and identify plans which are logically related to each other. They are especially useful when generating reports across multiple plans.

A project:

You can create a new project when creating a plan.

Plan

Plan plan = new Plan(project, "My Plan One", "PLAN1")
    .description("This is an example of a plan")
    .enabled(true)
    .stages(stage1)
    .triggers(scheduledTrigger)
    .planBranchManagement(planBranchManagement)
    .dependencies(planDependencies)
    .linkedRepositories(myGitRepo)
    .planRepositories(myBitbucketRepo)
    .variables(var1, var2);

A plan defines everything about your continuous integration build process in Bamboo.

A plan:

Every plan belongs to a project.

Plan branches

Plan branches are used to represent a branch in your version control repository, with the plan branch using the same build configuration as your plan. Tools such as Git and Mercurial encourage a practice called feature branching, where a developer can use a new branch to work in isolation from his or her team members before merging their changes back into main line development.

With plan branches in Bamboo:

You can create plan branches manually or automatically. The branch configuration can be provided on the plan level and customized on the branch level. The settings provided in the branch configuration override the settings provided for the plan.

Automatic branch management

Plan branches can be created and deleted automatically based on the updates in the primary source repository. Automatic branch management is available for Git, Mercurial, and Subversion. For other repository types, you can use manual branching. You can override the default settings for a branch, such as values of the variables. By default, automatic branch management is:

You can specify how often Bamboo checks the primary source repository for new or deleted branches. The default value is 300 seconds. You can also override the branch deletion settings.

Handling new branches

Create new plans for new branches matching JIRA issue key. Build triggers are inherited from the master plan.

Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new GitRepository()
        .name("my-repo")
        .url("ssh://git@bitbucket.org:my-company/my-repo.git")
        .branch("master"))
    .planBranchManagement(new PlanBranchManagement()
        .createForVcsBranchMatching("^JIRA-[0-9]+")
        .triggerBuildsLikeParentPlan());

Handling deleted branches

Create plan branches for all new branches in the repository. Delete plans 30 days after a repository branch is deleted.

Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new GitRepository()
        .name("my-repo")
        .url("ssh://git@bitbucket.org:my-company/my-repo.git")
        .branch("master"))
    .planBranchManagement(new PlanBranchManagement()
        .createForVcsBranch()
        .delete(new BranchCleanup()
            .whenRemovedFromRepositoryAfterDays(30)));

Handling inactive branches

Create plan branches for all new branches in the repository. Delete plans after 30 days of no activity on a repository branch.

Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new GitRepository()
        .name("my-repo")
        .url("ssh://git@bitbucket.org:my-company/my-repo.git")
        .branch("master"))
    .planBranchManagement(new PlanBranchManagement()
        .createForVcsBranch()
        .delete(new BranchCleanup()
            .whenInactiveInRepositoryAfterDays(30)));

Manual branch management

Create three separate plans for ‘master’, ‘release_1_0’ and ‘integration’ branches.

List<Plan> plans = new ArrayList<>();
for (String branch : Arrays.asList("master", "release_1_0", "integration")) {
    Plan plan = new Plan(project, planName(branch), planKey(branch)).planRepositories(new GitRepository().name("my-repo").url("ssh://git@bitbucket.org:my-company/my-repo.git").branch(branch));
    plans.add(plan);
};

Bamboo UI allows to not only set up automatic plan branch creation for new branches detected in a repository, but also to manually create plan branches for already existing ones. Bamboo Specs does not have an option to manually specify plan branches at the moment. You would have to use Bamboo UI to manually create branches after plan is created.

Alternatively, you could create separate plans for each branch. Keep in mind that using this approach you won’t be able to use Bamboo branch-specific features (for instance to see them on the “Branch view” page).

Automatic branch merging

Bamboo provides two merging models if you choose to automate your branch merging. Automatic merging has few limitations:

Branch updater

Create a plan building the ‘master’ branch. Automatically create plan branches for all feature branches as soon as these branches are created. Merge the master branch into a feature branch and build the merge result. Push a merge commit into the feature branch on a successful build.

Plan plan = new Plan(project, "Features with master", "MASTER")
    .stages(new Stage("Stage 1")
        .jobs(new Job("Job1", "JOB1")))
    .planRepositories(new GitRepository()
        .name("my-repo")
        .url("ssh://git@bitbucket.org:my-company/my-repo.git")
        .branch("master"))
    .planBranchManagement(new PlanBranchManagement()
        .createForVcsBranchMatching("feature/.*")
        .branchIntegration(new BranchIntegration()
            .integrationBranchKey("MASTER")
            .gatekeeper(false)
            .pushOnSuccessfulBuild(true)));

A branch repository is kept up-to-date with changes to master. The Branch updater should be used when you want to:

Gatekeeper

Create a plan building the ‘master’ branch. Automatically create a plan branch for the ‘integration’ branch as soon as this branch is created. Merge the integration branch into ‘master’ branch and build the merge result. Push a merge commit into the master on a successful build.

Plan plan = new Plan(project, "Integration into master", "MASTER")
    .stages(new Stage("Stage 1")
        .jobs(new Job("Job1", "JOB1")))
    .planRepositories(new GitRepository()
        .name("my-repo")
        .url("ssh://git@bitbucket.org:my-company/my-repo.git")
        .branch("master"))
    .planBranchManagement(new PlanBranchManagement()
        .createForVcsBranchMatching("integration")
        .branchIntegration(new BranchIntegration()
            .integrationBranchKey("MASTER")
            .gatekeeper(true)
            .pushOnSuccessfulBuild(true)));

In Gatekeeper the default repository is only updated with changes in the branch that have built successfully. The Gatekeeper should be used when you want to:

Branch notifications

Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new GitRepository()
        .name("my-repo")
        .url("ssh://git@bitbucket.org:my-company/my-repo.git")
        .branch("master"))
    .planBranchManagement(new PlanBranchManagement()
        .createForVcsBranch()
        .notificationForCommitters());

You can get build notifications from branch plans just as you do for master plans. You can choose one of the following options:

Overriding branch settings

Whether a plan branch is created automatically or manually, the master plan maintains the structure and configuration of it’s branch plans. However, you can use Bamboo UI and go to the configuration pages to override settings in a branch plan, see Branch details configuration chapter for more details.

Stage

Stage stage = new Stage("My Stage")
    .description("This is a manual stage")
    .jobs(job)
    .manual(true);

Stages group (or ‘map’) jobs to individual steps within a plan’s build process. For example, you may have an overall plan build process that comprises a compilation step, followed by several test steps, followed by a deployment step. You can create separate Bamboo stages to represent each of these steps.

A stage:

Each plan should contain at least one stage.

Job

A job which runs few tasks, generates and uses artifacts and has some build requirements.

Job job = new Job("My Job", "JOB1")
    .tasks(tasks)
    .artifacts(testReportArtifact)
    .artifactSubscriptions(warArtifact)
    .requirements(osLinux);

A Bamboo job is a single build unit within a plan. One or more jobs can be organized into one or more stages. The jobs in a stage can all be run at the same time, if enough Bamboo agents are available. A job is made up of one or more tasks.

A job:

Each plan should contain at least one job.

Tasks

A job with two build tasks and one final task

Job job = new Job("Job", "JOB")
    .tasks(new VcsCheckoutTask()
        .addCheckoutOfDefaultRepository(), new ScriptTask()
        .fileFromPath("build.sh"))
    .finalTasks(new ScriptTask()
        .fileFromPath("cleanup.sh"));

A task is a small discrete unit of work, such as source code checkout or running a script. Tasks are configured within the scope of a job and run on a Bamboo working directory.

Tasks can be designated as build tasks or final tasks in a job:

A task may make use of an executable if required.

Task: Artifact Downloader

A task downloading all artifacts produced by plan “PROJECTKEY-PLANKEY” to the working directory as well as an artifact called “an artifact” to a folder called “subdirectory”.

DownloadItem downloadAllArtifacts = new DownloadItem()
    .allArtifacts(true);
DownloadItem downloadSpecificArtifact = new DownloadItem()
    .artifact("an artifact")
    .path("subdirectory");
PlanIdentifier planIdentifier = new PlanIdentifier("PROJECTKEY", "PLANKEY");
ArtifactDownloaderTask artifactDownloaderTask = new ArtifactDownloaderTask()
    .description("My artifact downloader task")
    .sourcePlan(planIdentifier)
    .artifacts(downloadAllArtifacts, downloadSpecificArtifact);

The task which copies Bamboo shared artifacts to a specified folder. This task allows sharing artifacts between different build plans. For example, you may want to run acceptance tests on a particular build from a different plan by sharing the same WAR from one plan to another without rebuilding it each time.

In order to configure the task:

In order to specify single download request:

Task: Clean Working Directory

A task cleaning working directory after the build.

CleanWorkingDirectoryTask cleanWorkingDirectoryTask = new CleanWorkingDirectoryTask()
    .description("My clean working directory task")
    .enabled(true);

The task to clean working directory of the job. The task removes all files from the working directory and can be used, for example, to enforce a clean build or to save space on the agent once the build is complete.

Task: Script

Run a script defined inline using a default interpreter, which is a Bash shell as per the shebang line

ScriptTask scriptTask = new ScriptTask()
    .inlineBody("#!/bin/bash\necho \'Hello Bamboo!\'");

Run a script from a file with /bin/sh or cmd.exe interpreter

ScriptTask scriptTask = new ScriptTask()
    .description("Running a script from a file")
    .interpreterBinSh()
    .fileFromPath("path/to/my/script.sh");

Run a script with an argument, environment variable and in an ‘abc’ working subdirectory

ScriptTask scriptTask = new ScriptTask()
    .interpreterBinSh()
    .fileFromPath("ant-build.sh")
    .argument("--verbose")
    .environmentVariables("ANT_OPTS=-Xmx700m")
    .workingSubdirectory("abc");

This task allows to use a script executable. You can use bash on Linux and batch files on Windows.

You can specify which interpreter to use:

You can either define the script inline using the inlineBody method or load it from an external file using the fileFromPath method.

Additional options you can specify are:

Task: Test Results Parser

Test tasks in Bamboo parse test data, and may run tests, using a particular testing framework. Please note:

Task: JUnit Parser

Scan JUnit test reports from ‘build/test/reports’ and ‘target/test/xml-reports’ directories.

TestParserTask junitParserTask = TestParserTask.createJUnitParserTask()
    .description("My JUnit test results parser task")
    .resultDirectories("build/test/reports", "target/test/xml-reports");

Task: TestNG Parser

Scan TestNG reports from default location. Pick test results also from previous builds.

TestParserTask junitParserTask = TestParserTask.createTestNGParserTask()
    .description("My TestNG test results parser task")
    .defaultResultDirectory()
    .pickUpTestResultsCreatedOutsideOfThisBuild(true);

Task: Repository Checkout

A task checking out the default repository to the working directory and a repository called “repositoryName” into a “subdirectory”.

CheckoutItem defaultRepository = new CheckoutItem()
    .defaultRepository();
CheckoutItem specificRepository = new CheckoutItem()
    .repository("repositoryName")
    .path("subdirectory");
VcsCheckoutTask vcsCheckoutTask = new VcsCheckoutTask()
    .description("My repository checkout task")
    .cleanCheckout(false)
    .checkoutItems(defaultRepository, specificRepository);

Task to check out a repository for use by just one job. By default, repositories are checked out to the Bamboo working directory. It’s possible to check out multiple repositories using one task, but in that case order in which repositories are checked out is undefined.

In order to configure the task:

A repository can be specified by its name or identifier. Repository must be either a plan repository or a linked repository. You can also pick defaultRepository option, in which case the task checks out the first repository that was added or linked to the plan, regardless of its actual definition.

Paths must be relative to the working directory.

Task: Maven

Simple Maven 3 task running with JDK 1.8.

MavenTask mavenTask = new MavenTask()
    .goal("clean install")
    .hasTests(false)
    .version3()
    .jdk("JDK 1.8")
    .executableLabel("Maven 3.2");

Apache Maven is a tool used for building and managing Java-based projects. Bamboo provides a dedicated task to execute Maven goals for building, testing and deploying your code.

The most important configuration option for Maven task is the goal to execute. Multiple goals can be specified, separated by spaces, for example clean install. It is also possible to pass additional JVM and Maven parameters, such as -Djava.awt.headless=true or -Pdatabase.tests. Bamboo Variables may be included in this field too, for example clean compile ${bamboo.maven.compile.flags}.

Two other necessary fields to set are the JDK and the Maven executable. These configuration options indicate which version of Java Development Kit and which version of Apache Maven should be used to execute the task. The options should point to valid Bamboo capabilities.

More detailed documentation of the Maven task can be found here.

Parsing test results

Maven 3 task with test parsing enabled.

MavenTask mavenTask = new MavenTask()
    .goal("clean install")
    .hasTests(false)
    .version3()
    .hasTests(true)
    .testResultsPath("**/my-acceptance-tests/target/surefire-reports/*.xml")
    .jdk("JDK 1.8")
    .executableLabel("Maven 3.2");

Maven task is capable of parsing test results generated during the build. To configure the task to pick up tests, make sure to enable the feature (as shown in the code sample) and point Bamboo to test reports which will be created. Bamboo will use JUnit test parser to gather test results, so make sure the reports are in the correct format.

Configuring runtime environment

Maven 3 task running in custom working directory, with MAVEN_OPTS environment variable set.

MavenTask mavenTask = new MavenTask()
    .goal("clean install")
    .hasTests(false)
    .version3()
    .jdk("JDK 1.8")
    .executableLabel("Maven 3.2")
    .environmentVariables("MAVEN_OPTS=\"-Xmx768m -Xms64m -Dmaven.compiler.fork=true\"")
    .workingSubdirectory("maven-working-dir");

The Maven task offers additional flexibility for configuring runtime environment.

There is a possibility of setting environment variables for the build. It’s a common practice to set MAVEN_OPTS for the build’s execution (e.g. MAVEN_OPTS="-Xms200m -Xmx700m"). You can include Bamboo variables for this configuration option (e.g. MAVEN_OPTS="${bamboo.maven.compile.opts}").

Multiple environment variables can be provided, separated with spaces. Parameters with spaces must be quoted. Note that existing environment variables are automatically available and there’s no need to override them.

It is also possible to execute the Maven task in a specific sub-folder of the build’s working directory by providing relative path to it.

Configuring unsupported tasks

The ‘Add Requirement’ task with ‘isLinux=true’ using generic AnyTask

Map<String, String> configuration = new MapBuilder<String, String>()
    .append("existingRequirement", "isLinux")
    .append("regexMatchValue", "true")
    .append("requirementKey", "")
    .append("requirementMatchType", "match")
    .append("requirementMatchValue", "")
    .build();
AnyTask anyTask = new AnyTask(new AtlassianModule("com.atlassian.bamboo.plugin.requirementtask:task.requirements"))
    .configuration(configuration);

Not all tasks available in Bamboo have corresponding task classes in Bamboo Specs library. A good example are tasks bundled in third party plugins.

In order to handle an unsupported task use the generic AnyTask class. The AnyTask class requires an identifier of a task module and a set of properties describing task’s settings.

The fastest way to get this data is as follows:

  1. Create a plan in Bamboo. From top menu choose ‘Create’ > ‘Create a new plan’, enter plan name and key, select ‘Link new repository’ with ‘None’ and click ‘Configure plan’.

  2. Add a task you would like to use. Click ‘Add task’ and select a task from list, set all options, click ‘Save’ and next click ‘Create’.

  3. Export plan configuration. From the plan configuration page click ‘Actions’ > ‘View plan as Bamboo Specs’.

  4. Copy generated AnyTask code to your Bamboo Specs. Hint: you may want to encapsulate it in your own class inheriting from the Task class. In case you see an inline comment ‘Bamboo Support for task “Xyz” coming soon’ then it means that this is a plugin bundled with Bamboo and we will deliver appropriate class in one of next Bamboo major or minor releases.

Repositories

This section describes how to configure Bamboo to use repositories. You can specify repositories at the following levels in Bamboo:

Multiple repositories

A plan with two linked and two global repositories.

Plan plan = new Plan(project, planName, planKey)
    .linkedRepositories("my-global-repository1")
    .linkedRepositories("my-global-repository2")
    .planRepositories(new GitRepository()
        .name("my-plan-repository1")
        .url("ssh://git@bitbucket.org:my-company/my-repository1.git")
        .branch("master"))
    .planRepositories(new GitRepository()
        .name("my-plan-repository2")
        .url("ssh://git@bitbucket.org:my-company/my-repository2.git")
        .branch("master"));

One or more repositories can be added to a plan. All those repositories will be available to every job in the plan. The first repository in the list is the Plan’s Default Repository.

Plan-local vs linked repositories

Linked repositories are available globally to all plans and jobs configured on the Bamboo server. Doing this can save you from having to reconfigure the source repositories in multiple places if these ever change - any changes to a linked repository are applied to every plan or job that uses that repository.

Creating linked repositories

Currently it is not possible to create new linked repositories from Bamboo Specs.

See Linking to source code repositories how to set up linked repositories using UI. Once linked repository is defined, you can refer it in your code, see chapter below.

Referring linked repositories

Plan plan = new Plan(project, planName, planKey)
    .linkedRepositories("my-global-repository");

Once the linked repository is set up you can easily refer to it in your plan configuration.

Creating local repositories

Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new GitRepository()
        .name("my-plan-repository")
        .url("ssh://git@bitbucket.org:my-company/my-repository.git")
        .branch("master"));

In case you want to use a repository in only one plan and don’t want to share it, then you can define it as local.

Git

You need to have previously defined a Git capability before you can configure a Git source repository – see Defining a new version control capability.

Note that Bamboo comes with its own built-in Git implementation. However, you need to use native Git to be able to use symbolic links, submodules, automatic branch detection and automatic merging - these are not supported by the built-in Git.

Basic options

In case you are using a linked repository, then you need to provide repository name only.

In case you are creating a local repository definition, you have to provide at least:

Authentication

In case you have to authenticate you can use several methods.

Git repository with SSH authentication

Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new GitRepository()
        .name("my-repository")
        .url("ssh://git@bitbucket.org:my-company/my-repository.git")
        .branch("master")
        .authentication(new SshPrivateKeyAuthentication(sshPrivateKey)
            .passphrase(passphrase)));

Provide an SSH private key and provide the SSH passphrase.

With user/password authentication

Git repository with user-password authentication

Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new GitRepository()
        .name("my-repository")
        .url("https://bitbucket.org/my-company/my-repository.git")
        .branch("master")
        .authentication(new UserPasswordAuthentication(username)
            .password(password)));

We advise to not store user and password in the source code, but to read them from a resource file or a system property.

With shared credentials

Git repository with authentication using shared credentials

Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new GitRepository()
        .name("my-repository")
        .url("ssh://git@bitbucket.org:my-company/my-repository.git")
        .branch("master")
        .authentication(new SharedCredentialsIdentifier("identifier")));

You can store credentials within Bamboo for easier access to repositories. The access details that you provide are available to all plans on your Bamboo server. See Shared credentials for more details.

With no credentials

In case you want to access the repository anonymously, simply do not declare any authentication.

Advanced options

Checkout shallow clone of Git LFS-enabled repository of an ‘integration’ branch. The repository does not use Git submodules.

Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new GitRepository()
        .name("repository-name-in-bamboo")
        .url("ssh://git@bitbucket.org:my-company/my-repository.git")
        .branch("integration")
        .shallowClonesEnabled(true)
        .lfsEnabled(true)
        .submodulesEnabled(false));

You can tune repository checkout performance with the following options:

Note that not all combinations of the three options above make sense. Reasonable combinations are:

shallow clones fetch whole repository remote agent cache outcome
true false false the latest revision of given branch is fetched
false false false all revisions of given branch are fetched
false false true all revisions of given branch are fetched, an agent caches it
false true false the entire repository is fetched
false true true the entire repository is fetched, an agent caches it

Link the Git repository with Atlassian FishEye.

Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new GitRepository()
        .name("repository-name-in-bamboo")
        .url("ssh://git@bitbucket.org:my-company/my-repository.git")
        .branch("master")
        .repositoryViewer(new FishEyeRepositoryViewer()
            .repositoryName("repository-name-in-fisheye")
            .fishEyeUrl("https://fisheye.host:8060/")));

Other options are:

Group commits from 1 minute, trigger build on *.java files only, skip changesets with ‘draft’ in a commit message.

Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new GitRepository()
        .name("repository-name-in-bamboo")
        .url("ssh://git@bitbucket.org:my-company/my-repository.git")
        .branch("master")
        .changeDetection(new VcsChangeDetection()
            .quietPeriodEnabled(true)
            .quietPeriod(Duration.ofMinutes(1))
            .changesetFilterPatternRegex(".*draft.*")
            .filterFilePatternOption(FileFilteringOption.INCLUDE_ONLY)
            .filterFilePatternRegex(".*\\.java")));

Change detection options:

Bitbucket Server Git repository

Atlassian Bitbucket Server hosts Git repositories, so you can define it as a standard Git repository. However, defining such repository as Bitbucket Server gives you many advantages.

When you link a repository hosted in Atlassian’s Bitbucket Server with a build plan in Bamboo, then without any further configuration:

Bitbucket Server and Bamboo only need to have been connected by creating an application link. Repositories in Bitbucket Server are then made available in Bamboo, so it is easy for you to link your Bamboo plan to a Bitbucket Server repository.

When you create a plan that uses a Bitbucket Server source repository, Bamboo will automatically use the repository trigger instead of a polling trigger. This reduces the load on the Bamboo and Bitbucket servers because Bamboo doesn’t need to send poll requests (for each branch of each plan) to the Bitbucket Server every few minutes. Instead, Bitbucket Server will notify Bamboo whenever there is a push to the repository.

Basic options

Minimal Bitbucket Server configuration

Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new BitbucketServerRepository()
        .name("my-bitbucket-repository")
        .server(new ApplicationLink()
            .name("bitbucket-server"))
        .projectKey("BBSPROJECT")
        .repositorySlug("my-repository-slug")
        .branch("master"));

In order to configure Bitbucket Server repository provide at least:

Authentication

Authentication with custom SSH keys

Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new BitbucketServerRepository()
        .name("my-bitbucket-repository")
        .server(bitbucketServerApplink)
        .projectKey("BBSPROJECT")
        .repositorySlug("my-repository-slug")
        .branch("master")
        .sshPrivateKey(sshPrivateKey)
        .sshPublicKey(sshPublicKey));

Bamboo uses SSH authentication against Bitbucket Server. You can configure:

You have to provide both private and public key when setting them. If not provided, Bamboo will attempt to generate and install new SSH keys into Bamboo Server instance.

Advanced options

Use shallow clones, enable LFS support and set commit isolation (to trigger a build on every commit)

Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new BitbucketServerRepository()
        .name("my-bitbucket-repository")
        .server(new ApplicationLink()
            .name("bitbucket-server"))
        .projectKey("BBSPROJECT")
        .repositorySlug("my-repository-slug")
        .branch("master")
        .lfsEnabled(true)
        .changeDetection(new VcsChangeDetection()
            .commitIsolationEnabled(true))
        .shallowClonesEnabled(true)
        .fetchWholeRepository(false)
        .commandTimeoutInMinutes(30));

Bitbucket Server repository supports the same set of options as Git repository. See the ‘Advanced options’ section for Git for more details.

SVN

Currently there is no dedicated builder for SVN repositories, but there is a generic AnyVcsRepository builder.

AtlassianModule atlassianModuleSvn = new AtlassianModule("com.atlassian.bamboo.plugin.system.repository:svnv2");
Map<String, Object> svnConfiguration = ImmutableMap.<String, Object>builder()
    .put("repository.svn.useExternals", false)
    .put("repository.svn.tag.create.autodetectPath", true)
    .put("repository.svn.authType", "password")
    .put("repository.svn.username", "")
    .put("repository.svn.branch.create.autodetectPath", true)
    .put("repository.svn.userPassword", false)
    .put("repository.svn.repositoryRoot", "file:///path/to/my/svn/repository")
    .build();
Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new AnyVcsRepository(atlassianModuleSvn)
        .name("my-svn-repository")
        .serverConfiguration(svnConfiguration));

Mercurial

Currently there is no dedicated builder for Mercurial repositories, but there is a generic AnyVcsRepository builder.

AtlassianModule atlassianModuleHg = new AtlassianModule("com.atlassian.bamboo.plugins.atlassian-bamboo-plugin-mercurial:mercurial");
Map<String, Object> hgConfiguration = ImmutableMap.<String, Object>builder()
    .put("repository.hg.repositoryUrl", "file:///path/to/my/hg/repository")
    .put("repository.hg.ssh.compression", false)
    .put("repository.hg.verbose.logs", false)
    .put("repository.hg.authentication", "BYPASS")
    .put("repository.hg.noRepositoryCache", false)
    .put("repository.hg.commandTimeout", 180)
    .build();
Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new AnyVcsRepository(atlassianModuleHg)
        .name("my-mercurial-repository")
        .serverConfiguration(hgConfiguration));

CVS

Currently there is no dedicated builder for CVS repositories, but there is a generic AnyVcsRepository builder.

AtlassianModule atlassianModuleCvs = new AtlassianModule("com.atlassian.bamboo.plugin.system.repository:cvs");
Map<String, Object> cvsConfiguration = ImmutableMap.<String, Object>builder()
    .put("cvsRoot", "/path/to/my/cvs/repository")
    .put("password", "")
    .put("quietPeriod", 2)
    .put("module", "module")
    .put("authType", "password")
    .put("selectedVersionType", "head")
    .build();
Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new AnyVcsRepository(atlassianModuleCvs)
        .name("my-cvs-repository")
        .serverConfiguration(ImmutableMap.of("repository.cvs", cvsConfiguration)));

Artifacts

Artifacts are files created by a job build (e.g. JAR files). Artifact definitions are used to specify which artifacts to keep from a build and are configured for individual jobs. You can also configure artifact sharing between jobs in a plan. For example, you may want to run acceptance tests on a build, and then share the WAR from one job to another, without rebuilding the WAR each time.

Defining an artifact

A ‘Test Reports’ artifact containing XML files

Artifact artifact = new Artifact("Test Reports")
    .location("target/reports")
    .copyPattern("**/*.xml");

You can specify which artifacts to keep by setting up an artifact definition for the job. The artifacts will be available after each build of a job. You can specify:

See also Pattern matching reference.

Sharing an artifact

Declare a shared artifact

Artifact artifact = new Artifact("Test Reports")
    .location("target/reports")
    .shared(true);

You can share an artifact among other jobs or plans. Set the ‘shared’ property to true and optionally define jobs subscribing to this artifact.

The artifact from the most recent successful build will be used. If there are no successful builds from the artifact-producing plan or the artifacts have expired, the artifact-consuming job will fail.

Using a shared artifact in another job of the same plan

Create a WAR artifact in the ‘Build’ stage and use it in the ‘Test’ stage

Stage buildStage = new Stage("Build")
    .jobs(new Job("Build WAR", "BUILD")
        .artifacts(new Artifact("WAR")
            .location("target")
            .copyPattern("*.war")
            .shared(true)));
Stage testStage = new Stage("Test")
    .jobs(new Job("Test app", "TEST")
        .artifactSubscriptions(new ArtifactSubscription()
            .artifact("WAR")
            .destination("deploy")));
Plan plan = new Plan(project, planName, planKey)
    .stages(buildStage, testStage);

You can share artifacts between jobs in different stages using artifact dependencies. For example, you may want to run acceptance tests on a build, sharing the same WAR from one job to another without rebuilding it each time. Each time the artifact is shared with a subsequent job, it is copied to the job’s agent.

You can refer only to artifacts from jobs in previous stages that have been marked as shared. Destination directory is relative to the build directory. Do not use the absolute path to refer to the destination directory.

Using a shared artifact in another plan

Download all artifacts from another plan

Plan artifact = new Plan(project, planName, planKey)
    .stages(new Stage("Stage 1")
        .jobs(new Job("Job", "JOB")
            .tasks(new ArtifactDownloaderTask()
                .sourcePlan(new PlanIdentifier("PROJECTKEY", "PLANKEY"))
                .artifacts(new DownloadItem()
                    .allArtifacts(true)))));

Download selected artifacts from another plan

Plan artifact = new Plan(project, planName, planKey)
    .stages(new Stage("Stage 1")
        .jobs(new Job("Job", "JOB")
            .tasks(new ArtifactDownloaderTask()
                .sourcePlan(new PlanIdentifier("PROJECTKEY", "PLANKEY"))
                .artifacts(new DownloadItem()
                    .artifact("WAR"), new DownloadItem()
                    .artifact("DATA")))));

You have to use the Artifact Downloader Task for this purpose. In this task point to the build plan that is the source of the artifact(s) you need to download. You can either download all artifacts from the plan or selected ones as well as specify target folder for them.

Sharing an artifact to a deployment environment

Bamboo Specs do not support deployment plans at the moment. See Sharing artifacts from a build plan to a deployment environment how to set it up.

Build triggers

Triggering in Bamboo allows plan builds to be started automatically. Bamboo has the following trigger methods.

Polling the repository for changes

Bamboo will poll the selected source code repositories for code changes, using either a specified interval or a schedule. If Bamboo detects code changes, a build of the plan is triggered.

Poll periodically

Plan plan = new Plan(project, planName, planKey)
    .triggers(new RepositoryPollingTrigger()
        .pollEvery(10, TimeUnit.MINUTES));

You can poll source code repository every N minutes / hours / days for new commits.

Poll daily, weekly or monthly

Plan dailyPlan = new Plan(project, planName, planKey)
    .triggers(new RepositoryPollingTrigger()
        .pollOnceDaily(LocalTime.of(12, 59)));
Plan weeklyPlan = new Plan(project, planName, planKey)
    .triggers(new RepositoryPollingTrigger()
        .pollWeekly(LocalTime.of(12, 59), DayOfWeek.SATURDAY, DayOfWeek.SUNDAY));
Plan monthlyPlan = new Plan(project, planName, planKey)
    .triggers(new RepositoryPollingTrigger()
        .pollMonthly(LocalTime.of(12, 59), 28));

You can define a time schedule when to poll the repository. You can poll daily, on specific days of a week or on specific days of a month.

Poll with cron expression

Plan plan = new Plan(project, planName, planKey)
    .triggers(new RepositoryPollingTrigger()
        .pollWithCronExpression("0 0/30 9-19 ? * MON-FRI"));

You can also use a cron expression (see Constructing a cron expression in Bamboo).

Repository triggers a build on commit

A plan listening for events from a ‘my-repo’ repository from ‘12.34.56.78’ IP address.

Plan plan = new Plan(project, planName, planKey)
    .planRepositories(new GitRepository()
        .name("my-repo")
        .url("ssh://git@bitbucket.org:my-company/my-repo.git")
        .branch("master"))
    .triggers(new RemoteTrigger()
        .triggerIPAddresses("12.34.56.78"));

Bamboo waits to receive a message about changed code from any of the selected source code repositories. When Bamboo receives such a message, a build of the plan is triggered. This option minimizes server load, because message events are sent only when code changes to a repository are committed. This is the default option when you use a linked Bitbucket Server repository.

See the Repository triggers the build when changes are committed how to set up the trigger on the repository side.

On the Bamboo side, use the triggers(new RemoteTrigger()) on plan definition. By default the remote trigger will react on all triggering repositories defined in a plan. You can limit it by selecting a subset of repositories.

In case you want Bamboo to trigger on post-commit messages from other than the primary IP address for the repository, specify it in triggerIPAddresses.

Notes:

Cron-based scheduling

In case of the cron-based scheduling, the build will always run at specified time, no matter whether content of repositories has changed or not.

Schedule with time interval

Plan plan = new Plan(project, planName, planKey)
    .triggers(new ScheduledTrigger()
        .scheduleEvery(4, TimeUnit.HOURS));

You can schedule a build to run every N minutes / hours / days.

Schedule with daily, weekly or monthly plan

Plan plan = new Plan(project, planName, planKey)
    .triggers(new ScheduledTrigger()
        .scheduleOnceDaily(LocalTime.of(12, 59)));
Plan plan = new Plan(project, planName, planKey)
    .triggers(new ScheduledTrigger()
        .scheduleWeekly(LocalTime.of(12, 59), DayOfWeek.SATURDAY));
Plan plan = new Plan(project, planName, planKey)
    .triggers(new ScheduledTrigger()
        .scheduleMonthly(LocalTime.of(12, 59), 1));

The schedule can be daily (specific time each day), weekly (days per week), monthly (days per month).

Schedule with cron expression

Plan plan = new Plan(project, planName, planKey)
    .triggers(new ScheduledTrigger()
        .cronExpression("0 0/30 9-19 ? * MON-FRI"));

The schedule can be also expressed using a cron expression.

Conditional build triggers

In Bamboo UI it is possible to define a trigger condition, i.e. that a given trigger will execute only if specified plans are passing. This option is not available in Bamboo Specs at the moment.

See Triggering builds / Conditional build triggers.

Running a build when another plan has successfully completed

A dependency blocking strategy which blocks a trigger if parent’s build is in progress, unless this is a branch plan

Plan plan = new Plan(project, planName, planKey)
    .dependencies(new Dependencies()
        .configuration(new DependenciesConfiguration()
            .enabledForBranches(false)
            .blockingStrategy(BLOCK_IF_PARENT_IN_PROGRESS)));

In Bamboo UI it is possible to define build dependencies, i.e. to trigger a plan build when another plan’s build has successfully completed. This option is not available in Bamboo Specs at the moment.

Both in Bamboo UI and Bamboo Specs it is possible to define dependency blocking strategies, such as:

See:

Multiple triggers

You can use many triggers for a single plan. In such case a build will run for a plan whenever condition of any trigger is satisfied.

No triggers

You can of course configure your plan to have no triggers at all. In such case the plan have to be executed manually. This is useful when human decision is required, for instance publishing a new product release.

Requirements

In the example below, the Maven task will implicitly add requirements for Maven and JDK tools. We specify additional requirements on Job level.

MavenTask mavenTask = new MavenTask()
    .executableLabel("Maven 3")
    .jdk("JDK 1.8")
    .goal("clean integration-test");
Job job = new Job(jobName, jobKey)
    .tasks(mavenTask)
    .requirements(new Requirement("operating.system")
        .matchType(MatchType.EQUALS)
        .matchValue("Linux"))
    .requirements(new Requirement("xvfb"));

Configuring a job with a simple Script task usually requires specifying the requirements manually to ensure necessary capabilities exist on the agent.

ScriptTask scriptTask = new ScriptTask()
    .inlineBody("mvn clean test");
Job job = new Job(jobName, jobKey)
    .tasks(scriptTask)
    .requirements(new Requirement("bamboo.capability.system.jdk.JDK 1.8"))
    .requirements(new Requirement("bamboo.capability.system.builder.mvn3.Maven 3"));

It’s not uncommon to run the same build on different platforms, such as operating systems or databases. It’s also not uncommon to run many times with even the same set of tools but with different versions to check the compatibility matrix. In such cases defining proper requirements for a build agent is necessary.

A requirement is specified in a job or a task. A requirement specifies a capability that an agent must have for it to build that job or task. A job inherits all of the requirements specified in its tasks.

There are four types of capabilities in Bamboo that can be specified by job and task requirements:

To learn more, refer to the following documentation pages:

Additionally, in Bamboo variables documentation you may find details on how to refer to various types of capabilities.

Variables

Defining plan variables

Plan plan = new Plan(project, planName, planKey)
    .variables(new Variable("maven.goal", "clean install -DskipTests"));

Using variables in tasks

MavenTask mavenTask = new MavenTask()
    .executableLabel("Maven 3")
    .goal("${bamboo.maven.goal} --batch-mode");
ScriptTask scriptTask = new ScriptTask()
    .inlineBody("mvn $bamboo_mvn_goal --batch-mode");

Variables can be used to make values available when building plans in Bamboo.

Variables can be used in configuration fields of tasks. The following format should be used when referencing a variable:

For Script task Bamboo variables are additionally exported as shell variables. All full stops (periods) are converted to underscores. For example, the variable bamboo.my.variable will become $bamboo_my_variable.

See the official documentation for more details about Bamboo variables.

Utilities

Publish plan to Bamboo using URL, login and password provided from a command line. In public static void main(String[] args):

String bambooUrl = args[0];
UserPasswordCredentials adminUser = new SimpleUserPasswordCredentials(args[1], args[2]);
BambooServer server = new BambooServer(bambooUrl, adminUser);
server.publish(createPlan());;

The Bamboo Specs library comes with several helper classes, which can ease task of deploying a spec to Bamboo.