Announcement: Bitbucket Server 5.0 Early Access Program (EAP) release

Hi everyone,

We are pleased to announce the availability of the first Early Access Program (EAP) release of Bitbucket Server 5.0.

This EAP release is so that add-on vendors and customers who have written in-house add-ons can update their add-ons and ensure they will work with the public release of Bitbucket Server 5.0.

Important things to note about this EAP release:

  • This release should not be used in a production environment.
  • This release does not include new features that may be part of the final 5.0 release.
  • There may be other minor API changes between this release and the public release of Bitbucket Server 5.0.

Key changes for add-on developers in the Bitbucket Server 5.0 EAP release:

  • New Comment API to make it easier for add-on developers to work with comments across the application.
  • Removal of APIs previously deprecated during the Bitbucket Server 4.x lifecycle.
  • Changes to the naming conventions of front-end AMD modules.

Read the full release notes below for more in-depth notes about the changes in the Bitbucket Server 5.0 EAP.

Installing the Bitbucket Server 5.0 EAP release

Links to download installers and archives:

Sources are available for users with a valid Bitbucket Server license through their license details at

The Bitbucket Server 5.0 EAP can also be run with AMPS version 6.3.0-fef7990 by running this command with the Atlassian Plugin SDK installed:

atlas-run-standalone -u 6.3.0-fef7990 --product bitbucket --version 5.0.0-eap2

We need your feedback!

If you have any questions or feedback about this preview of Bitbucket Server 5.0, ask them in the Bitbucket Server category here in the Atlassian Developer Community forums, and our friendly team of developers will respond to them.

Bitbucket Server 5.0 EAP release notes

Bitbucket Server 5.0 EAP contains several changes that may affect existing add-ons. The changes are summarised below.

Removed deprecated Java APIs

Java APIs that have been previously deprecated in the Bitbucket Server 4.x lifecycle have been removed in this 5.0 EAP release.

List of API deprecation removals and replacements

