Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 51 additions & 117 deletions .github/workflows/validate-pr-ab-id.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,149 +10,83 @@ on:
types: [opened, reopened, edited, labeled, synchronize]

jobs:
# This action checks your pull request to make sure it is linked to a work item using AB# before you can merge.
validation:
name: Check if PR has a valid ADO ID
check-and-apply-abid:
name: Check and apply AB#ID to PR title
permissions:
contents: read
issues: write
pull-requests: write
runs-on: ubuntu-latest
if: "!contains(github.event.pull_request.labels.*.name, 'skip AB ID validation')"
steps:
- uses: danhellem/github-actions-pr-is-linked-to-work-item@main

# Get AB#ID
get_ab_id:
name: Get AB ID
runs-on: ubuntu-latest
needs: validation
outputs:
abid: ${{ steps.get.outputs.id }}
steps:
# Extracts the AB ID from the pull_request body using regex and store the result using outputs
- name: Get AB ID from comment
id: get
- name: Validate PR is linked to a work item
uses: danhellem/github-actions-pr-is-linked-to-work-item@main
continue-on-error: true

- name: Extract AB ID from PR body
id: extract-ab
shell: bash
env:
PR_BODY: ${{ github.event.pull_request.body }}
run: |
result=$(echo "$PR_BODY" | grep -oP '(?<=#)\d+')
echo "id=${result}" >> "$GITHUB_OUTPUT"
clean=$(printf "%s" "$PR_BODY" | tr -d '`')
# Get first AB ID if multiple are present
abid=$(printf "%s" "$clean" | grep -oP '(?<=AB#)\d+' | head -n1 || true)
echo "abid=${abid}" >> $GITHUB_OUTPUT

# Get Pull request ID
get_pr_id:
name: Get PR ID
runs-on: ubuntu-latest
needs: validation
outputs:
prid: ${{ steps.pr.outputs.id }}
steps:
# Extracts the pull request id and store the result using outputs
- name: Extract pull request id
id: pr
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
run: echo "id=$PR_NUMBER" >> $GITHUB_OUTPUT
- name: Abort if no AB ID found
if: steps.extract-ab.outputs.abid == ''
run: |
echo "No AB ID found in PR body; failing the workflow."
exit 1

# Get Pull request title
get_pr_title:
name: Get PR title
permissions:
contents: read
issues: read
pull-requests: read
runs-on: ubuntu-latest
needs: get_pr_id
outputs:
prtitle: ${{ steps.current-title.outputs.title }}
steps:
# Get current PR title
- name: Get the current PR title
id: current-title
- name: Get current PR title
id: get-title
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_ID: ${{ needs.get_pr_id.outputs.prid }}
PR_ID: ${{ github.event.pull_request.number }}
run: |
PR_TITLE=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${PR_ID}" \
| jq -r .title)
PR_TITLE=$(curl -s -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/${{ github.repository }}/pulls/${{ env.PR_ID }} | jq -r .title)
echo "title=$PR_TITLE" >> $GITHUB_OUTPUT

# Checks if the Pull request contains Fixed AB#ID in the title,
# if not cretaes a new title appending ',Fixed AB#ID' to the current title
check_if_title_needs_to_be_updated:
name: Check if title needs to be updated
runs-on: ubuntu-latest
needs: [get_pr_title, get_ab_id]
outputs:
new_pr_title: ${{ steps.new-title.outputs.new_pr_title }}
update_required: ${{ steps.check.outputs.update_required }}
steps:
- name: Check if PR title contains fix keyword with AB# using grep
id: check
- name: Decide if title needs update
id: decide
shell: bash
env:
PR_TITLE: ${{ needs.get_pr_title.outputs.prtitle }}
PR_TITLE: ${{ steps.get-title.outputs.title }}
AB_ID: ${{ steps.extract-ab.outputs.abid }}
run: |
if echo "$PR_TITLE" | grep -i -q '\bfix\(ed\|es\)\? AB#[0-9]'; then
echo "Pattern found in PR title!, no need to update."
if [ -z "${AB_ID}" ]; then
echo "update_required=false" >> $GITHUB_OUTPUT
exit 0
fi
if echo "$PR_TITLE" | grep -i -qE '\bfix(es|ed)?\b.*AB#[0-9]'; then
echo "update_required=false" >> $GITHUB_OUTPUT
else
echo "Pattern not found in PR title!"
NEW_TITLE="$PR_TITLE, Fixes AB#${AB_ID}"
echo "update_required=true" >> $GITHUB_OUTPUT
echo "new_title=${NEW_TITLE}" >> $GITHUB_OUTPUT
fi
- name: Generate new PR title
env:
AB_ID: ${{ needs.get_ab_id.outputs.abid }}
CURRENT_PR_TITLE: ${{ needs.get_pr_title.outputs.prtitle }}
if: steps.check.outputs.update_required == 'true'
id: new-title
run: |
NEW_TITLE="$CURRENT_PR_TITLE, Fixes AB#$AB_ID"
echo "new_pr_title=${NEW_TITLE}" >> $GITHUB_OUTPUT

