Script Console
The Script Console is the place for running one-off ad hoc scripts, and for learning and experimenting with the Bitbucket API.
Either enter your script directly in the browser, or click the File tab, and type the path to a file. The file can be a fully-qualified path name to a .groovy file accessible to the server. If you provide a relative path name, the file is resolved relative to your script roots. By default there is one script root automatically created, which is <stash_home>/scripts/
.
Read more about script roots and script plugins.
Samples
Take one of these samples, and use it as a starting point for your own situation.
List all Repository Sizes By Project
Let’s start with computing the sizes of all repositories, and summing them by project. We might wish to identify the projects that are using the most disk space on our Bitbucket instance.
This will just dump the results as JSON to the console when run:
import com.atlassian.bitbucket.project.ProjectService
import com.atlassian.bitbucket.repository.Repository
import com.atlassian.bitbucket.repository.RepositoryService
import com.atlassian.sal.api.component.ComponentLocator
import groovy.json.JsonBuilder
import static com.onresolve.scriptrunner.canned.bitbucket.util.BitbucketCannedScriptUtils.unlimitedPager
def repositoryService = ComponentLocator.getComponent(RepositoryService)
def projectService = ComponentLocator.getComponent(ProjectService)
def allProjects = projectService.findAll(unlimitedPager).values // <1>
def sizeByProject = allProjects.collect { project ->
def repos = repositoryService.findByProjectKey(project.key, unlimitedPager).values // <2>
def repoSizes = repos.collectEntries { Repository repo ->
[(repo.name): repositoryService.getSize(repo)] // <3>
}
[
project : project.name,
totalSize : repoSizes.values().sum(),
repositories: repoSizes
]
}
"<pre>" + new JsonBuilder(sizeByProject).toPrettyString() + "</pre>"
Line 14: Get all projects in this instance
Line 17: Get all repositories for each project
Line 19: Get the size of each repository
That’s not fantastically useful… let’s format these into a table so we can see the size for each repository, grouped by project:
You can replace the final return
line with the following code:
static String humanReadableByteCount(long bytes) {
int unit = 1000
if (bytes < unit) {
return bytes + " B"
}
int exp = (int) (Math.log(bytes) / Math.log(unit))
String pre = "kMGTPE".charAt(exp - 1)
String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre)
}
def writer = new StringWriter()
def builder = new MarkupBuilder(writer)
builder.table(class: "aui") {
thead {
tr {
th("Project Name")
th("Repository Name")
th("Size")
}
}
tbody {
sizeByProject.each { dataRow ->
tr {
td {
b(dataRow.project)
}
td()
td {
b(humanReadableByteCount(dataRow.totalSize ?: 0))
}
}
dataRow.repositories.each { repoRow ->
tr {
td()
td(repoRow.key)
td(humanReadableByteCount(repoRow.value ?: 0))
}
}
}
}
}
writer.toString()
On clicking Run you should see something like:
Enable Repository Hooks on Multiple Repositories
Manually enabling and configuring Bitbucket hooks across multiple repositories is a time-consuming and error-prone business. The following example enables and configures a hook across all the repositories in a project. In this case it enables the excellent Repository Mirror Plugin for Stash, which allows synchronization to a remote repository, which could be on Bitbucket or GitHub for instance.
This script assumes that for each repository in a Bitbucket project, there is a corresponding empty GitHub repository. It could easily be enhanced to create the remote repository if not present.
import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.bitbucket.hook.repository.RepositoryHookService
import com.atlassian.bitbucket.repository.RepositoryService
import com.atlassian.bitbucket.util.PageRequestImpl
def repositoryService = ComponentLocator.getComponent(RepositoryService)
def repositoryHookService = ComponentLocator.getComponent(RepositoryHookService)
def final String MIRROR_HOOK_KEY = "com.englishtown.bitbucket-hook-mirror:mirror-repository-hook"
repositoryService.findByProjectKey("TEST", new PageRequestImpl(0, 100)).values.each { repository ->
repositoryHookService.findAll(repository, new PageRequestImpl(0, 100)).values.each { hook ->
def settings = repositoryHookService.createSettingsBuilder()
.add("mirrorRepoUrl0", "git@github.com:<orgname>/${repository.slug}") // <1>
.add("username0", "<github-username>") // <2>
.add("password0", "<github-password>") // <3>
.build()
repositoryHookService.enable(repository, MIRROR_HOOK_KEY, settings)
}
}
Line 15: Change orgname to your github organization or username
Line 16: Enter github username
Line 17: Enter github password
Delete all the Repositories in a Project
Bitbucket won’t let you delete a project if there are any repositories in it. Deleting them one by one is painful.
This script will delete all the repositories for any given project. Make sure you modify to include the correct project key.
Be sure this is what you want to do, there is no undo button.
import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.bitbucket.repository.Repository
import com.atlassian.bitbucket.repository.RepositoryService
import com.atlassian.bitbucket.util.Page
import com.atlassian.bitbucket.util.PageProvider
import com.atlassian.bitbucket.util.PageRequest
import com.atlassian.bitbucket.util.PagedIterable
def repositoryService = ComponentLocator.getComponent(RepositoryService)
def final projectKey = "AAA" /// delete repositories of this project
new PagedIterable<Repository>(new PageProvider<Repository>() {
@Override
Page<Repository> get(PageRequest pageRequest) {
repositoryService.findByProjectKey(projectKey, pageRequest) as Page<Repository>
}
}, 10).collect().each { Repository repository ->
log.debug("Delete repository: ${repository.name}")
repositoryService.delete(repository)
}
Bulk Project Permissions Update
After using Bitbucket for a while you may decide that you want to modify all projects to:
change the default access level
make them publicly accessible to non logged-in users
add a group with write permissions
remove a user or group from all projects
See default project / repository permissions listeners for a way to set default project / repository settings on creation.
The following snippet, will iterate over all of your projects, but not actually do anything. What follows after is a list of snippets whereby you can make changes similar to the examples.
import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.bitbucket.project.Project
import com.atlassian.bitbucket.project.ProjectService
import com.atlassian.bitbucket.project.ProjectUpdateRequest
import com.atlassian.bitbucket.permission.Permission
import com.atlassian.bitbucket.permission.PermissionAdminService
import com.atlassian.bitbucket.user.UserService
import com.atlassian.bitbucket.permission.SetPermissionRequest
import com.atlassian.bitbucket.util.Page
import com.atlassian.bitbucket.util.PageProvider
import com.atlassian.bitbucket.util.PageRequest
import com.atlassian.bitbucket.util.PagedIterable
def projectService = ComponentLocator.getComponent(ProjectService)
def permissionAdminService = ComponentLocator.getComponent(PermissionAdminService)
def userService = ComponentLocator.getComponent(UserService)
new PagedIterable<Project>(new PageProvider<Project>() {
@Override
Page<Project> get(PageRequest pageRequest) {
projectService.findAll(pageRequest) as Page<Project>
}
}, 10).each { project ->
log.debug("Update project ${project.key}")
}
To use these snippets, add them to the code that iterates each project, immediately after the log.debug
line, and before the closing }
.
To enable public access to non-logged in users, add this:
projectService.update(
new ProjectUpdateRequest.Builder(project)
.publiclyAccessible(true)
.build()
)
To grant a default permission to the project:
permissionAdminService.revokeAllProjectPermission(
Permission.PROJECT_WRITE, project) // <1>
permissionAdminService.grantAllProjectPermission(
Permission.PROJECT_READ, project)
Line 2: if you need to revoke previously given WRITE privileges
Add a group to all projects with a particular permission:
def setPermissionRequest = new SetPermissionRequest.Builder()
.projectPermission(Permission.PROJECT_WRITE, project) // <1>
.group("project-creators") // <2>
.build()
permissionAdminService.setPermission(setPermissionRequest)
Line 2: PROJECT_READ and PROJECT_ADMIN does what you expect
Line 3: Set the name of the group to add
Remove a group from all projects:
permissionAdminService.revokeAllProjectPermissions(project, "authorised-devs")
Remove a user from all projects:
permissionAdminService.revokeAllProjectPermissions(
project, userService.getUserByName("anuser")
)
Further Examples
Creating multiple branch restrictions across single or multiple repositories: https://community.atlassian.com/t5/Answers-Developer-Questions/I-can-t-create-multiple-restrictions-for-a-branch-using-rest-api/qaq-p/479806#M17462