Unless noted, these methods / classes / packages have been removed. All package references in this list are assumed to be prefixed with com.atlassian.bitbucket unless otherwise specified.

  • .plugin.util
    • The entire bitbucket-plugin-util module has been removed.
  • .mirroring
    • .mirror
      • MirrorDisabledUpstreamEvent
      • MirrorEnabledUpstreamEvent
      • MirrorInstalledUpstreamEvent: now extends UpstreamLifecycleEvent
    • ENABLED and DISABLED: have been collapsed into INSTALLED
  • .repository.ref.restriction
    • Removed constructors:
      • RefRestrictionAddedEvent(Object source, Repository repository, RefRestriction restriction, Collection<ApplicationUser> affectedUsers, Collection<String> affectedGroups)
      • RefRestrictionDeletedEvent(Object source, Repository repository, RefRestriction restriction, Collection<ApplicationUser> affectedUsers, Collection<String> affectedGroups)
      • RefRestrictionUpdatedEvent(Object source, Repository repository, RefRestriction restriction, Collection<ApplicationUser> affectedUsers, Collection<String> affectedGroups)
      • RefRestrictionEvent(Object source, Repository repository, RefRestriction restriction, Collection<ApplicationUser> affectedUsers, Collection<String> affectedGroups)
    • RefRestrictionEvent#getAffectedGroups()
    • RefRestrictionEvent#getAffectedUsers()
    • RefRestriction.getAccessGrants()
  • .commit
    • AbstractCommitsRequest#isIgnoringMissing(): changed return type from Boolean to boolean
    • CommitsBetweenRequest
      • getMaxMessageLength()
      • getPaths()
      • getPropertyKeys()
      • getRepository()
      • isFollowingRenames()
      • isIgnoringMissing()
    • CommitsBetweenRequest.Builder
      • followRenames()
      • ignoreMissing()
      • maxMessageLength()
      • path()
      • paths(Iterable<String> values)
      • paths(String value, String... values)
      • propertyKey(String value)
      • propertyKeys(Iterable<String> values)
      • propertyKeys(String value, String... values)
    • TO_AUTHOR: use Commit::getAuthor instead
    • TO_ID: use MinimalCommit::getId instead
  • .content
    • AbstractFileContentCallback#offerBlame(List<Blame> blames): use offerBlame(Page<Blame> blames) instead
    • FileContentCallback#offerBlame(List<Blame> blames): use offerBlame(Page<Blame> blames) instead
    • ContentService#getBlame(...) now returns a Page<Blame> instead of a List<Blame>
    • Blame#TO_AUTHOR: use Blame::getAuthor instead
    • SimpleDirectory(Path path, String contentId): use SimpleDirectory’s Builder instead
    • SimpleFile(Path path, String contentId): use SimpleFile’s Builder instead
  • .event.pull
    • PullRequestApprovalEvent: use PullRequestParticipantStatusUpdatedEvent instead
    • PullRequestApprovedEvent: use PullRequestParticipantApprovedEvent instead
    • PullRequestRolesUpdatedEvent: use PullRequestReviewersUpdatedEvent instead
    • PullRequestUnapprovedEvent: use PullRequestParticipantUnapprovedEvent instead
  • .io
    • LineReaderOutputHandler(String charsetName): use LineReaderOutputHandler(Charset) instead
    • TruncatedLineOutputHandler(int maxLineLength, @Nullable String encoding): use TruncatedLineOutputHandler(int, Charset) instead
  • .project
    • AbstractProjectRequest(String key, String name, String description, boolean publiclyAccessible): use AbstractProjectRequest(AbstractBuilder builder) instead
  • .pull
    • PullRequest#TO_ID: use PullRequest::getId instead
    • PullRequestParticipantRequest#getApproved(): use getStatuses() instead
    • PullRequestService
      • approve(): use setReviewerStatus() instead
      • assignRole(): use addReviewer() instead
      • unassignRole(): use removeReviewer() instead
      • withdrawApproval(): use setReviewerStatus() instead
  • .repository
    • RefChange
      • getRefId(): use getRef().getId() instead
      • TO_REF_ID: use RefChange::getRefId instead
      • TO_TYPE: use RefChange::getType instead
    • RefService#resolveRef(): use resolveRef(ResolveRefRequest) instead
    • SimpleRefChange#getRefId(): use RefChange::getRefId
    • MinimalRef
      • TO_DISPLAY_ID: use MinimalRef::getDisplayId
      • TO_ID: use MinimalRef::getId
    • Ref::TO_LATEST_COMMIT: use Ref::getLatestCommit
    • Repository#NAME_MAX_SIZE: use Repository#MAX_NAME_LENGTH instead
  • .rest
    • .content.RestFile(RestPath path, String contentId): use RestFile(File) instead
    • .pull.RestPullRequestParticipant#newExample(String, PullRequestRole, Boolean): use RestPullRequestParticipant#newExample(String, PullRequestRole, PullRequestParticipantStatus) instead
  • .server
    • ApplicationPropertiesService#getDefaultTimeZone(): use TimeZoneService#getDefaultTimeZone()
  • .scm
    • AvailableScm#TO_ID: use AvailableScm::getId instead
    • CommandBuilderSupport#environment(): use withEnvironment(String, String) instead
    • CommitsCommandParameters
      • Boolean isIgnoringMissing(): use boolean isIgnoringMissing() instead
    • CommitsCommandParameters.Builder
      • Boolean isIgnoringMissing(): use boolean isIgnoringMissing() instead
    • ScmCommandFactory
      • Command<List<Blame>> blame(): use Command<Page<Blame>> instead
      • create(): use RepositoryService.create() instead
      • fork(): use RepositoryService.fork() instead
      • merge(): use ScmExtendedCommandFactory.merge() instead
      • resolveRef(): use resolveRef(ResolveRefCommandParameters) instead
      • updateDefaultBranch(): use ScmExtendedCommandFactory.updateDefaultBranch() instead
    • .pull
      • ScmPullRequestCommandFactory#canMerge(): use tryMerge(PullRequest) instead
      • PluginPullRequestCommandFactory#canMerge(): use tryMerge(PullRequest) instead
      • default tryMerge() for PluginPullRequestCommandFactory uses replacement for tryMerge()
    • .git.command.GitCommandFactory
      • GitCommand<List<Blame>> blame(): use GitCommand<Page<Blame>> blame() instead
      • fork(): use GitExtendedCommandFactory.fork() instead
      • merge(): use GitExtendedCommandFactory.merge() instead
      • resolveRef(Repository repository, String refId)
      • updateDefaultBranch(): use GitExtendedCommandFactory.updateDefaultBranch() instead
    • .git.command.GitPullRequestCommandFactory
      • canMerge(): use tryMerge(PullRequest) instead
      • rescope()
    • .git.command.CommitReader
      • CommitReader(Repository): use CommitReader(CommitReaderSettings) instead
      • CommitReader(Repository, boolean): use CommitReader(CommitReaderSettings) instead
    • .git.command.merge.conflict
      • AddAddGitMergeConflict(String message, String path): use AddAddGitMergeConflict(String, String, boolean) instead
      • ContentGitMergeConflict(String message, String path): use ContentGitMergeConflict(String, String, boolean) instead
    • CompatibilityResolveRefsCommand
    • CompatibilityStreamBranchesCommand
    • AbstractCommandBuilder#environment(): use withEnvironment(String, String) instead
    • PluginCommandFactory
      • Command<List<Blame>> blame(): use Command<Page<Blame>> instead
      • default branches()
      • fork()
      • merge()
      • resolveRef(Repository repository, String refId)
      • default resolveRefs()
      • updateDefaultBranch()
    • .throttle
      • ThrottledScmRequestFactory(ThrottleService throttleService, I18nService i18nService, HelpPathService helpPathService): use ThrottledScmRequestFactory(ThrottleService) instead
  • .user
    • ApplicationUser::TO_ID: use ApplicationUser::getId instead
    • Person::TO_EMAIL_ADDRESS: use Person::getEmailAddress instead
  • .util
    • PropertiesUtils
      • parseExpression(@Nullable String expression, long defaultValue): use parseExpressionAsLong(String) instead
      • parseExpression(@Nullable String expression, int defaultValue): use parseExpressionAsInt(String) instead
    • UserUtils
      • IS_ACTIVE: use ApplicationUser::isActive instead
      • TO_ID: use ApplicationUser::getId instead
      • TO_USERNAME: use Principal::getName instead
  • .web
    • HasPullRequestApproveCondition: use HasApprovedPullRequestCondition instead
    • IsNormalUserCondition: use IsUserOfTypeCondition instead
    • PullRequestDiffPage#getFileContent(): use PullRequestDiffPage#getUnifiedFileContent() instead

