Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
ac2d118
Init PR checks
Mar 18, 2026
fc68715
PR check calls CT api
Mar 24, 2026
13bd561
Fixed minor format err
Apr 9, 2026
54deac1
fix: Removed group vars
Apr 10, 2026
77722f2
Set default container to azl3
Apr 10, 2026
884357e
Use azl agent pool
Apr 10, 2026
ebf57c3
Trying a Linux container instead of custom agent pool.
PawelWMS Apr 10, 2026
ab05a66
Removing 'addSpnToEnvironment: true' to hide sensitive data.
PawelWMS Apr 10, 2026
9b5125c
Passing 'API_TOKEN' through 'env'.
PawelWMS Apr 10, 2026
65ab31f
Security and refactoring tweaks.
PawelWMS Apr 10, 2026
59949c4
Trying to fix variable access.
PawelWMS Apr 10, 2026
7cb83df
Trying to enable network in OB.
PawelWMS Apr 10, 2026
bcac4d7
Adding 'azldev'.
PawelWMS Apr 10, 2026
4524da0
Using internal Go proxy.
PawelWMS Apr 11, 2026
7e35406
Fix command.
PawelWMS Apr 11, 2026
8e02390
Move failing stuff to the top.
PawelWMS Apr 11, 2026
3451bb6
Add SC check.
PawelWMS Apr 11, 2026
a51e774
Disabling rendering.
PawelWMS Apr 11, 2026
b45a6b8
Moving variables group around.
PawelWMS Apr 11, 2026
a1acfb5
Revert "Moving variables group around."
PawelWMS Apr 11, 2026
f6e2aaa
Hard-coding the SC.
PawelWMS Apr 11, 2026
e79f6e3
Removing unused argument.
PawelWMS Apr 13, 2026
4a8ae72
Added scaffolding for AI.
PawelWMS Apr 13, 2026
decc6c6
Clean-up + adding dummy delta components listing
PawelWMS Apr 13, 2026
c9c9495
Clean-up
PawelWMS Apr 13, 2026
d3fbbc4
Switching to the test branch.
PawelWMS Apr 13, 2026
4875caf
Fixing "trim"
PawelWMS Apr 13, 2026
48655d3
Adding build reason to CT call.
PawelWMS Apr 13, 2026
48e2b65
Making template NonOfficial for debugging.
PawelWMS Apr 13, 2026
b5abce9
Revert "Making template NonOfficial for debugging."
PawelWMS Apr 13, 2026
2a8d0d8
Always printing the service response.
PawelWMS Apr 13, 2026
eccbca2
Refactoring
PawelWMS Apr 13, 2026
0384f1f
Fixing the SC name.
PawelWMS Apr 13, 2026
b5bc996
Empty commit.
PawelWMS Apr 13, 2026
c3e6348
Moving the pipeline YAML.
PawelWMS Apr 14, 2026
933ce3d
Testing 'mock'.
PawelWMS Apr 14, 2026
f71e678
Refactoring.
PawelWMS Apr 15, 2026
298122b
Moving the pipeline YAML.
PawelWMS Apr 15, 2026
289c16b
Testing 'mock'.
PawelWMS Apr 15, 2026
36c30ff
Listing changed components.
PawelWMS Apr 15, 2026
ea27929
Testing 'mock'.
PawelWMS Apr 15, 2026
8eef5b7
Testing 'mock'.
PawelWMS Apr 15, 2026
eec5648
Full run
PawelWMS Apr 15, 2026
5f098f1
Fixing mock
PawelWMS Apr 15, 2026
53dcc26
Fixing mock
PawelWMS Apr 15, 2026
09f6aec
Trying to run on host.
PawelWMS Apr 15, 2026
d21fe10
Fixing mock
PawelWMS Apr 15, 2026
405c251
Fixing git config
PawelWMS Apr 15, 2026
73d3f0f
Fixing git config
PawelWMS Apr 15, 2026
fe1a2ec
Making component render quiet.
PawelWMS Apr 15, 2026
8485fc3
Forcing render overwrite.
PawelWMS Apr 15, 2026
3231fcf
Debugging with simple input
PawelWMS Apr 15, 2026
ccd745b
Dummy 'atlas' change - REVERT ME
PawelWMS Apr 15, 2026
e834162
Add logging.
PawelWMS Apr 15, 2026
39713b8
Switching to using a Python script for change detection.
PawelWMS Apr 16, 2026
cdd9929
Add logging.
PawelWMS Apr 16, 2026
ebde7f7
Add logging.
PawelWMS Apr 16, 2026
d5c6c69
Failing on updated specs.
PawelWMS Apr 16, 2026
f4ac9a6
Adding extra logging.
PawelWMS Apr 16, 2026
9f2b512
Revert "Dummy 'atlas' change - REVERT ME"
PawelWMS Apr 16, 2026
7c308d9
Going back to checking all components.
PawelWMS Apr 16, 2026
0ef9e56
Fix comments.
PawelWMS Apr 16, 2026
0c2bb12
Extend VS Code settings.
PawelWMS Apr 16, 2026
dd68939
Refactoring, clean-up.
PawelWMS Apr 16, 2026
81ab293
Moving CT call to a Python script.
PawelWMS Apr 17, 2026
4db3223
Checking with upstream pip
PawelWMS Apr 17, 2026
9d4d2ec
Re-naming the script
PawelWMS Apr 17, 2026
ef0b05d
Adding job status polling.
PawelWMS Apr 17, 2026
3bb83f6
Restoring 'PipAuthenticate'.
PawelWMS Apr 17, 2026
4e513e4
Restoring 'PipAuthenticate'.
PawelWMS Apr 17, 2026
3bd3d41
Debugging with simple input
PawelWMS Apr 18, 2026
af97a2e
Revert "Debugging with simple input"
PawelWMS Apr 18, 2026
c7774b0
Merge branch 'tomls/base/main' into asalinas/tomls/pr-check
PawelWMS Apr 20, 2026
f79a0f4
Initial ADO YAML instructions.
PawelWMS Apr 21, 2026
3b0efd6
Refactoring the ADO template into raw + wrapper.
PawelWMS Apr 21, 2026
cc7c643
Debugging with dummy components
PawelWMS Apr 21, 2026
f30d577
Disabling spec render check.
PawelWMS Apr 21, 2026
3571917
Supporting source branch or commit.
PawelWMS Apr 21, 2026
37cc40e
Disabling target commit.
PawelWMS Apr 21, 2026
45c4671
Adjusting pipeline config.
PawelWMS Apr 22, 2026
7bb4788
Add VS Code configs for ADO pipelines.
PawelWMS Apr 22, 2026
453f787
Add --clean-stale + document TODOs.
PawelWMS Apr 22, 2026
a90c807
Address some feedback.
PawelWMS Apr 22, 2026
e08780b
Address more Copilot feedback.
PawelWMS Apr 22, 2026
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
302 changes: 302 additions & 0 deletions .github/instructions/ado-pipeline.instructions.md

