238b49a04a
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
268 lines
8.5 KiB
YAML
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"
|