Skip to content

Commit 02d3e85

Browse files
committed
Add repository linking to Bamboo API
atlassian-api#1240
1 parent 9f22808 commit 02d3e85

3 files changed

Lines changed: 73 additions & 0 deletions

File tree

atlassian/bamboo.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,40 @@ def get_plan_specs(self, plan_key, package=None, format="YAML"):
249249
params["package"] = package
250250
return self.get(self.resource_url(f"plan/{plan_key}/specs"), params=params)
251251

252+
def search_linked_repositories(self, search_term=None):
253+
"""Search globally configured Bamboo linked repositories.
254+
255+
The public Bamboo REST API can search existing linked repositories but
256+
does not create or update their connection configuration. Create those
257+
connections in Bamboo administration, then use the returned repository
258+
ID with :meth:`link_repository_to_project`.
259+
260+
:param search_term: Optional repository-name fragment.
261+
:return: Bamboo's paged linked-repository response.
262+
"""
263+
params = {}
264+
if search_term is not None:
265+
params["searchTerm"] = search_term
266+
return self.get(self.resource_url("repository"), params=params)
267+
268+
def get_project_linked_repositories(self, project_key):
269+
"""Return linked repositories authorized for Bamboo Specs in a project."""
270+
return self.get(self.resource_url(f"project/{project_key}/repository"))
271+
272+
def link_repository_to_project(self, project_key, repository_id):
273+
"""Authorize an existing linked repository for Bamboo Specs in a project.
274+
275+
This grants a repository-stored Bamboo Specs repository permission to
276+
create or edit plans in ``project_key``. It does not change the
277+
repositories checked out by an existing plan; update and apply that
278+
plan's Bamboo Specs for plan-level repository changes.
279+
"""
280+
return self.post(self.resource_url(f"project/{project_key}/repository"), data={"id": repository_id})
281+
282+
def unlink_repository_from_project(self, project_key, repository_id):
283+
"""Remove a project-level Bamboo Specs repository authorization."""
284+
return self.delete(self.resource_url(f"project/{project_key}/repository/{repository_id}"))
285+
252286
def search_plans(self, search_term, fuzzy=True, start_index=0, max_results=25):
253287
"""
254288
Search plans by name

docs/bamboo.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,26 @@ Projects & Plans
6060
# Delete project
6161
delete_project(project_key)
6262
63+
Linked repositories and Bamboo Specs
64+
------------------------------------
65+
66+
Bamboo's public REST API can search existing global linked repositories and
67+
authorize one for a project’s Repository-Stored Bamboo Specs. It does not
68+
create a connection on the **Linked repositories** administration page, nor
69+
does it directly change the repositories checked out by an existing plan.
70+
Create the global connection in Bamboo administration; change plan repositories
71+
through that plan's Bamboo Specs and apply the Specs.
72+
73+
.. code-block:: python
74+
75+
candidates = bamboo.search_linked_repositories("build-specs")
76+
repository_id = candidates["searchResults"][0]["id"]
77+
78+
bamboo.link_repository_to_project("PROJECT", repository_id)
79+
allowed = bamboo.get_project_linked_repositories("PROJECT")
80+
# Revoke the project-level Repository-Stored Specs authorization:
81+
bamboo.unlink_repository_from_project("PROJECT", repository_id)
82+
6383
Branches
6484
-------------
6585

tests/bamboo/test_bamboo.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,22 @@ def test_plan_results_supports_multiple_labels(mock_get):
107107
assert list(bamboo.plan_results("PROJ", "PLAN", label=["release", "production"])) == []
108108

109109
assert mock_get.call_args.args[3]["label"] == ["release", "production"]
110+
111+
112+
@patch.object(Bamboo, "delete")
113+
@patch.object(Bamboo, "post")
114+
@patch.object(Bamboo, "get")
115+
def test_project_linked_repository_methods(mock_get, mock_post, mock_delete):
116+
bamboo = Bamboo("https://bamboo.example.test", token="token")
117+
mock_get.side_effect = [{"searchResults": []}, [{"id": 42, "name": "Specs repository"}]]
118+
119+
bamboo.search_linked_repositories("specs")
120+
bamboo.get_project_linked_repositories("PROJ")
121+
bamboo.link_repository_to_project("PROJ", 42)
122+
bamboo.unlink_repository_from_project("PROJ", 42)
123+
124+
assert mock_get.call_args_list[0].args[0] == "rest/api/latest/repository"
125+
assert mock_get.call_args_list[0].kwargs["params"] == {"searchTerm": "specs"}
126+
assert mock_get.call_args_list[1].args[0] == "rest/api/latest/project/PROJ/repository"
127+
mock_post.assert_called_once_with("rest/api/latest/project/PROJ/repository", data={"id": 42})
128+
mock_delete.assert_called_once_with("rest/api/latest/project/PROJ/repository/42")

0 commit comments

Comments
 (0)