Large diffs are not rendered by default.

72 changes: 72 additions & 0 deletions .github/workflows/ado/sources-upload.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Microsoft Corporation
#
# Wrapper pipeline — passed to ADO as the entry point. This file owns all
# OneBranch-specific wiring (governed templates repo, Official vs NonOfficial
# variant, featureFlags) and delegates the actual stages/jobs/steps to the
# raw stages template at:
# .github/workflows/ado/templates/sources-upload-stages.yml
#
# Authenticates via Workload Identity Federation (OIDC) and calls the Control
# Tower prcheck API with PR context.
#
# Prerequisites (ADO / Azure Portal):
# 1. Entra ID App Registration with audience URI
# "api://<ControlTower-ClientId>" (see variable group below).
# 2. Federated identity credential on the app registration for the ADO
# service connection (issuer: https://vstoken.dev.azure.com/<org-id>,
# subject: sc://<org>/<project>/<service-connection-name>).
# 3. ARM service connection in ADO project settings using Workload Identity
# Federation (manual).
# 4. ADO branch policy or pipeline PR trigger configured to fire on PRs.
#
# Variable Group (ADO Pipelines > Library):
# Name: "ControlTower-PRCheck"
# Required variables:
# - ApiAudience : Entra ID audience URI for the Control Tower app
# - ApiBaseUrl : Base URL of the Control Tower service
# - AzldevCommit : Commit hash for azldev (go install ...@<commit>)

