BitBucket: How to update a file via the API - bitbucket

I'm struggling to understand how to implement the following API to update files in a repo:
https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Busername%7D/%7Brepo_slug%7D/src#post
GitLab and GitHub have a simple api - pass contents of a file + commit SHA, and it will update if the commit SHA is still current.
I tried this and of course it happily overwrites anything that was already there:
curl -X POST \
'https://api.bitbucket.org/2.0/repositories/%7B%7D/{uuid}/src' \
-H 'Authorization: Bearer ***' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'cache-control: no-cache' \
-d 'src%2Flocale%2Fen.js=test&message=Test%20commit'
How can I specify a file commit SHA so that it doesn't overwrite content if it's been updated? Thanks

In the documentation you already have in your question it is stated:
parents (string):
A comma-separated list of SHA1s of the commits that should be the parents of the newly created commit.
When omitted, the new commit will inherit from and become a child of the main branch's tip/HEAD commit.
When more than one SHA1 is provided, the first SHA1 identifies the commit from which the content will be inherited.
When more than 2 parents are provided on a Mercurial repo, a 400 is returned as Mercurial does not support "octopus merges".
That doesn't really say something about prevention, but in the description of the branch parameter it is stated:
When a branch name is not specified, but a parent SHA1 is provided, then Bitbucket asserts that it represents the main branch's current HEAD/tip, or a 409 is returned.
So, sounds like you just need to add that parameter to your data payload and it should prevent changes if the provided hash is not the current commit. You would then get a response with a http status 409 back.
-d 'src%2Flocale%2Fen.js=test&message=Test%20commit&parents=sha-hash'

Related

How do I specify multiple node values in a buildWithParameters call to Jenkins?

I have a webhook service which kicks off a buildWithParameters Jenkins job, and I want to be able to specify which buildservers are being used.
This is easy enough in the job configuration - I've added a Node parameter which lets me specify which nodes are valid, and when starting the job manually in the Jenkins web UI, I can select which nodes I want:
I'm able to kick off the job via curl using the buildWithParameters Jenkins feature:
curl -vvv 'https://webhook:examplepassword#jenkins.example.com/job/build-sideboard-plugin/buildWithParameters?token=exampletoken&GIT_REPO=example/repo&YUM_REPO=example&BUILDSERVER=sideboard.build.dev.xr'
However, I can't figure out how to specify multiple parameters. I expected that I'd simply be able to add a second &BUILDSERVER=xxx value and have that work, but running this:
curl -vvv 'https://webhook:examplepassword#jenkins.example.com/job/build-sideboard-plugin/buildWithParameters?token=exampletoken&GIT_REPO=example/repo&YUM_REPO=example&BUILDSERVER=sideboard.build.dev.xr&BUILDSERVER=sideboard.rocky8.build.dev.xr'
Returns a 500 error. I also tried providing a single value with a comma separating the two values, i.e.
curl -vvv 'https://webhook:examplepassword#jenkins.example.com/job/build-sideboard-plugin/buildWithParameters?token=exampletoken&GIT_REPO=example/repo&YUM_REPO=example&BUILDSERVER=sideboard.build.dev.xr,sideboard.rocky8.build.dev.xr'
but Jenkins interpreted that as a single Node value which didn't match any node since there's no node named sideboard.build.dev.xr,sideboard.rocky8.build.dev.xr. I got the same result when submitting the two values separated by a space.
Is there any way to get Jenkins to do this while still using the buildWithParameter functionality? I'd hate to have to redo the structure of our build triggering or switch to Jenkins Pipeline. Even making 2 different curl commands would be somewhat of a pain given how our webhooks are structured, so I'd love to be able to provide both parameters just like I can in the Jenkins web UI.
I don't think it is possible using the query parameters like you have tried, due to the fact the the plugin actually triggers two different builds.
What you can do is pass the parameters with the submit command as JSON data, which will simulate the trigger of the build with multiple servers selected.
The general syntax will be something like:
curl -u USER:PASSWORD --show-error \
--data 'json={"parameter":[{"name":"PARAMNAME","value":["node1","node2"]}]}' \
http://localhost:8080/job/remote/build?token=TOKEN
or in your case:
curl -u webhook:examplepassword --show-error \
--data 'json={"parameter":[{"name":"BUILDSERVER","value":["sideboard.build.dev.xr","sideboard.rocky8.build.dev.xr"]}]}' \
https://jenkins.example.com/job/build-sideboard-plugin/build?token=exampletoken
You can of course pass all other needed parameters alongside the BUILDSERVERin the JSON data:
curl -u webhook:examplepassword --show-error \
--data 'json={"parameter":[{"name":"BUILDSERVER","value":["sideboard.build.dev.xr","sideboard.rocky8.build.dev.xr"]},{"name":"YUM_REPO","value":"example"},{"name":"GIT_REPO","value":"=example/repo"}]}' \
https://jenkins.example.com/job/build-sideboard-plugin/build?token=exampletoken
In addition it is probably better to use the --data-urlencode instead of the --data flag for the curl commands to avoid encoding issues in case the values of your parameters have special characters.
More info on submitting jobs via Remote Access API is available Here.

