Skip to content

Commit cbbca23

Browse files
committed
ci: add workflow to create pipeline to test
1 parent 5aba541 commit cbbca23

File tree

1 file changed

+177
-0
lines changed

1 file changed

+177
-0
lines changed

.github/workflows/ci-pull-request.yml

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
pull_request:
55
branches:
66
- main
7+
workflow_dispatch:
78

89
permissions:
910
contents: write
@@ -54,3 +55,179 @@ jobs:
5455
exit 1
5556
fi
5657
echo "new_version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
58+
59+
60+
ado-pr-ephemeral:
61+
runs-on: ubuntu-latest
62+
env:
63+
YAML_PATH: .azure-pipelines.yml
64+
PR_NUMBER: ${{ github.event.pull_request.number }}
65+
PR_BRANCH: ${{ github.head_ref }}
66+
PR_SHA: ${{ github.event.pull_request.head.sha }}
67+
PIPELINE_NAME: pr-${{ github.event.pull_request.number }}-${{ github.run_id }}
68+
69+
steps:
70+
- uses: actions/checkout@v4
71+
72+
- name: Azure login (OIDC)
73+
uses: azure/login@v2
74+
with:
75+
client-id: ${{ secrets.AZURE_APPLICATION_CLIENT_ID }}
76+
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
77+
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
78+
79+
- name: Install jq & curl
80+
run: sudo apt-get update -y && sudo apt-get install -y jq curl
81+
82+
- name: Get Azure DevOps AAD token
83+
id: token
84+
run: |
85+
ADO_TOKEN=$(az account get-access-token --resource https://app.vssps.visualstudio.com/ --query accessToken -o tsv)
86+
if [ -z "$ADO_TOKEN" ]; then echo "No token for Azure DevOps"; exit 1; fi
87+
echo "::add-mask::$ADO_TOKEN"
88+
echo "ADO_TOKEN=$ADO_TOKEN" >> $GITHUB_ENV
89+
90+
- name: Autodetect Azure DevOps organization (if not provided)
91+
id: org
92+
env:
93+
ADO_TOKEN: ${{ env.ADO_TOKEN }}
94+
run: |
95+
if [ -n "${AZDO_ORG}" ]; then
96+
echo "Using AZDO_ORG=${AZDO_ORG} (provided)"; exit 0
97+
fi
98+
ACCOUNTS=$(curl -sS -H "Authorization: Bearer ${ADO_TOKEN}" \
99+
"https://app.vssps.visualstudio.com/_apis/accounts?api-version=7.1")
100+
COUNT=$(echo "$ACCOUNTS" | jq '.count')
101+
if [ "$COUNT" -eq 0 ]; then
102+
echo "This user does not belong to any Azure DevOps org."; exit 1
103+
fi
104+
if [ "$COUNT" -gt 1 ]; then
105+
echo "Multiple orgs detected. Export AZDO_ORG with one of those and retry:"; \
106+
echo "$ACCOUNTS" | jq -r '.value[] | "\(.accountName) (\(.accountId))"'; exit 1
107+
fi
108+
AZDO_ORG_AUTO=$(echo "$ACCOUNTS" | jq -r '.value[0].accountName')
109+
echo "AZDO_ORG=$AZDO_ORG_AUTO" >> $GITHUB_ENV
110+
echo "Detected AZDO_ORG=${AZDO_ORG_AUTO}"
111+
112+
- name: Autodetect Azure DevOps project (if not provided)
113+
id: proj
114+
env:
115+
ADO_TOKEN: ${{ env.ADO_TOKEN }}
116+
run: |
117+
ORG="${AZDO_ORG:-${{ env.AZDO_ORG }}}"
118+
PROJS=$(curl -sS -H "Authorization: Bearer ${ADO_TOKEN}" \
119+
"https://dev.azure.com/${ORG}/_apis/projects?api-version=7.1")
120+
COUNT=$(echo "$PROJS" | jq '.count')
121+
if [ "$COUNT" -eq 0 ]; then
122+
echo "No projects detected in org ${ORG}."; exit 1
123+
fi
124+
if [ -n "${AZDO_PROJECT}" ]; then
125+
echo "Using AZDO_PROJECT=${AZDO_PROJECT} (provided)"
126+
else
127+
if [ "$COUNT" -gt 1 ]; then
128+
echo "Multiple projects detected. Export AZDO_PROJECT with one of those and try again:"; \
129+
echo "$PROJS" | jq -r '.value[] | .name'; exit 1
130+
fi
131+
AZDO_PROJECT_AUTO=$(echo "$PROJS" | jq -r '.value[0].name')
132+
echo "AZDO_PROJECT=$AZDO_PROJECT_AUTO" >> $GITHUB_ENV
133+
echo "Detected AZDO_PROJECT=${AZDO_PROJECT_AUTO}"
134+
fi
135+
136+
- name: Find a GitHub Service Connection
137+
id: sc
138+
env:
139+
ADO_TOKEN: ${{ env.ADO_TOKEN }}
140+
run: |
141+
ORG="${AZDO_ORG:-${{ env.AZDO_ORG }}}"
142+
PROJ="${AZDO_PROJECT:-${{ env.AZDO_PROJECT }}}"
143+
LIST=$(curl -sS -H "Authorization: Bearer ${ADO_TOKEN}" \
144+
"https://dev.azure.com/${ORG}/${PROJ}/_apis/serviceendpoint/endpoints?api-version=7.1")
145+
echo "$LIST" | jq -r '.value[] | {id,type:.type,name:.name}'
146+
SC_ID=$(echo "$LIST" | jq -r '.value[] | select((.type|ascii_downcase|contains("github"))) | .id' | head -n1)
147+
if [ -z "$SC_ID" ] || [ "$SC_ID" = "null" ]; then
148+
echo "No Github Service Connection detected in ${PROJ}. Create one (GitHub/GitHub App) and retry."; exit 1
149+
fi
150+
echo "sc_id=${SC_ID}" >> "$GITHUB_OUTPUT"
151+
152+
- name: Create ephemeral pipeline
153+
id: create
154+
env:
155+
ADO_TOKEN: ${{ env.ADO_TOKEN }}
156+
run: |
157+
ORG="${AZDO_ORG:-${{ env.AZDO_ORG }}}"
158+
PROJ="${AZDO_PROJECT:-${{ env.AZDO_PROJECT }}}"
159+
SC_ID="${{ steps.sc.outputs.sc_id }}"
160+
BODY=$(jq -n \
161+
--arg name "${PIPELINE_NAME}" \
162+
--arg folder "pr-validation" \
163+
--arg path "${YAML_PATH}" \
164+
--arg repo "${GITHUB_REPOSITORY}" \
165+
--arg scid "${SC_ID}" \
166+
'{
167+
name:$name, folder:$folder,
168+
configuration:{
169+
type:"yaml", path:$path,
170+
repository:{ type:"github", name:$repo, connection:{id:$scid} }
171+
}
172+
}')
173+
RESP=$(curl -sS -X POST -H "Authorization: Bearer ${ADO_TOKEN}" -H "Content-Type: application/json" \
174+
-d "${BODY}" "https://dev.azure.com/${ORG}/${PROJ}/_apis/pipelines?api-version=7.1")
175+
echo "$RESP" | jq .
176+
PIPELINE_ID=$(echo "$RESP" | jq -r '.id')
177+
if [ -z "$PIPELINE_ID" ] || [ "$PIPELINE_ID" = "null" ]; then echo "Create failed"; exit 1; fi
178+
echo "PIPELINE_ID=$PIPELINE_ID" >> $GITHUB_ENV
179+
180+
- name: Run pipeline for exact PR commit
181+
id: run
182+
env:
183+
ADO_TOKEN: ${{ env.ADO_TOKEN }}
184+
run: |
185+
ORG="${AZDO_ORG:-${{ env.AZDO_ORG }}}"
186+
PROJ="${AZDO_PROJECT:-${{ env.AZDO_PROJECT }}}"
187+
PIPELINE_ID="${PIPELINE_ID}"
188+
BODY=$(jq -n --arg ref "refs/heads/${PR_BRANCH}" --arg ver "${PR_SHA}" \
189+
'{resources:{repositories:{self:{refName:$ref, version:$ver}}}}')
190+
RUN=$(curl -sS -X POST -H "Authorization: Bearer ${ADO_TOKEN}" -H "Content-Type: application/json" \
191+
-d "${BODY}" "https://dev.azure.com/${ORG}/${PROJ}/_apis/pipelines/${PIPELINE_ID}/runs?api-version=7.1")
192+
echo "$RUN" | jq .
193+
RUN_ID=$(echo "$RUN" | jq -r '.id')
194+
if [ -z "$RUN_ID" ] || [ "$RUN_ID" = "null" ]; then echo "Queue failed"; exit 1; fi
195+
echo "RUN_ID=$RUN_ID" >> $GITHUB_ENV
196+
197+
- name: Wait for completion
198+
env:
199+
ADO_TOKEN: ${{ env.ADO_TOKEN }}
200+
run: |
201+
ORG="${AZDO_ORG:-${{ env.AZDO_ORG }}}"
202+
PROJ="${AZDO_PROJECT:-${{ env.AZDO_PROJECT }}}"
203+
echo "Polling run ${RUN_ID}..."
204+
while true; do
205+
R=$(curl -sS -H "Authorization: Bearer ${ADO_TOKEN}" \
206+
"https://dev.azure.com/${ORG}/${PROJ}/_apis/pipelines/${PIPELINE_ID}/runs/${RUN_ID}?api-version=7.1")
207+
STATE=$(echo "$R" | jq -r '.state')
208+
RESULT=$(echo "$R" | jq -r '.result')
209+
echo "state=$STATE result=$RESULT"
210+
if [ "$STATE" = "completed" ]; then
211+
[ "$RESULT" = "succeeded" ] && exit 0 || exit 1
212+
fi
213+
sleep 10
214+
done
215+
216+
- name: Delete ephemeral pipeline (cleanup)
217+
if: ${{ !cancelled() }}
218+
env:
219+
ADO_TOKEN: ${{ env.ADO_TOKEN }}
220+
run: |
221+
ORG="${AZDO_ORG:-${{ env.AZDO_ORG }}}"
222+
PROJ="${AZDO_PROJECT:-${{ env.AZDO_PROJECT }}}"
223+
# Resuelve build definition por nombre y bórrala
224+
DEF=$(curl -sS -H "Authorization: Bearer ${ADO_TOKEN}" \
225+
"https://dev.azure.com/${ORG}/${PROJ}/_apis/build/definitions?name=${PIPELINE_NAME}&api-version=7.1")
226+
DEF_ID=$(echo "$DEF" | jq -r '.value[0].id')
227+
if [ -n "$DEF_ID" ] && [ "$DEF_ID" != "null" ]; then
228+
curl -sS -X DELETE -H "Authorization: Bearer ${ADO_TOKEN}" \
229+
"https://dev.azure.com/${ORG}/${PROJ}/_apis/build/definitions/${DEF_ID}?api-version=7.1" \
230+
-o /dev/null -w "Deleted definition ${DEF_ID} (HTTP %{http_code})\n"
231+
else
232+
echo "No build definition found for ${PIPELINE_NAME}; nothing to delete."
233+
fi

0 commit comments

Comments
 (0)