# Trigger controlled by ADO branch policy — not YAML triggers.
trigger: none

pr: none

resources:
repositories:
- repository: templates
type: git
name: OneBranch.Pipelines/GovernedTemplates
ref: refs/heads/main

extends:
template: v2/OneBranch.Official.CrossPlat.yml@templates
parameters:
featureFlags:
golang:
internalModuleProxy:
enabled: true
LinuxHostVersion:
Network: R1
runOnHost: true
EnableCDPxPAT: false

# https://aka.ms/obpipelines/sdl
globalSdl:
disableLegacyManifest: true
sbom:
enabled: false
tsa:
enabled: false

stages:
- template: /.github/workflows/ado/templates/sources-upload-stages.yml@self
parameters:
outputDirectory: $(Build.ArtifactStagingDirectory)/output
artifactBaseName: prcheck
containerImage: mcr.microsoft.com/onebranch/azurelinux/build:3.0
poolType: linux
serviceConnection: CT-Endpoints-Access-ServiceConnection-DEV
Comment thread
PawelWMS marked this conversation as resolved.
variableGroup: ControlTower-PRCheck
# Must exceed the script's --poll-timeout-seconds (default 7200s = 120m)
# with enough headroom for setup steps and the final API call.
timeoutInMinutes: 150
194 changes: 194 additions & 0 deletions .github/workflows/ado/templates/sources-upload-stages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Microsoft Corporation
#
# Raw stages template for the sources-upload PR check pipeline.
#
# This template is OneBranch-agnostic: it declares the stages/jobs/steps that
# do the actual work and exposes the OneBranch-coupled knobs as parameters.
# The wrapper at .github/workflows/ado/sources-upload.yml is responsible for
# choosing the OneBranch governed template variant (Official vs NonOfficial),
# configuring its featureFlags, and supplying concrete values for the
# parameters declared below.

parameters:
- name: outputDirectory
type: string
- name: artifactBaseName
type: string
- name: containerImage
type: string
- name: poolType
type: string
default: linux
- name: serviceConnection
type: string
- name: variableGroup
type: string
- name: timeoutInMinutes
type: number

stages:
- stage: PRCheck
jobs:
- job: CallControlTowerAPI
# Must exceed the script's --poll-timeout-seconds (default 7200s = 120m)
# with enough headroom for setup steps and the final API call.
timeoutInMinutes: ${{ parameters.timeoutInMinutes }}
pool:
type: ${{ parameters.poolType }}
variables:
- group: ${{ parameters.variableGroup }}
- name: ob_outputDirectory
value: ${{ parameters.outputDirectory }}
- name: ob_artifactBaseName
value: ${{ parameters.artifactBaseName }}
- name: LinuxContainerImage
value: ${{ parameters.containerImage }}
steps:
- task: PipAuthenticate@1
displayName: "Authenticate pip"
inputs:
artifactFeeds: "azl/ControlTowerFeed"

- script: |
set -euo pipefail

echo "##[group]Mock"
tdnf install -y mock mock-rpmautospec python3-chardet
sudo usermod -aG mock "$(whoami)"
Comment thread
PawelWMS marked this conversation as resolved.
echo "##[endgroup]"

echo "##[group]Azldev"
echo "Installing azldev@${AZLDEV_COMMIT}..."
go install "github.com/microsoft/azure-linux-dev-tools/cmd/azldev@${AZLDEV_COMMIT}"

go_bin_path="$(go env GOPATH)/bin"
echo "##vso[task.prependpath]$go_bin_path"

"$go_bin_path/azldev" --version
echo "##[endgroup]"

echo "##[group]Python dependencies"
pip install -r .github/workflows/scripts/control-tower-prcheck/requirements.txt
echo "##[endgroup]"
displayName: "Install dependencies"
env:
AZLDEV_COMMIT: $(AzldevCommit)

- script: |
set -euo pipefail

# Workaround for an ADO git config error during spec rendering.
# The config key may not be present on every agent image, so tolerate its absence.
git config --unset extensions.worktreeConfig || true

# Full history is needed for spec rendering to work.
if [ "$(git rev-parse --is-shallow-repository)" = "true" ]; then
git fetch --unshallow
fi