Fetch single layer from image repository using docker or other tooling?

Our build creates temporary images which we store to the repository for caching purposes as subsequent images are relying on them.
The images are untagged afterwards. The layer ID I can get from the build log.
But as they might contain credentials in some layers (set in Dockerfile via "ENV API_KEY=$API_KEY) I just want to fetch these layers and make sure that nobody can extract the credentials.
Is there an easy way of doing so?
I am unsure if you are actually referencing whole image ID or single layer ID. Usually you should see whole digest of image as well. With whole image digest you can do following. Also final steps can be done for single layers if you don't know specific layer of configuration file layer.
But in general, this depends on the manifest schema version. With schema version 1, you can see environment variables on manifest. With schema version 2 it is two step process. Examples are based on Docker Hub registry, but same API is applied elsewhere.
In both cases, you need authentication token at first, which can be acquired:
curl -sSL "https://auth.docker.io/token?service=registry.docker.io&scope=repository:<repository>:pull" > auth.json
Then pull manifest in version 1 schema and get history section which contains environment variables:
curl --request GET -sLH "Authorization: Bearer `jq -r '.token' auth.json`" -H "Accept: application/vnd.docker.distribution.manifest.v1+json”" "https://index.docker.io/v2/<repository>/manifests/latest" | jq ".history"
Manifest v2 schema uses different Accept header and is more supported in these days and provides more information:
curl --request GET -sLH "Authorization: Bearer `jq -r '.token' auth.json`" -H "Accept: application/vnd.docker.distribution.manifest.v2+json" "https://index.docker.io/v2/<repository>/manifests/latest"
On response there is config section:
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 5802,
"digest": "sha256:2ff217b387d7bbc0ad3fb1cbb2cdae9f7e562f26065f847a1b69964fcb71108"
}
And finally download whole blob:
curl --request GET -LOH "Authorization: Bearer `jq -r '.token' auth.json`" "https://index.docker.io/v2/<repository>/blobs/sha256:2ff217b387d7bbc0ad3fb1cbb2cdae9f7e562f26065f847a1b69964fcb71108"
See contents of whole configuration file which contains environment variables with included history:
jq . sha256:2ff217b387d7bbc0ad3fb1cbb2cdae9f7e562f26065f847a1b69964fcb71108

Create repo on Bitbucket programmatically

I used to do
curl -k -X POST --user john#outlook.com:doe13 "https://api.bitbucket.org/1.0/repositories" -d "name=logoApp"
and success.
now I got : error
{"type": "error", "error": {"message": "Resource removed", "detail": "This API is no longer supported.\n\nFor information about its removal, please refer to the deprecation notice at: https://developer.atlassian.com/cloud/bitbucket/deprecation-notice-v1-apis/"}}
Does anyone know a know way to do this ?
There's a difference between a success from curl (OK:200) and an error from the service you're trying to use. The error, however, mentions that you're trying to use the Cloud Rest API version 1, which is deprecated effective 30 June 2018.
Read this for more information.
I don't use Bitbucket Server (a local option), and I think that has more features for this sort of thing.
For the public Bitbucket, you can still do it but it isn't documented.
The v1.0 API has been removed, and the new v2.0 API doesn't document a POST to a /repositories. Instead, you have to hit an endpoint that includes the repo that doesn't yet exist: /repositories/workspace/repo_slug
The JSON payload needs to know the project for the repo: look in the slug for a project that already exists. Fill in the user/team and repo name in the URL. And, you can make an application password so you aren't using your account password. This app password can limit the scope of what that access can do.
% curl -X POST --user 'user:app_pass' \
-H "Content-type: application/json" \
-d '{"project":{"key":"PROJ"}}' \
"https://api.bitbucket.org/2.0/repositories/USER/REPO"