Redesigned Comment API

We have largely redesigned our API to make working with comments easier for add-on developers.

The new Comment API introduces two major components:

  • CommentService: This service consolidates all comment related functionality and replaces the comment-related methods in PullRequestService and CommitService. This allowed us to remove a lot of duplicated functionality and provide a consistent behaviour for our API. This service is largely based on the Commentable interface and is PullRequest and Commit agnostic.
  • CommentThread: This new addition to our model allows us to easily tie all comments in the same thread of discussion. Add-on developers will find that it is now a lot easier to navigate from a reply to the rest of the comments in a thread. All comments have a reference to thread they belong to which, in turn, provides access to the corresponding anchoring data (if available).

Removed explicit naming from front-end AMD modules

Bitbucket Server’s core JavaScript now uses ES Modules (they are transformed and end up as AMD modules). This means a lot of modules have had their names changed. As part of this rename there is a mapping to the old names; however, add-on developers are encouraged to use the new module names as the old ones are deprecated and will be removed in Bitbucket Server 6.0. Please note the following when working with JavaScript in Bitbucket Server 5.0 and later:

  • Module names can now be inferred from a module’s file path starting from the static root path (webapp/default/src/main/frontend/static). For instance, .../frontend/static/bitbucket/internal/util/notifications/notifications.js has a module name of bitbucket/internal/util/notifications/notifications.
  • The way values are exported in some modules may change because of the way ES module exports work. You are encouraged to check that the way you are consuming Bitbucket Server’s code still functions as expected.

Please note that modules within bitbucket/internal/ are not considered API and may change in any new version of Bitbucket Server.

Library updates and removals

  • The host application exports Spring 4.3 to OSGi.
  • The atlassian-core library has been removed from Bitbucket Server 5.0.
  • atlassian-spring-scanner has been upgraded to 2.1.3. Plugins using version 1.x of atlassian-spring-scanner will continue to work as normal.
  • Raphael is a bundled JavaScript library that has been deprecated since Bitbucket Server 4.10. It is not used by core Bitbucket Server code and has been removed for performance reasons. Third parties that rely on Raphael should bundle it in their add-ons from Bitbucket Server 5.0 onwards.

Bundled Scala updates

Bitbucket Server 4.x bundled the runtime environment for Scala 2.10 and 2.11. These runtime environments allow add-ons written in Scala to run without the need to include the Scala runtime environment in the add-on itself.

Bitbucket Server 5.0 removes support for Scala 2.10 and adds support for Scala 2.12. Support for Scala 2.11 also continues.

Spring Boot

Bitbucket Server 5.0 has been converted to run as a Spring Boot application. This should not impact the development or running of third-party add-ons.

Removed support for deprecated database versions

Support for the following database versions has been removed:

  • Microsoft SQL Server 2008
  • Postgres 9.1 and below
  • MariaDB 5.5.22 and below
  • MySQL 5.5.7 and below
  • Oracle 11g and below

