Files
doczyai-pipelines/bitbucket-pipelines.yml
T
Sujit Deokar 238b49a04a Merged in feature/DAIP2-1575-set-up-dev-prod-uat-branches- (pull request #931)
Feature/DAIP2-1575 set up dev prod uat branches

* Add branch promotion gates and release pipelines

* Add resolve_source_branch.sh script and update .gitignore; fix pipeline step name casing 'dev'

* Add AI code review step and refactor branch resolution in pipelines

* Merged dev into feature/DAIP2-1575-set-up-dev-prod-uat-branches-

* Merged dev into feature/DAIP2-1575-set-up-dev-prod-uat-branches-

* Merged dev into feature/DAIP2-1575-set-up-dev-prod-uat-branches-


Approved-by: Katon Minhas
2026-04-02 19:42:12 +00:00

268 lines
8.5 KiB
YAML

definitions:
scripts:
- script: &install
pip install uv;
uv sync --group dev --group test;
- script: &resolve-branch
source resolve_source_branch.sh;
echo "PR source branch:$SOURCE_BRANCH";
echo "PR destination branch:${BITBUCKET_PR_DESTINATION_BRANCH}";
steps:
- step: &install-deps
name: Install Dependencies
image: python:3.12.7
script:
- *install
caches:
- pip
- step: &lint
name: Lint (black)
image: python:3.12.7
script:
- *install
- uv run black --check src/
caches:
- pip
- step: &typecheck
name: Type Check (mypy)
image: python:3.12.7
script:
- *install
- uv run mypy src/
caches:
- pip
- step: &unit-tests
name: Unit Tests (pytest)
image: python:3.12.7
script:
- *install
- uv run pytest src/tests/
caches:
- pip
- step: &ai-code-review
name: AI Code Review
image: python:3.12-slim
oidc: true
script:
- apt-get update && apt-get install -y git
- pip install boto3 requests
- export AWS_REGION=us-east-1
- export AWS_ROLE_ARN=arn:aws:iam::975049960860:role/DoczyAI-Bitbucket-OIDC
- export AWS_WEB_IDENTITY_TOKEN_FILE=$(pwd)/web-identity-token
- echo $BITBUCKET_STEP_OIDC_TOKEN > $(pwd)/web-identity-token
- git clone https://x-token-auth:${BITBUCKET_CLONE_TOKEN}@bitbucket.org/${BITBUCKET_WORKSPACE}/code-review-agent.git
- export PR_URL="https://bitbucket.org/${BITBUCKET_WORKSPACE}/${BITBUCKET_REPO_SLUG}/pull-requests/${BITBUCKET_PR_ID}"
- cd code-review-agent && python main.py "$PR_URL"
pipelines:
default:
- step: *install-deps
- parallel:
- step: *lint
- step: *typecheck
- step: *unit-tests
pull-requests:
"feature/*":
- step: *install-deps
- parallel:
- step: *lint
- step: *typecheck
- step: *unit-tests
- step:
name: "Gate: feature PR must target dev only"
script:
- *resolve-branch
- |
if [ "${BITBUCKET_PR_DESTINATION_BRANCH}" != "dev" ]; then
echo "Blocked: feature PR must target dev only"
exit 1
fi
- step: *ai-code-review
dev:
- step: *install-deps
- parallel:
- step: *lint
- step: *typecheck
- step: *unit-tests
- step:
name: "Gate: only allow PR from dev -> stg"
script:
- *resolve-branch
- |
if [ "${BITBUCKET_PR_DESTINATION_BRANCH}" != "stg" ]; then
echo "Blocked: dev PR must target stg only for this pipeline."
exit 1
fi
- step: *ai-code-review
stg:
- step: *install-deps
- parallel:
- step: *lint
- step: *typecheck
- step: *unit-tests
- step:
name: "Gate: only allow PR from stg -> main"
script:
- *resolve-branch
- |
if [ "${BITBUCKET_PR_DESTINATION_BRANCH}" != "main" ]; then
echo "Blocked: stg PR must target main only."
exit 1
fi
- step: *ai-code-review
# Hotfix promotion gate (hotfix/* -> main OR dev only)
"hotfix/*":
- step: *install-deps
- parallel:
- step: *lint
- step: *typecheck
- step: *unit-tests
- step:
name: "Gate: allow hotfix PR only to main or dev"
script:
- *resolve-branch
- |
if [ "${BITBUCKET_PR_DESTINATION_BRANCH}" != "main" ] && \
[ "${BITBUCKET_PR_DESTINATION_BRANCH}" != "dev" ]; then
echo "Blocked: hotfix PR must target main or dev only."
exit 1
fi
- step: *ai-code-review
# bugfix promotion gate (bugfix/* -> dev only)
"bugfix/*":
- step: *install-deps
- parallel:
- step: *lint
- step: *typecheck
- step: *unit-tests
- step:
name: "Gate: bugfix PR must target dev only"
script:
- *resolve-branch
- |
if [ "${BITBUCKET_PR_DESTINATION_BRANCH}" != "dev" ]; then
echo "Blocked: bugfix PR must target dev only"
exit 1
fi
- step: *ai-code-review
#PR pipeline check for branch name validation
'**':
- step: *install-deps
- parallel:
- step: *lint
- step: *typecheck
- step: *unit-tests
- step:
name: Validate branch name
image: atlassian/default-image:4
script:
- |
echo "Validating PR source branch name..."
- *resolve-branch
- |
if [[ ! "$SOURCE_BRANCH" =~ ^(feature|bugfix|hotfix)/.+$ ]]; then
echo " ERROR - Invalid branch name"
echo "OK - Allowed formats:"
echo " - feature/<description>"
echo " - bugfix/<description>"
echo " - hotfix/<description>"
exit 1
fi
echo "OK - Branch name is valid"
- step: *ai-code-review
custom:
release-prod:
- variables:
- name: RELEASE_TYPE
default: minor
allowed-values:
- major
- minor
- step:
name: "Create release tag"
script:
- source resolve_source_branch.sh
- echo "PR source branch:$SOURCE_BRANCH"
if [ "$SOURCE_BRANCH" != "main" ]; then
echo "Blocked- releases can only be created from main."
exit 1
fi
- git config user.email "bitbucket-pipelines@local"
- git config user.name "Bitbucket Pipelines"
- git fetch --tags --force
- latest_tag=$(git tag -l "v*" | sort -V | tail -n1)
- if [ -z "$latest_tag" ]; then latest_tag="v0.0.0"; fi
- version=$(echo "$latest_tag" | sed 's/^v//')
- major=$(echo "$version" | cut -d. -f1)
- minor=$(echo "$version" | cut -d. -f2)
- |
if [ "$RELEASE_TYPE" = "major" ]; then
major=$((major + 1))
minor=0
patch=0
else
minor=$((minor + 1))
patch=0
fi
- new_tag="v${major}.${minor}.${patch}"
- echo "Creating tag:${new_tag}"
- git tag -a "$new_tag" -m "Release ${new_tag}"
- git push origin "$new_tag"
- echo "$new_tag" > release_tag.txt
artifacts:
- release_tag.txt
- step:
name: "Deploy release to production"
deployment: production
script:
- export RELEASE_TAG=$(cat release_tag.txt)
- echo "Deploying ${RELEASE_TAG}"
- |
if [ -z "${DEPLOY_COMMAND}" ]; then
echo "Blocked: set repository variable DEPLOY_COMMAND (use \\$RELEASE_TAG inside command)."
exit 1
fi
- sh -c "$DEPLOY_COMMAND"
rollback-prod:
- variables:
- name: ROLLBACK_TAG
default: v0.0.0
- step:
name: "Rollback: validate release tag"
script:
- source resolve_source_branch.sh
- echo "PR source branch:$SOURCE_BRANCH"
if [ "$SOURCE_BRANCH" != "main" ]; then
echo "Blocked- rollback can only run from main."
exit 1
fi
- |
if [ -z "${ROLLBACK_TAG}" ]; then
echo "Blocked: ROLLBACK_TAG is required."
exit 1
fi
- git fetch --tags --force
- |
if ! git rev-parse "${ROLLBACK_TAG}" >/dev/null 2>&1; then
echo "Blocked: tag ${ROLLBACK_TAG} does not exist."
exit 1
fi
- step:
name: "Rollback deploy to production"
deployment: production
script:
- export RELEASE_TAG="${ROLLBACK_TAG}"
- echo "Rolling back to ${RELEASE_TAG}"
- |
if [ -z "${DEPLOY_COMMAND}" ]; then
echo "Blocked: set repository variable DEPLOY_COMMAND (use \\$RELEASE_TAG inside command)."
exit 1
fi
- sh -c "$DEPLOY_COMMAND"