Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b6ac9524f7 | |||
| 0e96bf5af3 | |||
| 0acbaf7e0b | |||
| 56448711e8 |
@@ -46,7 +46,7 @@ parameters:
|
|||||||
variables:
|
variables:
|
||||||
# Tenant-specific values are expected in a variable group (see templates/variables-tenant.yml).
|
# Tenant-specific values are expected in a variable group (see templates/variables-tenant.yml).
|
||||||
# Uncomment the line below after creating the group in your Azure DevOps project.
|
# Uncomment the line below after creating the group in your Azure DevOps project.
|
||||||
# - group: vg-astral-tenant
|
- group: vg-astral-cqre
|
||||||
- template: templates/variables-common.yml
|
- template: templates/variables-common.yml
|
||||||
- name: BACKUP_FOLDER
|
- name: BACKUP_FOLDER
|
||||||
value: tenant-state
|
value: tenant-state
|
||||||
@@ -64,6 +64,26 @@ jobs:
|
|||||||
- checkout: self
|
- checkout: self
|
||||||
persistCredentials: true
|
persistCredentials: true
|
||||||
|
|
||||||
|
# Uncomment the block below for agent-side debugging.
|
||||||
|
# - task: Bash@3
|
||||||
|
# displayName: DEBUG — dump agent state (restore)
|
||||||
|
# inputs:
|
||||||
|
# targetType: inline
|
||||||
|
# script: |
|
||||||
|
# set -euo pipefail
|
||||||
|
# echo "=== Variables ==="
|
||||||
|
# echo "BACKUP_FOLDER=$(BACKUP_FOLDER)"
|
||||||
|
# echo "INTUNE_BACKUP_SUBDIR=$(INTUNE_BACKUP_SUBDIR)"
|
||||||
|
# echo "BASELINE_BRANCH=$(BASELINE_BRANCH)"
|
||||||
|
# echo "=== Git state ==="
|
||||||
|
# git branch -a
|
||||||
|
# git log --oneline -5
|
||||||
|
# git status --short
|
||||||
|
# echo "=== File system ==="
|
||||||
|
# ls -la "$(Build.SourcesDirectory)"
|
||||||
|
# find "$(BACKUP_FOLDER)" -maxdepth 2 -type d 2>/dev/null || true
|
||||||
|
# workingDirectory: "$(Build.SourcesDirectory)"
|
||||||
|
|
||||||
- task: Bash@3
|
- task: Bash@3
|
||||||
displayName: Checkout approved baseline snapshot
|
displayName: Checkout approved baseline snapshot
|
||||||
inputs:
|
inputs:
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ schedules:
|
|||||||
variables:
|
variables:
|
||||||
# Tenant-specific values are expected in a variable group (see templates/variables-tenant.yml).
|
# Tenant-specific values are expected in a variable group (see templates/variables-tenant.yml).
|
||||||
# Uncomment the line below after creating the group in your Azure DevOps project.
|
# Uncomment the line below after creating the group in your Azure DevOps project.
|
||||||
# - group: vg-astral-tenant
|
- group: vg-astral-cqre
|
||||||
- template: templates/variables-common.yml
|
- template: templates/variables-common.yml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -26,6 +26,26 @@ jobs:
|
|||||||
- checkout: self
|
- checkout: self
|
||||||
persistCredentials: true
|
persistCredentials: true
|
||||||
|
|
||||||
|
# Uncomment the block below for agent-side debugging.
|
||||||
|
# - task: Bash@3
|
||||||
|
# displayName: DEBUG — dump agent state (Intune review sync)
|
||||||
|
# inputs:
|
||||||
|
# targetType: inline
|
||||||
|
# script: |
|
||||||
|
# set -euo pipefail
|
||||||
|
# echo "=== Variables ==="
|
||||||
|
# echo "BACKUP_FOLDER=$(BACKUP_FOLDER)"
|
||||||
|
# echo "DRIFT_BRANCH_INTUNE=$(DRIFT_BRANCH_INTUNE)"
|
||||||
|
# echo "BASELINE_BRANCH=$(BASELINE_BRANCH)"
|
||||||
|
# echo "=== Git state ==="
|
||||||
|
# git branch -a
|
||||||
|
# git log --oneline -5
|
||||||
|
# git status --short
|
||||||
|
# echo "=== File system ==="
|
||||||
|
# ls -la "$(Build.SourcesDirectory)"
|
||||||
|
# find "$(BACKUP_FOLDER)" -maxdepth 2 -type d 2>/dev/null || true
|
||||||
|
# workingDirectory: "$(Build.SourcesDirectory)"
|
||||||
|
|
||||||
- task: Bash@3
|
- task: Bash@3
|
||||||
displayName: Apply reviewer /reject decisions (Intune)
|
displayName: Apply reviewer /reject decisions (Intune)
|
||||||
condition: eq(variables['ENABLE_PR_REVIEWER_DECISIONS'], 'true')
|
condition: eq(variables['ENABLE_PR_REVIEWER_DECISIONS'], 'true')
|
||||||
@@ -114,6 +134,26 @@ jobs:
|
|||||||
- checkout: self
|
- checkout: self
|
||||||
persistCredentials: true
|
persistCredentials: true
|
||||||
|
|
||||||
|
# Uncomment the block below for agent-side debugging.
|
||||||
|
# - task: Bash@3
|
||||||
|
# displayName: DEBUG — dump agent state (Entra review sync)
|
||||||
|
# inputs:
|
||||||
|
# targetType: inline
|
||||||
|
# script: |
|
||||||
|
# set -euo pipefail
|
||||||
|
# echo "=== Variables ==="
|
||||||
|
# echo "BACKUP_FOLDER=$(BACKUP_FOLDER)"
|
||||||
|
# echo "DRIFT_BRANCH_ENTRA=$(DRIFT_BRANCH_ENTRA)"
|
||||||
|
# echo "BASELINE_BRANCH=$(BASELINE_BRANCH)"
|
||||||
|
# echo "=== Git state ==="
|
||||||
|
# git branch -a
|
||||||
|
# git log --oneline -5
|
||||||
|
# git status --short
|
||||||
|
# echo "=== File system ==="
|
||||||
|
# ls -la "$(Build.SourcesDirectory)"
|
||||||
|
# find "$(BACKUP_FOLDER)" -maxdepth 2 -type d 2>/dev/null || true
|
||||||
|
# workingDirectory: "$(Build.SourcesDirectory)"
|
||||||
|
|
||||||
- task: Bash@3
|
- task: Bash@3
|
||||||
displayName: Apply reviewer /reject decisions (Entra)
|
displayName: Apply reviewer /reject decisions (Entra)
|
||||||
condition: eq(variables['ENABLE_PR_REVIEWER_DECISIONS'], 'true')
|
condition: eq(variables['ENABLE_PR_REVIEWER_DECISIONS'], 'true')
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ schedules:
|
|||||||
variables:
|
variables:
|
||||||
# Tenant-specific values are expected in a variable group (see templates/variables-tenant.yml).
|
# Tenant-specific values are expected in a variable group (see templates/variables-tenant.yml).
|
||||||
# Uncomment the line below after creating the group in your Azure DevOps project.
|
# Uncomment the line below after creating the group in your Azure DevOps project.
|
||||||
# - group: vg-astral-tenant
|
- group: vg-astral-cqre
|
||||||
- template: templates/variables-common.yml
|
- template: templates/variables-common.yml
|
||||||
- name: ROLLING_PR_TITLE_INTUNE
|
- name: ROLLING_PR_TITLE_INTUNE
|
||||||
value: "Intune drift review (rolling)"
|
value: "Intune drift review (rolling)"
|
||||||
@@ -85,6 +85,28 @@ jobs:
|
|||||||
- checkout: self
|
- checkout: self
|
||||||
persistCredentials: true
|
persistCredentials: true
|
||||||
|
|
||||||
|
# Uncomment the block below for agent-side debugging.
|
||||||
|
# - task: Bash@3
|
||||||
|
# displayName: DEBUG — dump agent state (Intune)
|
||||||
|
# inputs:
|
||||||
|
# targetType: inline
|
||||||
|
# script: |
|
||||||
|
# set -euo pipefail
|
||||||
|
# echo "=== Variables ==="
|
||||||
|
# echo "BACKUP_FOLDER=$(BACKUP_FOLDER)"
|
||||||
|
# echo "INTUNE_BACKUP_SUBDIR=$(INTUNE_BACKUP_SUBDIR)"
|
||||||
|
# echo "DRIFT_BRANCH_INTUNE=$(DRIFT_BRANCH_INTUNE)"
|
||||||
|
# echo "BASELINE_BRANCH=$(BASELINE_BRANCH)"
|
||||||
|
# echo "AGENT_POOL_NAME=$(AGENT_POOL_NAME)"
|
||||||
|
# echo "=== Git state ==="
|
||||||
|
# git branch -a
|
||||||
|
# git log --oneline -5
|
||||||
|
# git status --short
|
||||||
|
# echo "=== File system ==="
|
||||||
|
# ls -la "$(Build.SourcesDirectory)"
|
||||||
|
# find "$(BACKUP_FOLDER)" -maxdepth 2 -type d 2>/dev/null || true
|
||||||
|
# workingDirectory: "$(Build.SourcesDirectory)"
|
||||||
|
|
||||||
- task: Bash@3
|
- task: Bash@3
|
||||||
displayName: Snapshot validation helper script (Intune job)
|
displayName: Snapshot validation helper script (Intune job)
|
||||||
inputs:
|
inputs:
|
||||||
@@ -129,7 +151,7 @@ jobs:
|
|||||||
FULL_RUN=1
|
FULL_RUN=1
|
||||||
MODE="full"
|
MODE="full"
|
||||||
REASON="forced by parameter forceFullRun=true"
|
REASON="forced by parameter forceFullRun=true"
|
||||||
elif [ "$PRAGUE_HOUR" = "00" ]; then
|
elif [ "$LOCAL_HOUR" = "$(FULL_RUN_HOUR)" ]; then
|
||||||
FULL_RUN=1
|
FULL_RUN=1
|
||||||
MODE="full"
|
MODE="full"
|
||||||
REASON="scheduled midnight full run"
|
REASON="scheduled midnight full run"
|
||||||
@@ -138,7 +160,7 @@ jobs:
|
|||||||
MODE="light"
|
MODE="light"
|
||||||
REASON="default hourly light run"
|
REASON="default hourly light run"
|
||||||
fi
|
fi
|
||||||
echo "Run mode decision: $MODE ($REASON; Prague local time: $PRAGUE_NOW)"
|
echo "Run mode decision: $MODE ($REASON; local time ($(BACKUP_TIMEZONE)): $LOCAL_NOW)"
|
||||||
echo "##vso[task.setvariable variable=FULL_RUN]$FULL_RUN"
|
echo "##vso[task.setvariable variable=FULL_RUN]$FULL_RUN"
|
||||||
echo "##vso[task.setvariable variable=FULL_RUN;isOutput=true]$FULL_RUN"
|
echo "##vso[task.setvariable variable=FULL_RUN;isOutput=true]$FULL_RUN"
|
||||||
workingDirectory: "$(Build.SourcesDirectory)"
|
workingDirectory: "$(Build.SourcesDirectory)"
|
||||||
@@ -757,13 +779,23 @@ jobs:
|
|||||||
$generatedSplitMarkdownPattern = '^' + [Regex]::Escape("$(BACKUP_FOLDER)") + '/.*\.md$'
|
$generatedSplitMarkdownPattern = '^' + [Regex]::Escape("$(BACKUP_FOLDER)") + '/.*\.md$'
|
||||||
$generatedReportPattern = '^' + [Regex]::Escape("$(BACKUP_FOLDER)/$(REPORTS_SUBDIR)/")
|
$generatedReportPattern = '^' + [Regex]::Escape("$(BACKUP_FOLDER)/$(REPORTS_SUBDIR)/")
|
||||||
$workloadConfigPattern = '^' + [Regex]::Escape("$(BACKUP_FOLDER)/$(INTUNE_BACKUP_SUBDIR)/")
|
$workloadConfigPattern = '^' + [Regex]::Escape("$(BACKUP_FOLDER)/$(INTUNE_BACKUP_SUBDIR)/")
|
||||||
$changedFile = $untrackedFile, $trackedFile | % { $_ } | ? {
|
Write-Host "DEBUG: BACKUP_FOLDER=$(BACKUP_FOLDER), INTUNE_BACKUP_SUBDIR=$(INTUNE_BACKUP_SUBDIR)"
|
||||||
|
Write-Host "DEBUG: workloadConfigPattern = $workloadConfigPattern"
|
||||||
|
Write-Host "DEBUG: untracked count = $($untrackedFile.Count), tracked count = $($trackedFile.Count)"
|
||||||
|
$allFiles = @()
|
||||||
|
if ($untrackedFile) { $allFiles += $untrackedFile }
|
||||||
|
if ($trackedFile) { $allFiles += $trackedFile }
|
||||||
|
$changedFile = $allFiles | ? {
|
||||||
$_ -and
|
$_ -and
|
||||||
$_ -match $workloadConfigPattern -and
|
$_ -match $workloadConfigPattern -and
|
||||||
$_ -notmatch $generatedSplitMarkdownPattern -and
|
$_ -notmatch $generatedSplitMarkdownPattern -and
|
||||||
$_ -notmatch $generatedReportPattern -and
|
$_ -notmatch $generatedReportPattern -and
|
||||||
$_ -notlike "*/Assignment Report/*"
|
$_ -notlike "*/Assignment Report/*"
|
||||||
}
|
}
|
||||||
|
Write-Host "DEBUG: changed count = $($changedFile.Count)"
|
||||||
|
if ($changedFile.Count -gt 0) {
|
||||||
|
$changedFile | Select-Object -First 5 | ForEach-Object { Write-Host "DEBUG: changed file: $_" }
|
||||||
|
}
|
||||||
|
|
||||||
if ($changedFile) {
|
if ($changedFile) {
|
||||||
git show-ref --verify --quiet "refs/remotes/origin/$(DRIFT_BRANCH_INTUNE)"
|
git show-ref --verify --quiet "refs/remotes/origin/$(DRIFT_BRANCH_INTUNE)"
|
||||||
@@ -1023,22 +1055,7 @@ jobs:
|
|||||||
}
|
}
|
||||||
$modificationAuthor = $modificationAuthor | Sort-Object Key -Unique
|
$modificationAuthor = $modificationAuthor | Sort-Object Key -Unique
|
||||||
} else {
|
} else {
|
||||||
$isNonResourceFile = (
|
$nonResourceFileCount++
|
||||||
$file -like "*/reports/*" -or
|
|
||||||
$file -like "*/Assignment Report/*" -or
|
|
||||||
$file -like "*/Managed Google Play/*" -or
|
|
||||||
$file -like "*Device Management Settings/settings.json" -or
|
|
||||||
$file -like "*/Apple Push Notification/*" -or
|
|
||||||
$file -like "*Device Configurations/mobileconfig/*" -or
|
|
||||||
$file -like "*.md" -or
|
|
||||||
$file -like "*.gitkeep"
|
|
||||||
)
|
|
||||||
|
|
||||||
if ($isNonResourceFile) {
|
|
||||||
$nonResourceFileCount++
|
|
||||||
} else {
|
|
||||||
throw "Unable to find resourceId in '$file' file name. Pipeline code modification needed."
|
|
||||||
}
|
|
||||||
$modificationAuthor = $null
|
$modificationAuthor = $null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1337,6 +1354,28 @@ jobs:
|
|||||||
- checkout: self
|
- checkout: self
|
||||||
persistCredentials: true
|
persistCredentials: true
|
||||||
|
|
||||||
|
# Uncomment the block below for agent-side debugging.
|
||||||
|
# - task: Bash@3
|
||||||
|
# displayName: DEBUG — dump agent state (Entra)
|
||||||
|
# inputs:
|
||||||
|
# targetType: inline
|
||||||
|
# script: |
|
||||||
|
# set -euo pipefail
|
||||||
|
# echo "=== Variables ==="
|
||||||
|
# echo "BACKUP_FOLDER=$(BACKUP_FOLDER)"
|
||||||
|
# echo "ENTRA_BACKUP_SUBDIR=$(ENTRA_BACKUP_SUBDIR)"
|
||||||
|
# echo "DRIFT_BRANCH_ENTRA=$(DRIFT_BRANCH_ENTRA)"
|
||||||
|
# echo "BASELINE_BRANCH=$(BASELINE_BRANCH)"
|
||||||
|
# echo "AGENT_POOL_NAME=$(AGENT_POOL_NAME)"
|
||||||
|
# echo "=== Git state ==="
|
||||||
|
# git branch -a
|
||||||
|
# git log --oneline -5
|
||||||
|
# git status --short
|
||||||
|
# echo "=== File system ==="
|
||||||
|
# ls -la "$(Build.SourcesDirectory)"
|
||||||
|
# find "$(BACKUP_FOLDER)" -maxdepth 2 -type d 2>/dev/null || true
|
||||||
|
# workingDirectory: "$(Build.SourcesDirectory)"
|
||||||
|
|
||||||
- task: Bash@3
|
- task: Bash@3
|
||||||
displayName: Snapshot export/validation helper scripts (Entra job)
|
displayName: Snapshot export/validation helper scripts (Entra job)
|
||||||
inputs:
|
inputs:
|
||||||
@@ -1382,7 +1421,7 @@ jobs:
|
|||||||
MODE="full"
|
MODE="full"
|
||||||
FULL_RUN=1
|
FULL_RUN=1
|
||||||
MODE_REASON="forced by parameter forceFullRun=true"
|
MODE_REASON="forced by parameter forceFullRun=true"
|
||||||
elif [ "$PRAGUE_HOUR" = "00" ]; then
|
elif [ "$LOCAL_HOUR" = "$(FULL_RUN_HOUR)" ]; then
|
||||||
MODE="full"
|
MODE="full"
|
||||||
FULL_RUN=1
|
FULL_RUN=1
|
||||||
MODE_REASON="scheduled midnight full run"
|
MODE_REASON="scheduled midnight full run"
|
||||||
@@ -1414,7 +1453,7 @@ jobs:
|
|||||||
APP_REG_SCOPE_REASON="disabled (pipeline variable)"
|
APP_REG_SCOPE_REASON="disabled (pipeline variable)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Run mode decision (Entra): $MODE ($MODE_REASON; Prague local time: $PRAGUE_NOW)"
|
echo "Run mode decision (Entra): $MODE ($MODE_REASON; local time ($(BACKUP_TIMEZONE)): $LOCAL_NOW)"
|
||||||
echo "Enterprise Applications export scope: $ENTERPRISE_SCOPE_REASON"
|
echo "Enterprise Applications export scope: $ENTERPRISE_SCOPE_REASON"
|
||||||
echo "App Registrations export scope: $APP_REG_SCOPE_REASON"
|
echo "App Registrations export scope: $APP_REG_SCOPE_REASON"
|
||||||
echo "##vso[task.setvariable variable=ENTRA_RUN_MODE]$MODE"
|
echo "##vso[task.setvariable variable=ENTRA_RUN_MODE]$MODE"
|
||||||
|
|||||||
@@ -205,7 +205,14 @@ def main() -> int:
|
|||||||
pr = prs[0]
|
pr = prs[0]
|
||||||
pr_id = int(pr.get("pullRequestId"))
|
pr_id = int(pr.get("pullRequestId"))
|
||||||
|
|
||||||
_run_git(args.repo_root, ["fetch", "--quiet", "origin", baseline_branch, drift_branch])
|
_run_git(args.repo_root, ["fetch", "--quiet", "origin", baseline_branch])
|
||||||
|
try:
|
||||||
|
_run_git(args.repo_root, ["fetch", "--quiet", "origin", drift_branch])
|
||||||
|
except RuntimeError as exc:
|
||||||
|
if "couldn't find remote ref" in str(exc).lower() or "could not find remote ref" in str(exc).lower():
|
||||||
|
print(f"Drift branch '{drift_branch}' not found on origin; nothing to reject.")
|
||||||
|
return 0
|
||||||
|
raise
|
||||||
diff_paths = _run_diff_name_only(args.repo_root, baseline_branch, drift_branch)
|
diff_paths = _run_diff_name_only(args.repo_root, baseline_branch, drift_branch)
|
||||||
changed_paths = {
|
changed_paths = {
|
||||||
p.strip()
|
p.strip()
|
||||||
|
|||||||
@@ -512,7 +512,14 @@ def main() -> int:
|
|||||||
print("##vso[task.setvariable variable=DRIFT_PR_SUPPRESSED;isOutput=true]0")
|
print("##vso[task.setvariable variable=DRIFT_PR_SUPPRESSED;isOutput=true]0")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
_run_git(args.repo_root, ["fetch", "--quiet", "origin", baseline_branch, drift_branch])
|
_run_git(args.repo_root, ["fetch", "--quiet", "origin", baseline_branch])
|
||||||
|
try:
|
||||||
|
_run_git(args.repo_root, ["fetch", "--quiet", "origin", drift_branch])
|
||||||
|
except RuntimeError as exc:
|
||||||
|
if "couldn't find remote ref" in str(exc).lower() or "could not find remote ref" in str(exc).lower():
|
||||||
|
pass # Drift branch may not exist yet; fallback to HEAD below.
|
||||||
|
else:
|
||||||
|
raise
|
||||||
baseline_commitish = f"origin/{baseline_branch}" if _ref_has_commit(args.repo_root, f"origin/{baseline_branch}") else baseline_branch
|
baseline_commitish = f"origin/{baseline_branch}" if _ref_has_commit(args.repo_root, f"origin/{baseline_branch}") else baseline_branch
|
||||||
drift_commitish = f"origin/{drift_branch}" if _ref_has_commit(args.repo_root, f"origin/{drift_branch}") else "HEAD"
|
drift_commitish = f"origin/{drift_branch}" if _ref_has_commit(args.repo_root, f"origin/{drift_branch}") else "HEAD"
|
||||||
if not _workload_config_diff_exists(
|
if not _workload_config_diff_exists(
|
||||||
|
|||||||
@@ -2498,7 +2498,14 @@ def main() -> int:
|
|||||||
return 0
|
return 0
|
||||||
_debug(f"Active rolling PR detected: pr_id={pr_id}, source={source_ref}, target={target_ref}")
|
_debug(f"Active rolling PR detected: pr_id={pr_id}, source={source_ref}, target={target_ref}")
|
||||||
|
|
||||||
_run_git(args.repo_root, ["fetch", "--quiet", "origin", baseline_branch, drift_branch])
|
_run_git(args.repo_root, ["fetch", "--quiet", "origin", baseline_branch])
|
||||||
|
try:
|
||||||
|
_run_git(args.repo_root, ["fetch", "--quiet", "origin", drift_branch])
|
||||||
|
except RuntimeError as exc:
|
||||||
|
if "couldn't find remote ref" in str(exc).lower() or "could not find remote ref" in str(exc).lower():
|
||||||
|
print(f"Drift branch '{drift_branch}' not found on origin; skipping summary update.")
|
||||||
|
return 0
|
||||||
|
raise
|
||||||
diff_output = _run_diff_name_status(args.repo_root, baseline_branch, drift_branch)
|
diff_output = _run_diff_name_status(args.repo_root, baseline_branch, drift_branch)
|
||||||
changes = _parse_changes(diff_output, args.backup_folder, args.reports_subdir)
|
changes = _parse_changes(diff_output, args.backup_folder, args.reports_subdir)
|
||||||
_debug(f"Parsed non-doc/report changes for summary: count={len(changes)}")
|
_debug(f"Parsed non-doc/report changes for summary: count={len(changes)}")
|
||||||
|
|||||||
Reference in New Issue
Block a user