# TODO: Replace with using the TOML config to read the specs dir once available.
# The '-o "$specs_dir"' should be removed as part of the update. Future command:
# specs_dir="$(azldev config dump -q -f json | jq -r .project.renderedSpecsDir)"
# ADO task: 19149
specs_dir="specs"

echo "##[group]Specs rendering"
azldev component render -q -a -o "$specs_dir" --force --clean-stale
echo "##[endgroup]"

# Check for any new or modified files under the specs directory.
if ! python3 .github/workflows/scripts/check_rendered_specs.py --specs-dir "$specs_dir"; then
echo "##[group]Git diff"
git --no-pager diff -- "$specs_dir"
echo "##[endgroup]"
echo "##[warning]Specs are not up to date. Ignoring until main branch is updated and stable."
# TODO: Re-enabled failing once specs in the main branch are updated and stable.
# ADO task: 19150
# exit 1
fi
displayName: "Verify rendered specs are up to date"

- script: |
set -euo pipefail

# For both triggers, Build.SourceVersion is the relevant source commit:
# - PR trigger: ADO sets it to the GitHub-created merge commit (refs/pull/{n}/merge).
# - CI/merge-queue trigger: it is the commit that landed on the base branch.
source_hash="$SOURCE_COMMIT"

if [[ "$BUILD_REASON" == "PullRequest" ]]; then
# PR trigger: ADO provides the target branch directly.
target_hash=$(git ls-remote "$UPSTREAM_REPO_URL" "$PR_TARGET_BRANCH" | cut -f1)
else
# CI/merge-queue trigger: extract the base branch from the merge-queue branch name.
# Branch format: refs/heads/gh-readonly-queue/{base_branch}/pr-{pr_number}-{head_sha}
# Using 'test/' branches until ready with the merge queue, but the parsing logic is the same.
if ! base_branch=$(grep -oP '(?<=test/gh-readonly-queue/).+(?=/pr-[^/]+$)' <<< "$SOURCE_BRANCH"); then
echo "##[error]Unsupported SOURCE_BRANCH '$SOURCE_BRANCH' for non-PullRequest build. Expected 'refs/heads/gh-readonly-queue/<base>/pr-<n>-<sha>'."
exit 1
fi
target_hash=$(git ls-remote "$UPSTREAM_REPO_URL" "refs/heads/$base_branch" | cut -f1)
fi

echo "Source commit: $source_hash"
echo "Target commit: $target_hash"

echo "##vso[task.setvariable variable=sourceCommit]$source_hash"
echo "##vso[task.setvariable variable=targetCommit]$target_hash"
env:
BUILD_REASON: $(Build.Reason)
PR_TARGET_BRANCH: $(System.PullRequest.TargetBranch)
SOURCE_BRANCH: $(Build.SourceBranch)
SOURCE_COMMIT: $(Build.SourceVersion)
UPSTREAM_REPO_URL: $(Build.Repository.Uri)
displayName: "Determine source and target commit hashes"

- script: |
set -euo pipefail

cat << EOF
NOTE: It's possible more components changed between the source and target commits than displayed below.
This workflow only checks for updates in the 'sources' files and ignores all other changes.
EOF

components=()
while IFS= read -r line; do
components+=("$(basename "$(dirname "$line")")")
done < <(git diff "$SOURCE_COMMIT" "$TARGET_COMMIT" --name-only | grep '/sources$' | sort -u)
Comment thread
dmcilvaney marked this conversation as resolved.

components="$(IFS=, ; echo "${components[*]}")"
echo "##[warning] Debugging with dummy components 'atlas,words'"
components="atlas,words"
echo "Affected components: $components"
echo "##vso[task.setvariable variable=components]$components"
env:
SOURCE_COMMIT: $(sourceCommit)
TARGET_COMMIT: $(targetCommit)
displayName: "Determine affected components"

- task: AzureCLI@2
displayName: "Call Control Tower 'prcheck' API"
inputs:
azureSubscription: ${{ parameters.serviceConnection }}
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
set -euo pipefail