Again, this should not impact the development or running of third-party add-ons.


Permissions around tagging would be swell. See if you can slip that in.

testing right now :slight_smile:

Where can I download 5.0 EAP sources to get more info on API changes - thanks

Hi Ulrich,

I have uploaded the 5.0 EAP sources to, you will need to be logged in to view the source download.


1 Like

Any rough ETA for the official Bitbucket 5.0 release date?

We’re planning to release Bitbucket Server 5.0 in the first week of May.

1 Like

Another question: Bitbucket Server 4.14 supports a range of git versions from Git 1.8.0 all the way to Git 2.11+. Will this range stay the same for Bitbucket Server 5.0?

I noticed CommitReader.BASE_FORMAT has changed from “%H|%P|%aN|%aE|%at” to “”%H|%P|%aN|%aE|%at|%cN|%cE|%ct". Exciting! I look forward to seeing what Atlassian is planning to do with the extra committer metadata (e.g., %ct, the commit timestamp).


I’ve just changed the BBS version in the POM of one of our plug-ins to 5.0.0-eap2, fixed all compilation errors and started the plug-in with “atlas-debug”. I didn’t get any errors in the console nor in the Bitbucket Server or Tomcat logs. But when I go to the browser on http://localhost:7990/bitbucket/, all I get is a 404 Tomcat error.

The same happens when I create a new Bitbucket Server plug-in with atlas-create-bitbucket-plugin (SDK version 6.2.14 under Ubuntu). Is the Atlassian plug-in SDK already compatible with BBS 5.0? Do I need to change something additionally in the POM to get my plug-in working in 5.0.0?


Make sure to add -u 6.3.0-fef7990 to your atlas-debug / atlas-run command. This will load the correct version of the AMPS maven plugin for bitbucket 5 EAP.


Perfect, thanks, that made the trick!

1 Like

@nma: I was really hoping that there would be a demo repo in the BitBucket 5 default test data. I’ve been using the old BitBucket 4.0.0 test data for my integration tests. This was removed in later versions, but I could always just hard-code that version and it would automatically upgrade during application start. With BitBucket 5, this workaround is no longer valid and I get a clean install… Is there a way to get the old test data back?

UPDATE: never mind, I feel terribly stupid. The BitBucket 4.0.0 test data does work, I should have just spent 5 seconds longer in the BitBucket UI/UX to actually find it before posting this question.

5.0 will require git 2.2 as a minimum. The newer version of git allows us to remove a few hacks that worked around old git behaviour and offers a few interesting features that we hope to take advantage of in later 5.x releases.

I’m not aware of any grand plans but there was a request to add this info to the Java API and we have a couple small features that may require the info.

1 Like

I tried updating our internal bridge plugin to a legacy ALM system, but it somehow is not activated. The only error I see is:

Plugin 'de.tanner.bitbucket.mksbridge.MksBridge' never resolved service '&mksBridge'
with filter '(&(objectClass=de.tanner.bitbucket.mksbridge.MksBridge)

What is missing here? All I changed was the BB version in the plugins pom

I’ve got a dependency on com.atlassian.core.task.longrunning.AbstractLongRunningTask (uuhh, ohh - Founder Code!!) from atlassian-core. That’s no longer bundled with BBS 5 - what are the options? Is it safe to make it a plugin dependency? Are there perhaps better alternatives to LongRunningTask ?

@izymesdev - One option is to bundle atlassian-core with your plugin. That makes your plugin bigger, requires a bit more memory and causes your plugin to load a bit slower but it doesn’t require code changes.

Alternatively, what part(s) of AbstractLongRunningTask do you need? If you’re not using the progress reporting aspects of that class/interface, maybe you could use a Runnable.

1 Like

I’ve got a Bitbucket 5 compatible version of Reminders for Bitbucket ready - but can’t select Bitbucket 5 when uploading the add-on


I’ve seen a new version of PRHarmony being released on MP - how did you guys achieve that?

Thanks for your help

Hi @izymesdev - It took me a while to figure this one out. It’s a bit tricky. The problem in your screenshot is that “Compatible to” is only set to 4.14.5 so we’ve got some magic ensuring that “Compatible from” stops at 4.14.5, too. Try setting “Compatible to” first and you should be able to select 5.x versions.

1 Like

Wow, that was quick!! - Thanks. Good to know…

Maybe the magic can do its work when from is selected and then limit the to versions? That’s how I intuitively expected it to work… - just a thought.