Having count of open patches , but has to rename the branch

I have to rename my branch , but having lots of open patches in that branch. How to move those open patches to new branch without cherrypick.
Cherrypick is one of the option , but has to cherry pick every patch.
You can use the REST API to automate this task. You can find the open changes using the Query Changes endpoint (or just the "Search" field in the Gerrit UI) and than change their destination branch using the Move Change endpoint.
For example, you could put all open changes in a file (one change number in each line) and execute the following command:
for c in $(cat CHANGE-FILE)
do
curl -s --request POST --user USER:PASSWORD --data #- --header Content-Type:application/json GERRIT-SERVER/a/changes/CHANGE/move << EOF
{
"destination_branch" : "NEW-BRANCH"
}
EOF
done

Is there a way to rename a repository on Bitbucket using their API

I couldn't find anything even remotely related in the documentation.
Using the Bitbucket website you can rename a repo as follows:
Go to the repo's overview page, usually https://bitbucket.org/username/oldname/overview
Click the settings cog on the far right end of the menu row !
Instead of 1. and 2. you can type 'r' then 'a' for administration.
Change the name in the Name field.
Click Save repository details.
Be advised that changing the name of the repo will change its URL access too. Previously the access was https://username#bitbucket.org/username/oldname.git Now, however, the repo's URL/Path will be https://username#bitbucket.org/username/newname.git
You can check this by going back to the Overview page, and hovering over the big blue HTTPS button. The bottom of your browser will show that it now points to https://username#bitbucket.org/username/newname.git
If you are using SourceTree you can update the remote's URL by highlighting the local repo in SourceTree and then
Click Repository
Click Repository Settings...
Highlight the row containing the remote branch. Usually origin https://username#bitbucket.org/username/oldname.git
Click Edit
Update the URL/Path field. Change 'oldname.git' to 'newname.git', leave the rest unchanged. So the full path should be https://username#bitbucket.org/username/newname.git
Click OK
For version 2.0 of the API:
According to https://developer.atlassian.com/cloud/bitbucket/rest/api-group-repositories/#api-repositories-workspace-repo-slug-put
PUT https://api.bitbucket.org/2.0/repositories/{workspace}/{repo_slug} --data "{\"name\": \"${new_name}\"}"
Using the PUT method allows renaming of a repository.
For version 1.0 of the API:
According to https://confluence.atlassian.com/display/BITBUCKET/repository+Resource+1.0:
PUT https://api.bitbucket.org/1.0/repositories/{accountname}/{repo_slug} --data "name=new name"
This allows to update the visible name of a repository.
In a unix shell you can use cURL;
curl https://api.bitbucket.org/1.0/repositories/{accountname}/{old_repo_name} --data "name=new_repo_name" -X PUT
Is it possible for a user to authenticate in private repositories, but still have only administrators able to execute:
curl https://USER:PASS#api.bitbucket.org/1.0/repositories/{accountname}/{old_repo_name} --data "name=new_repo_name" -X PUT
Just in case anyone hits this with looking for a solution to an old version of the bitbucket API (in my case 5.14.0) to say the documentation on this version is lacking is being quite polite.
curl --location --request PUT 'https://git.local.install/rest/api/1.0/projects/aa/repos/my-repo' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic .....' \
--data-raw '{"name":"my-new-name"}'
According to the lastest API here is the correct curl command:
curl -X PUT --user username:password https://bitbucket.org/api/1.0/repositories/{accountname}/{repo_slug} --data "name=newRepoName"
Note that the repo_slug is the repository name IN LOWER CASE. If you don't put it all in lower case you would get the not so expressive answer "Not Found".
If you are not sure what is the repository slug execute the following command, which shows you the user's information including current repositories, and look for the field "slug"
curl --user username:password https://bitbucket.org/api/1.0/user

Resources