python3 .github/workflows/scripts/control-tower-prcheck/run_control_tower_prcheck.py \
--api-audience "$API_AUDIENCE" \
--api-base-url "$API_BASE_URL" \
--build-reason "$BUILD_REASON" \
--components "$COMPONENTS" \
--source-commit "$SOURCE_COMMIT" \
--repo-uri "$UPSTREAM_REPO_URL"
env:
API_AUDIENCE: $(ApiAudience)
API_BASE_URL: $(ApiBaseUrl)
BUILD_REASON: $(Build.Reason)
COMPONENTS: $(components)
SOURCE_COMMIT: $(sourceCommit)
# TODO: Target commit is not used. Will be needed once we move detection of affected components to CT.
# ADO task: 18816
TARGET_COMMIT: $(targetCommit)
UPSTREAM_REPO_URL: $(Build.Repository.Uri)
20 changes: 10 additions & 10 deletions .github/workflows/scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ The easiest way to get quick, interactive feedback is with [GitHub Copilot](http
```bash
cd ~/repos/azurelinux
python -m venv .venv && source .venv/bin/activate
pip install -r .github/workflows/scripts/requirements.txt
pip install -r .github/workflows/scripts/spec-review/requirements.txt
gh copilot
# OR
npm install -g @github/copilot
Expand All @@ -51,19 +51,19 @@ copilot --version # verify CLI
# Defaults: reviews all *.spec in repo, writes to repo root
# spec_review_report.json, copilot_log.md, spec_review_kb.md

./.github/workflows/scripts/spec_review.sh \
./.github/workflows/scripts/spec-review/spec_review.sh \
--spec base/comps/azurelinux-release/azurelinux-release.spec \
--spec base/comps/azurelinux-repos/azurelinux-repos.spec

# Validate / inspect
python .github/workflows/scripts/spec_review_schema.py /tmp/spec_review_report.json --all
python .github/workflows/scripts/spec_review_schema.py /tmp/spec_review_report.json --json | jq
python .github/workflows/scripts/spec-review/spec_review_schema.py /tmp/spec_review_report.json --all
python .github/workflows/scripts/spec-review/spec_review_schema.py /tmp/spec_review_report.json --json | jq
```

The script supports additional options (like selecting a model, or using different URLs); run with `--help` for details.

```bash
./.github/workflows/scripts/spec_review.sh --help
./.github/workflows/scripts/spec-review/spec_review.sh --help
```

## Run multi-model review (spec_review_multi.sh)
Expand All @@ -79,11 +79,11 @@ uses a third model pass to synthesize their findings into a single high-quality

```bash
# Defaults: claude-opus-4.6 + gpt-5.2-codex reviewers, gpt-5.2-codex synthesizer
./.github/workflows/scripts/spec_review_multi.sh \
./.github/workflows/scripts/spec-review/spec_review_multi.sh \
--spec base/comps/azurelinux-release/azurelinux-release.spec

# Custom models
./.github/workflows/scripts/spec_review_multi.sh \
./.github/workflows/scripts/spec-review/spec_review_multi.sh \
--spec foo.spec \
--model1 gpt-5.2-codex \
--model2 claude-opus-4.6 \
Expand All @@ -101,7 +101,7 @@ ls /tmp/spec_review_workdir/
Run with `--help` for all options:

```bash
./.github/workflows/scripts/spec_review_multi.sh --help
./.github/workflows/scripts/spec-review/spec_review_multi.sh --help
```

---
Expand All @@ -119,7 +119,7 @@ copilot --agent spec-review
```bash
# For semi-automated or fully automated runs, use -i or -p flags:
prompt="Review: base/comps/azurelinux-release/azurelinux-release.spec against packaging guidelines.\n"\
"Write JSON to spec_review_report.json and validate with: python .github/workflows/scripts/spec_review_schema.py spec_review_report.json"
"Write JSON to spec_review_report.json and validate with: python .github/workflows/scripts/spec-review/spec_review_schema.py spec_review_report.json"

# Semi-interactive (runs prompt, then waits for the user)
copilot --agent spec-review \
Expand All @@ -144,7 +144,7 @@ copilot --agent spec-review \
-p "$prompt"

# Review output
python .github/workflows/scripts/spec_review_schema.py spec_review_report.json --all
python .github/workflows/scripts/spec-review/spec_review_schema.py spec_review_report.json --all
```

## Future work
Expand Down
Loading
Loading