Skip to content

Commit c6505e3

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

File tree

1 file changed

+184
-0
lines changed

1 file changed

+184
-0
lines changed

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

Lines changed: 184 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,186 @@ 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+
APP_ID: ${{ secrets.AZURE_APPLICATION_CLIENT_ID }}
95+
run: |
96+
SP_OBJ_ID=$(az ad sp show --id "$APP_ID" --query id -o tsv)
97+
if [ -z "$SP_OBJ_ID" ]; then echo "No SP objectId"; exit 1; fi
98+
99+
ACCOUNTS=$(curl -sS -H "Authorization: Bearer ${ADO_TOKEN}" \
100+
"https://app.vssps.visualstudio.com/_apis/accounts?memberId=${SP_OBJ_ID}&api-version=7.1")
101+
echo "$ACCOUNTS"
102+
103+
COUNT=$(echo "$ACCOUNTS" | jq '.count')
104+
if [ "$COUNT" -eq 0 ]; then
105+
echo "This SP does not belong to any Azure DevOps org. Ask an admin to add this SP to an org/project and retry."
106+
exit 1
107+
fi
108+
if [ "$COUNT" -gt 1 ]; then
109+
echo "Multiple orgs detected. Export AZDO_ORG with one of those and retry:"
110+
echo "$ACCOUNTS" | jq -r '.value[] | .accountName'
111+
exit 1
112+
fi
113+
AZDO_ORG_AUTO=$(echo "$ACCOUNTS" | jq -r '.value[0].accountName')
114+
echo "AZDO_ORG=$AZDO_ORG_AUTO" >> $GITHUB_ENV
115+
echo "Detectado AZDO_ORG=${AZDO_ORG_AUTO}"
116+
117+
- name: Autodetect Azure DevOps project (if not provided)
118+
id: proj
119+
env:
120+
ADO_TOKEN: ${{ env.ADO_TOKEN }}
121+
run: |
122+
ORG="${AZDO_ORG:-${{ env.AZDO_ORG }}}"
123+
PROJS=$(curl -sS -H "Authorization: Bearer ${ADO_TOKEN}" \
124+
"https://dev.azure.com/${ORG}/_apis/projects?api-version=7.1")
125+
echo "$PROJS"
126+
COUNT=$(echo "$PROJS" | jq '.count')
127+
if [ "$COUNT" -eq 0 ]; then
128+
echo "No projects detected in org ${ORG}."; exit 1
129+
fi
130+
if [ -n "${AZDO_PROJECT}" ]; then
131+
echo "Using AZDO_PROJECT=${AZDO_PROJECT} (provided)"
132+
else
133+
if [ "$COUNT" -gt 1 ]; then
134+
echo "Multiple projects detected. Export AZDO_PROJECT with one of those and try again:"; \
135+
echo "$PROJS" | jq -r '.value[] | .name'; exit 1
136+
fi
137+
AZDO_PROJECT_AUTO=$(echo "$PROJS" | jq -r '.value[0].name')
138+
echo "AZDO_PROJECT=$AZDO_PROJECT_AUTO" >> $GITHUB_ENV
139+
echo "Detected AZDO_PROJECT=${AZDO_PROJECT_AUTO}"
140+
fi
141+
142+
- name: Find a GitHub Service Connection
143+
id: sc
144+
env:
145+
ADO_TOKEN: ${{ env.ADO_TOKEN }}
146+
run: |
147+
ORG="${AZDO_ORG:-${{ env.AZDO_ORG }}}"
148+
PROJ="${AZDO_PROJECT:-${{ env.AZDO_PROJECT }}}"
149+
LIST=$(curl -sS -H "Authorization: Bearer ${ADO_TOKEN}" \
150+
"https://dev.azure.com/${ORG}/${PROJ}/_apis/serviceendpoint/endpoints?api-version=7.1")
151+
echo "$LIST"
152+
echo "$LIST" | jq -r '.value[] | {id,type:.type,name:.name}'
153+
SC_ID=$(echo "$LIST" | jq -r '.value[] | select((.type|ascii_downcase|contains("github"))) | .id' | head -n1)
154+
if [ -z "$SC_ID" ] || [ "$SC_ID" = "null" ]; then
155+
echo "No Github Service Connection detected in ${PROJ}. Create one (GitHub/GitHub App) and retry."; exit 1
156+
fi
157+
echo "sc_id=${SC_ID}" >> "$GITHUB_OUTPUT"
158+
159+
- name: Create ephemeral pipeline
160+
id: create
161+
env:
162+
ADO_TOKEN: ${{ env.ADO_TOKEN }}
163+
run: |
164+
ORG="${AZDO_ORG:-${{ env.AZDO_ORG }}}"
165+
PROJ="${AZDO_PROJECT:-${{ env.AZDO_PROJECT }}}"
166+
SC_ID="${{ steps.sc.outputs.sc_id }}"
167+
BODY=$(jq -n \
168+
--arg name "${PIPELINE_NAME}" \
169+
--arg folder "pr-validation" \
170+
--arg path "${YAML_PATH}" \
171+
--arg repo "${GITHUB_REPOSITORY}" \
172+
--arg scid "${SC_ID}" \
173+
'{
174+
name:$name, folder:$folder,
175+
configuration:{
176+
type:"yaml", path:$path,
177+
repository:{ type:"github", name:$repo, connection:{id:$scid} }
178+
}
179+
}')
180+
RESP=$(curl -sS -X POST -H "Authorization: Bearer ${ADO_TOKEN}" -H "Content-Type: application/json" \
181+
-d "${BODY}" "https://dev.azure.com/${ORG}/${PROJ}/_apis/pipelines?api-version=7.1")
182+
echo "$RESP" | jq .
183+
PIPELINE_ID=$(echo "$RESP" | jq -r '.id')
184+
if [ -z "$PIPELINE_ID" ] || [ "$PIPELINE_ID" = "null" ]; then echo "Create failed"; exit 1; fi
185+
echo "PIPELINE_ID=$PIPELINE_ID" >> $GITHUB_ENV
186+
187+
- name: Run pipeline for exact PR commit
188+
id: run
189+
env:
190+
ADO_TOKEN: ${{ env.ADO_TOKEN }}
191+
run: |
192+
ORG="${AZDO_ORG:-${{ env.AZDO_ORG }}}"
193+
PROJ="${AZDO_PROJECT:-${{ env.AZDO_PROJECT }}}"
194+
PIPELINE_ID="${PIPELINE_ID}"
195+
BODY=$(jq -n --arg ref "refs/heads/${PR_BRANCH}" --arg ver "${PR_SHA}" \
196+
'{resources:{repositories:{self:{refName:$ref, version:$ver}}}}')
197+
RUN=$(curl -sS -X POST -H "Authorization: Bearer ${ADO_TOKEN}" -H "Content-Type: application/json" \
198+
-d "${BODY}" "https://dev.azure.com/${ORG}/${PROJ}/_apis/pipelines/${PIPELINE_ID}/runs?api-version=7.1")
199+
echo "$RUN" | jq .
200+
RUN_ID=$(echo "$RUN" | jq -r '.id')
201+
if [ -z "$RUN_ID" ] || [ "$RUN_ID" = "null" ]; then echo "Queue failed"; exit 1; fi
202+
echo "RUN_ID=$RUN_ID" >> $GITHUB_ENV
203+
204+
- name: Wait for completion
205+
env:
206+
ADO_TOKEN: ${{ env.ADO_TOKEN }}
207+
run: |
208+
ORG="${AZDO_ORG:-${{ env.AZDO_ORG }}}"
209+
PROJ="${AZDO_PROJECT:-${{ env.AZDO_PROJECT }}}"
210+
echo "Polling run ${RUN_ID}..."
211+
while true; do
212+
R=$(curl -sS -H "Authorization: Bearer ${ADO_TOKEN}" \
213+
"https://dev.azure.com/${ORG}/${PROJ}/_apis/pipelines/${PIPELINE_ID}/runs/${RUN_ID}?api-version=7.1")
214+
STATE=$(echo "$R" | jq -r '.state')
215+
RESULT=$(echo "$R" | jq -r '.result')
216+
echo "state=$STATE result=$RESULT"
217+
if [ "$STATE" = "completed" ]; then
218+
[ "$RESULT" = "succeeded" ] && exit 0 || exit 1
219+
fi
220+
sleep 10
221+
done
222+
223+
- name: Delete ephemeral pipeline (cleanup)
224+
if: ${{ !cancelled() }}
225+
env:
226+
ADO_TOKEN: ${{ env.ADO_TOKEN }}
227+
run: |
228+
ORG="${AZDO_ORG:-${{ env.AZDO_ORG }}}"
229+
PROJ="${AZDO_PROJECT:-${{ env.AZDO_PROJECT }}}"
230+
# Resuelve build definition por nombre y bórrala
231+
DEF=$(curl -sS -H "Authorization: Bearer ${ADO_TOKEN}" \
232+
"https://dev.azure.com/${ORG}/${PROJ}/_apis/build/definitions?name=${PIPELINE_NAME}&api-version=7.1")
233+
DEF_ID=$(echo "$DEF" | jq -r '.value[0].id')
234+
if [ -n "$DEF_ID" ] && [ "$DEF_ID" != "null" ]; then
235+
curl -sS -X DELETE -H "Authorization: Bearer ${ADO_TOKEN}" \
236+
"https://dev.azure.com/${ORG}/${PROJ}/_apis/build/definitions/${DEF_ID}?api-version=7.1" \
237+
-o /dev/null -w "Deleted definition ${DEF_ID} (HTTP %{http_code})\n"
238+
else
239+
echo "No build definition found for ${PIPELINE_NAME}; nothing to delete."
240+
fi

0 commit comments

Comments
 (0)