# Update new title
update_title:
name: Update title
permissions:
contents: read
issues: write
pull-requests: write
runs-on: ubuntu-latest
needs: [check_if_title_needs_to_be_updated, get_pr_id]
if: needs.check_if_title_needs_to_be_updated.outputs.update_required == 'true'
steps:
- name: Update the pull request title
- name: Update PR title (if required)
if: steps.decide.outputs.update_required == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_ID: ${{ needs.get_pr_id.outputs.prid }}
NEW_TITLE: ${{ needs.check_if_title_needs_to_be_updated.outputs.new_pr_title }}
PR_ID: ${{ github.event.pull_request.number }}
NEW_TITLE: ${{ steps.decide.outputs.new_title }}
run: |
curl -X PATCH \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${PR_ID}" \
-d "$(jq -n --arg title "$NEW_TITLE" '{title: $title}')"

# This job will determine the final status of the workflow and can be made a requirement before merging.
# The job will succeed if any of the following conditions are met:
# 1. The pull request title was successfully updated.
# 2. The pull request has the 'skip AB ID validation' label.
# 3. The title was already updated.
status_report:
name: AB ID validation Check
runs-on: ubuntu-latest
needs: [update_title, check_if_title_needs_to_be_updated, validation]
if: always()
steps:
- name: Check status of job1
id: check_status
curl -s -X PATCH -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/${{ github.repository }}/pulls/${{ env.PR_ID }} -d '{"title":"'"${{ env.NEW_TITLE }}"'"}'

- name: Final status reporting
if: always()
run: |
if [[ "${{ needs.update_title.result }}" == "success" ]] ||
[[ "${{ needs.validation.result }}" == "skipped" ]] ||
[[ "${{ needs.update_title.result }}" == "skipped" && "${{ needs.check_if_title_needs_to_be_updated.result }}" == "success" ]]; then
echo "Job succeeded or was skipped."
else
echo "Job failed or was cancelled."
exit 1
# Consider the run successful if either title was updated or the PR was skipped due to missing AB ID
if [ "${{ steps.decide.outputs.update_required }}" == "true" ]; then
echo "PR title updated to include AB ID."
exit 0
fi
if [ "${{ steps.extract-ab.outputs.abid }}" == "" ]; then
echo "No AB ID found; validation skipped by design."
exit 0
fi
echo "No change required or validation passed."
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# File: azure-pipelines/pull-request-validation/pr-msal-instrumented.yml
# Description: PR validation that runs MSAL instrumented (androidTest) tests on the 1ES Ubuntu build
# agents (which expose KVM, so the x86_64 emulator hardware-accelerates and boots
# reliably; the old Microsoft-hosted macOS pipeline was flaky). This is a thin
# 1ES-Unofficial wrapper that reuses the shared run-instrumented-tests.yml template from
# the AuthClientAndroidPipelines repo. gitProject: self checks out the PR commit, so this
# works as a Build Validation branch policy on the msal repo.
name: $(date:yyyyMMdd)$(rev:.r)

# PR validation is driven by a Build Validation branch policy in ADO, not by YAML triggers.
pr: none
trigger: none

resources:
repositories:
- repository: 1ESPipelineTemplates
type: git
name: 1ESPipelineTemplates/1ESPipelineTemplates
ref: refs/tags/release
- repository: AuthClientAndroidPipelines
type: git
name: Engineering/AuthClientAndroidPipelines
ref: refs/heads/main

variables:
- group: AndroidAuthClientAutomationSecrets

extends:
template: v1/1ES.Unofficial.PipelineTemplate.yml@1ESPipelineTemplates
parameters:
pool:
name: MSSecurity-1ES-Build-Agents-Pool
image: MSSecurity-1ES-Ubuntu-2204
os: linux
sdl:
# Anti-malware is injected by default and is only supported on Windows agents.
enableAllTools: false
sourceAnalysisPool:
name: MSSecurity-1ES-Build-Agents-Pool
image: MSSecurity-1ES-Windows-2022
os: windows
stages:
- stage: instrumented_tests
displayName: MSAL Instrumented Tests
dependsOn: []
jobs:
- template: templates/runTests/run-instrumented-tests.yml@AuthClientAndroidPipelines
parameters:
gitProject: self
projectName: msal
gradleOptions: -Psugar=true -PlabSecret=/data/local/tmp/LabAuth.pfx
10 changes: 10 additions & 0 deletions msal/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,16 @@ dependencies {
// Set this dependency to use JUnit 4 rules
androidTestImplementation "androidx.test:rules:$rootProject.rulesVersion"
androidTestImplementation "org.mockito:mockito-android:$rootProject.ext.mockitoAndroidVersion"
// testutils is pulled in solely for FlakyTestRetryRule + @RetryFlakyTest (retrying flaky
// instrumented tests; the org.gradle.test-retry plugin only covers JVM/Robolectric unit tests).
// transitive = false keeps only the rule's classes and avoids dragging testutils' whole
// transitive graph onto the androidTest classpath.
androidTestLocalImplementation(project(':testutils')) {
transitive = false
}
androidTestDistImplementation("com.microsoft.identity:testutils:0.0+") {
transitive = false
}
// 'local' flavor dependencies
localApi(project(":common")) {
transitive = true
Expand Down
Loading