Ok, after much figuring out, I figured out a way. I'm not sure if this is the best way but it works. I've changed the goal for the Bitbucket Pipeline to beautify the code and commit the reformatted code whenever a pull request is created or updated instead.
This solution is inspired by:
Step 1: Create an OAuth2 Consumer
- Go to "Workspace Settings"
- Under category "Apps and Features", click "OAuth consumers"
- Click "Add consumer", fill out necessary information. Makes sure to add permission to "read" and "write" for Pull Requests permission category. Also, "Callback URL" can't be empty, I used https://google.com .
- Click "Save"
- Your new OAuth consumer will have a Key and Secret generated

Step 2: Configure the Bitbucket Respository
- Go to the repository that will have the Bitbucket Pipeline setup
- Click "Repository settings"
- Under category "Pipelines", click "Repository variables"
- Add a new variable with name being
BB_AUTH_STRING
and value being a string of format Key:Secret
(see picture), using the key and secret of the OAuth consumer we created earlier
- Make sure to fill the checkbox "Secured" before clicking "Add"

Step 3: Setup your Bitbucket Pipeline YML
The bitbucket-pipelines.yml
I've settled on currently is the following:
image: python:3.10
pipelines:
pull-requests:
'**':
- step:
name: Commit if there are changed files
script:
- apt-get update
- apt-get -y install curl jq
- pip install black
- black -l 100 .
- modified=$(if git diff-index --quiet HEAD --; then echo "false"; else echo "true"; fi)
# BB_AUTH_STRING is a "Repository Variable",
# it's value is a string of the format "Key:Secret"
# with "Key" and "Secret" being the key and secret of a OAuth2 Workspace Consumer
- >
if [ "$modified" = "false" ]; then
exit 0;
else
export BB_TOKEN=$(curl -s -S -f -X POST -u "${BB_AUTH_STRING}" \
https://bitbucket.org/site/oauth2/access_token \
-d grant_type=client_credentials -d scopes="repository" | jq --raw-output '.access_token') ;
git config --global user.name 'Automatic Linter';
git config --global user.email 'techs@domain.com';
git remote set-url origin "https://x-token-auth:${BB_TOKEN}@bitbucket.org/vietthan/myrepositoryname.git";
git add -A;
git commit -m "[skip ci] automatic linter";
git push;
fi
condition:
changesets:
includePaths:
- "**"
This pipeline will only run whenever a Pull-Request is created and whenever new commits are made to the Pull Request.
The pipeline will install curl
and jq
.
The pipeline will install black
.
The pipeline will then run black -l 100
.
If no files were modified, the pipeline will exit.
Else:
- It will use
BB_AUTH_STRING
to get a temporary access token stored in BB_TOKEN
.
- It will set the git configuration for name, email
- It will set the git remote path+access token, I have this pointed to my intending repository.
- It will add all changed files, make a commit with
[skip ci]
in the commit head message to skip the pipeline when this commit is push
- Push the commit
Conclusion
You now have a bitbucket pipeline that will automatically format Python code with black
whenever your developers create a pull request or push new commits to it. It will avoid infinite bitbucket pipeline builds, it will detect if there are changes before committing.