diff --git a/Dockerfile b/Dockerfile index 0933a35e..422676df 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,13 +9,15 @@ ARG azure_resources=2.3.0 RUN [ "/bin/bash", "-c", "apt-get update &> /dev/null && apt-get install -y git wget &> /dev/null" ] RUN [ "/bin/bash", "-c", "wget https://github.com/cli/cli/releases/download/v${github}/gh_${github}_linux_amd64.deb -O /tmp/gh_${github}_linux_amd64.deb &> /dev/null" ] +RUN [ "/bin/bash", "-c", "curl -sL https://aka.ms/InstallAzureCLIDeb | bash &> /dev/null"] +RUN [ "/bin/bash", "-c", "az extension add --name azure-devops --system &> /dev/null"] RUN [ "/bin/bash", "-c", "dpkg -i /tmp/gh_${github}_linux_amd64.deb &> /dev/null" ] RUN [ "/usr/bin/pwsh", "-Command", "$ProgressPreference = 'SilentlyContinue'; Install-Module -Name Az.Accounts -RequiredVersion ${azure_accounts} -Scope AllUsers -Force" ] RUN [ "/usr/bin/pwsh", "-Command", "$ProgressPreference = 'SilentlyContinue'; Install-Module -Name Az.Resources -RequiredVersion ${azure_resources} -Scope AllUsers -Force" ] -COPY . /action +COPY . /var/lib/app -ENV AzOpsMainTemplate='/action/template/template.json' -ENV AzOpsStateConfig='/action/src/AzOpsStateConfig.json' +ENV AzOpsMainTemplate='/var/lib/app/template/template.json' +ENV AzOpsStateConfig='/var/lib/app/src/AzOpsStateConfig.json' -ENTRYPOINT ["pwsh", "/action/entrypoint.ps1"] +ENTRYPOINT ["pwsh", "/var/lib/app/entrypoint.ps1"] diff --git a/entrypoint.ps1 b/entrypoint.ps1 index 41d9a390..68688967 100644 --- a/entrypoint.ps1 +++ b/entrypoint.ps1 @@ -32,19 +32,54 @@ function Initialization { Connect-AzAccount -TenantId $credentials.tenantId -ServicePrincipal -Credential $credential -SubscriptionId $credentials.subscriptionId -WarningAction SilentlyContinue | Out-Null # Configure git - Start-AzOpsNativeExecution { - git config --global user.email $env:GITHUB_EMAIL - git config --global user.name $env:GITHUB_USERNAME - } | Out-Host + switch ($env:SCM_PLATFORM) { + "AzureDevOps" { + Start-AzOpsNativeExecution { + git config --global user.name $env:AZDEVOPS_USERNAME + git config --global user.email $env:AZDEVOPS_EMAIL + } | Out-Host + } + default { + Start-AzOpsNativeExecution { + git config --global user.name $env:GITHUB_USERNAME + git config --global user.email $env:GITHUB_EMAIL + } | Out-Host + } + } + + # Update branch names + if (($env:SCM_PLATFORM -eq "AzureDevOps") -and ($env:INPUT_MODE -eq "Push")) { + $env:AZDEVOPS_HEAD_REF = ($env:AZDEVOPS_HEAD_REF).Replace("refs/heads/", "") + $env:AZDEVOPS_BASE_REF = ($env:AZDEVOPS_BASE_REF).Replace("refs/heads/", "") + } # Print environment variables - Write-AzOpsLog -Level Information -Topic "entrypoint" -Message "AZOPS_STATE is $($env:AZOPS_STATE)" - Write-AzOpsLog -Level Information -Topic "entrypoint" -Message "AZOPS_ENROLLMENT_ACCOUNT is $($env:AZOPS_ENROLLMENT_ACCOUNT)" - Write-AzOpsLog -Level Information -Topic "entrypoint" -Message "AZOPS_OFFER_TYPE is $($env:AZOPS_OFFER_TYPE)" - Write-AzOpsLog -Level Information -Topic "entrypoint" -Message "AZOPS_DEFAULT_DEPLOYMENT_REGION is $($env:AZOPS_DEFAULT_DEPLOYMENT_REGION)" - Write-AzOpsLog -Level Information -Topic "entrypoint" -Message "AZOPS_INVALIDATE_CACHE is $($env:AZOPS_INVALIDATE_CACHE)" - Write-AzOpsLog -Level Information -Topic "entrypoint" -Message "AZOPS_IGNORE_CONTEXT_CHECK is $($env:AZOPS_IGNORE_CONTEXT_CHECK)" - Write-AzOpsLog -Level Information -Topic "entrypoint" -Message "AZOPS_THROTTLE_LIMIT is $($env:AZOPS_THROTTLE_LIMIT)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "AZOPS_MODE: $($env:INPUT_MODE)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "AZOPS_STATE: $($env:AZOPS_STATE)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "AZOPS_ENROLLMENT_ACCOUNT: $($env:AZOPS_ENROLLMENT_ACCOUNT)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "AZOPS_OFFER_TYPE: $($env:AZOPS_OFFER_TYPE)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "AZOPS_DEFAULT_DEPLOYMENT_REGION: $($env:AZOPS_DEFAULT_DEPLOYMENT_REGION)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "AZOPS_INVALIDATE_CACHE: $($env:AZOPS_INVALIDATE_CACHE)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "AZOPS_IGNORE_CONTEXT_CHECK: $($env:AZOPS_IGNORE_CONTEXT_CHECK)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "AZOPS_THROTTLE_LIMIT: $($env:AZOPS_THROTTLE_LIMIT)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "AZOPS_STRICT_MODE: $($env:AZOPS_STRICT_MODE)" + switch ($env:SCM_PLATFORM) { + "AzureDevOps" { + Write-AzOpsLog -Level Information -Topic "env-var" -Message "AZDEVOPS_AUTO_MERGE: $($env:AZDEVOPS_AUTO_MERGE)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "AZDEVOPS_EMAIL: $($env:AZDEVOPS_EMAIL)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "AZDEVOPS_USERNAME: $($env:AZDEVOPS_USERNAME)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "AZDEVOPS_PULL_REQUEST: $($env:AZDEVOPS_PULL_REQUEST)" + } + default { + Write-AzOpsLog -Level Information -Topic "env-var" -Message "GITHUB_AUTO_MERGE: $($env:GITHUB_AUTO_MERGE)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "GITHUB_EMAIL: $($env:GITHUB_EMAIL)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "GITHUB_USERNAME: $($env:GITHUB_USERNAME)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "GITHUB_PULL_REQUEST: $($env:GITHUB_PULL_REQUEST)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "GITHUB_HEAD_REF: $($env:GITHUB_HEAD_REF)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "GITHUB_BASE_REF: $($env:GITHUB_BASE_REF)" + Write-AzOpsLog -Level Information -Topic "env-var" -Message "GITHUB_COMMENTS: $($env:GITHUB_COMMENTS)" + } + } # Initialize global variables Initialize-AzOpsGlobalVariables diff --git a/src/auxiliary/guidance/strict/azdevops/README.md b/src/auxiliary/guidance/strict/azdevops/README.md new file mode 100644 index 00000000..0221e478 --- /dev/null +++ b/src/auxiliary/guidance/strict/azdevops/README.md @@ -0,0 +1,18 @@ +## AzOps + +The 'main' branch in the repository does not contain the latest configuration of Azure. + +It is strongly recommended to ensure that 'feature' and 'main' branches contain the current Azure configuration. + +### Remediation + +[Re-initialize](https://github.com/Azure/Enterprise-Scale/blob/main/docs/Deploy/setup-azuredevops.md#discover-environment) your repository to pull latest changes from Azure by invoking the Azure Pipeline. You can monitor the status of the Pipeline in `Pipelines` section. + +Upon successful completion, the action will create a new `system` branch and a new `Azure Change Notification` pull request containing the latest configuration. + +- Please merge Pull Request from `system` branch in to your `main` branch. + +- Update you feature branch from main `git pull origin/main` + +- Push your branch to `origin` by running following command `git push` + diff --git a/src/auxiliary/guidance/strict/README.md b/src/auxiliary/guidance/strict/github/README.md similarity index 87% rename from src/auxiliary/guidance/strict/README.md rename to src/auxiliary/guidance/strict/github/README.md index 7de2ebdf..0c79e7fb 100644 --- a/src/auxiliary/guidance/strict/README.md +++ b/src/auxiliary/guidance/strict/github/README.md @@ -6,7 +6,7 @@ It is strongly recommended to ensure that 'feature' and 'main' branches contain ### Remediation -[Re-initialization](https://github.com/Azure/Enterprise-Scale/blob/main/docs/Deploy/discover-environment.md#initialize-existing-environment) of the repository to pull the latest changes from Azure by manually invoking the GitHub Action. +[Re-initialize](https://github.com/Azure/Enterprise-Scale/blob/main/docs/Deploy/discover-environment.md#initialize-existing-environment) of the repository to pull the latest changes from Azure by manually invoking the GitHub Action. Upon successful completion, the action will create a new `system` branch and a new `Azure Change Notification` pull request containing the latest configuration. diff --git a/src/providerfeatures.json b/src/auxiliary/providerfeatures.json similarity index 100% rename from src/providerfeatures.json rename to src/auxiliary/providerfeatures.json diff --git a/src/resourceproviders.json b/src/auxiliary/resourceproviders.json similarity index 100% rename from src/resourceproviders.json rename to src/auxiliary/resourceproviders.json diff --git a/src/private/ConvertTo-AzOpsState.ps1 b/src/private/ConvertTo-AzOpsState.ps1 index 8f93462a..72091c72 100644 --- a/src/private/ConvertTo-AzOpsState.ps1 +++ b/src/private/ConvertTo-AzOpsState.ps1 @@ -282,7 +282,7 @@ function ConvertTo-AzOpsState { } } else { - Write-AzOpsLog -Level Warning -Topic "ConvertTo-AzOpsState" -Message "Unable to find valid object to convert." + Write-AzOpsLog -Level Warning -Topic "ConvertTo-AzOpsState" -Message "Unable to find valid object to convert" } } diff --git a/src/private/Get-AzOpsAllSubscription.ps1 b/src/private/Get-AzOpsAllSubscription.ps1 index 4eac1de6..50acf3de 100644 --- a/src/private/Get-AzOpsAllSubscription.ps1 +++ b/src/private/Get-AzOpsAllSubscription.ps1 @@ -52,7 +52,7 @@ function Get-AzOpsAllSubscription { $IncludedSubscriptions = $AllSubscriptionsResults | Where-Object { $_.state -notin $ExcludedStates -and $_.subscriptionPolicies.quotaId -notin $ExcludedOffers } # Validate that subscriptions were found if ($null -eq $IncludedSubscriptions) { - Write-AzOpsLog -Level Error -Topic "Get-AzOpsAllSubscription" -Message "Found [$($IncludedSubscriptions.count)] subscriptions - verify appropriate permissions or that excluded offers and states are correct." + Write-AzOpsLog -Level Error -Topic "Get-AzOpsAllSubscription" -Message "Found [$($IncludedSubscriptions.count)] subscriptions - verify appropriate permissions or that excluded offers and states are correct" } else { # Calculate no of excluded subscriptions diff --git a/src/private/Get-AzOpsResourceDefinitionAtScope.ps1 b/src/private/Get-AzOpsResourceDefinitionAtScope.ps1 index dd987069..bb087193 100644 --- a/src/private/Get-AzOpsResourceDefinitionAtScope.ps1 +++ b/src/private/Get-AzOpsResourceDefinitionAtScope.ps1 @@ -143,11 +143,11 @@ function Get-AzOpsResourceDefinitionAtScope { catch { if ($retryCount -lt $maxRetryCount) { $sleepTimeInSeconds = [math]::Pow($backoffMultiplier, $retryCount) - Write-AzOpsLog -Level Warning -Topic "Get-AzOpsResourceDefinitionAtScope" -Message "Caught error finding Resource Groups (retryCount=$retryCount). Waiting for $sleepTimeInSeconds seconds." + Write-AzOpsLog -Level Warning -Topic "Get-AzOpsResourceDefinitionAtScope" -Message "Caught error finding Resource Groups (retryCount=$retryCount). Waiting for $sleepTimeInSeconds seconds" Start-Sleep -Seconds $sleepTimeInSeconds } elseif ($retryCount -ge $maxRetryCount) { - Write-AzOpsLog -Level Warning -Topic "Get-AzOpsResourceDefinitionAtScope" -Message "Timeout exporting Resource Groups from Subscription $($context.Subscription.Id)." + Write-AzOpsLog -Level Warning -Topic "Get-AzOpsResourceDefinitionAtScope" -Message "Timeout exporting Resource Groups from Subscription $($context.Subscription.Id)" Write-AzOpsLog -Level Error -Topic "Get-AzOpsResourceDefinitionAtScope" -Message "$($_.Exception.Message | Out-String)" break } @@ -206,11 +206,11 @@ function Get-AzOpsResourceDefinitionAtScope { catch { if ($retryCount -lt $maxRetryCount) { $sleepTimeInSeconds = [math]::Pow($backoffMultiplier, $retryCount) - Write-AzOpsLog -Level Warning -Topic "Get-AzOpsResourceDefinitionAtScope" -Message "Caught error finding Resources (retryCount=$retryCount). Waiting for $sleepTimeInSeconds seconds." + Write-AzOpsLog -Level Warning -Topic "Get-AzOpsResourceDefinitionAtScope" -Message "Caught error finding Resources (retryCount=$retryCount). Waiting for $sleepTimeInSeconds seconds" Start-Sleep -Seconds $sleepTimeInSeconds } elseif ($retryCount -ge $maxRetryCount) { - Write-AzOpsLog -Level Warning -Topic "Get-AzOpsResourceDefinitionAtScope" -Message "Timeout exporting Resources from Resource Group [$($rg.ResourceGroupName)]." + Write-AzOpsLog -Level Warning -Topic "Get-AzOpsResourceDefinitionAtScope" -Message "Timeout exporting Resources from Resource Group [$($rg.ResourceGroupName)]" Write-AzOpsLog -Level Error -Topic "Get-AzOpsResourceDefinitionAtScope" -Message "$($_.Exception.Message | Out-String)" break } diff --git a/src/private/New-AzOpsStateDeployment.ps1 b/src/private/New-AzOpsStateDeployment.ps1 index ca09bc49..e11061e4 100644 --- a/src/private/New-AzOpsStateDeployment.ps1 +++ b/src/private/New-AzOpsStateDeployment.ps1 @@ -187,7 +187,7 @@ function New-AzOpsStateDeployment { New-AzResourceGroupDeployment -ResourceGroupName $scope.resourcegroup -TemplateFile $templatePath -TemplateParameterFile $filename -Name $deploymentName } else { - Write-AzOpsLog -Level Error -Topic "New-AzOpsStateDeployment" -Message "Resource Group [$($scope.resourcegroup)] not found. Unable to initiate deployment." + Write-AzOpsLog -Level Error -Topic "New-AzOpsStateDeployment" -Message "Resource Group [$($scope.resourcegroup)] not found. Unable to initiate deployment" } } elseif ($scope.subscription -and $PSCmdlet.ShouldProcess("Start Subscription Deployment?")) { diff --git a/src/public/Initialize-AzOpsGlobalVariables.ps1 b/src/public/Initialize-AzOpsGlobalVariables.ps1 index d56fd8c5..4fd2653e 100644 --- a/src/public/Initialize-AzOpsGlobalVariables.ps1 +++ b/src/public/Initialize-AzOpsGlobalVariables.ps1 @@ -42,10 +42,11 @@ function Initialize-AzOpsGlobalVariables { # Required environment variables hashtable with default values $AzOpsEnvVariables = @{ + # AzOps AZOPS_STATE = @{ AzOpsState = (Join-Path $pwd -ChildPath "azops") } # Folder to store AzOpsState artefact AZOPS_MAIN_TEMPLATE = @{ AzOpsMainTemplate = "$PSScriptRoot\..\..\template\template.json" } # Main template json AZOPS_STATE_CONFIG = @{ AzOpsStateConfig = "$PSScriptRoot\..\AzOpsStateConfig.json" } # Configuration file for resource serialization - AZOPS_ENROLLMENT_PRINCIPAL_NAME = @{ AzOpsEnrollmentAccountPrincipalName = $null } + AZOPS_ENROLLMENT_ACCOUNT = @{ AzOpsEnrollmentAccountPrincipalName = $null } AZOPS_EXCLUDED_SUB_OFFER = @{ AzOpsExcludedSubOffer = "AzurePass_2014-09-01,FreeTrial_2014-09-01,AAD_2015-09-01" } # Excluded QuotaIDs as per https://docs.microsoft.com/en-us/azure/cost-management-billing/costs/understand-cost-mgt-data#supported-microsoft-azure-offers AZOPS_EXCLUDED_SUB_STATE = @{ AzOpsExcludedSubState = "Disabled,Deleted,Warned,Expired,PastDue" } # Excluded subscription states as per https://docs.microsoft.com/en-us/rest/api/resources/subscriptions/list#subscriptionstate AZOPS_OFFER_TYPE = @{ AzOpsOfferType = 'MS-AZR-0017P' } @@ -60,15 +61,31 @@ function Initialize-AzOpsGlobalVariables { AZOPS_STRICT_MODE = @{ AzOpsStrictMode = 0 } AZOPS_SKIP_RESOURCE_GROUP = @{ AzOpsSkipResourceGroup = 1 } AZOPS_SKIP_POLICY = @{ AzOpsSkipPolicy = 0 } - GITHUB_API_URL = @{ GitHubApiUrl = $null } - GITHUB_PULL_REQUEST = @{ GitHubPullRequest = $null } - GITHUB_REPOSITORY = @{ GitHubRepository = $null } - GITHUB_TOKEN = @{ GitHubToken = $null } - GITHUB_AUTO_MERGE = @{ GitHubAutoMerge = 1 } - GITHUB_BRANCH = @{ GitHubBranch = $null } - GITHUB_COMMENTS = @{ GitHubComments = $null } + # Azure DevOps + AZDEVOPS_AUTO_MERGE = @{ AzDevOpsAutoMerge = 1 } + AZDEVOPS_EMAIL = @{ AzDevOpsEmail = $null } + AZDEVOPS_USERNAME = @{ AzDevOpsUsername = $null } + AZDEVOPS_PULL_REQUEST = @{ AzDevOpsPullRequest = $null } + AZDEVOPS_PULL_REQUEST_ID = @{ AzDevOpsPullRequestId = $null } + AZDEVOPS_HEAD_REF = @{ AzDevOpsHeadRef = $null } + AZDEVOPS_BASE_REF = @{ AzDevOpsBaseRef = $null } + AZDEVOPS_API_URL = @{ AzDevOpsApiUrl = $null } + AZDEVOPS_PROJECT_ID = @{ AzDevOpsProjectId = $null } + AZDEVOPS_REPOSITORY = @{ AzDevOpsRepository = $null } + AZDEVOPS_TOKEN = @{ AzDevOpsToken = $null } + # GitHub + GITHUB_AUTO_MERGE = @{ GitHubAutoMerge = 1 } # Auto merge pull requests for pull workflow + GITHUB_EMAIL = @{ GitHubEmail = $null } + GITHUB_USERNAME = @{ GitHubUsername = $null } + GITHUB_PULL_REQUEST = @{ GitHubPullRequest = $null } # Pull Request title GITHUB_HEAD_REF = @{ GitHubHeadRef = $null } GITHUB_BASE_REF = @{ GitHubBaseRef = $null } + GITHUB_API_URL = @{ GitHubApiUrl = $null } # Built-in env var + GITHUB_REPOSITORY = @{ GitHubRepository = $null } # Built-in env var + GITHUB_TOKEN = @{ GitHubToken = $null } # Built-in env var + GITHUB_COMMENTS = @{ GitHubComments = $null } # Built-in env var + # Source Control + SCM_PLATFORM = @{ SCMPlatform = "GitHub" } } # Iterate through each variable and take appropriate action foreach ($AzOpsEnv in $AzOpsEnvVariables.Keys) { @@ -165,7 +182,7 @@ function Initialize-AzOpsGlobalVariables { } else { - Write-AzOpsLog -Level Error -Topic "Initialize-AzOpsGlobalVariables" -Message "Cannot access root management group $RootScope. Verify that principal $((Get-AzContext).Account.Id) have access or set env:AZOPS_SUPPORT_PARTIAL_MG_DISCOVERY to 1 for partial discovery support." + Write-AzOpsLog -Level Error -Topic "Initialize-AzOpsGlobalVariables" -Message "Cannot access root management group $RootScope. Verify that principal $((Get-AzContext).Account.Id) have access or set env:AZOPS_SUPPORT_PARTIAL_MG_DISCOVERY to 1 for partial discovery support" } } diff --git a/src/public/Initialize-AzOpsRepository.ps1 b/src/public/Initialize-AzOpsRepository.ps1 index 1aa04ec7..e182ccfa 100644 --- a/src/public/Initialize-AzOpsRepository.ps1 +++ b/src/public/Initialize-AzOpsRepository.ps1 @@ -92,12 +92,12 @@ function Initialize-AzOpsRepository { } # Set environment variable ExportRawTemplate to 1 if switch ExportRawTemplate switch has been used if ($PSBoundParameters['ExportRawTemplate']) { - $env:ExportRawTemplate = 1 + $env:AZOPS_EXPORT_RAW_TEMPLATES = 1 } # Initialize Global Variables and return error if not set Initialize-AzOpsGlobalVariables if (-not (Test-AzOpsVariables)) { - Write-AzOpsLog -Level Error -Topic "Initialize-AzOpsRepository" -Message "AzOps Global Variables not set." + Write-AzOpsLog -Level Error -Topic "Initialize-AzOpsRepository" -Message "AzOps Global Variables not set" } # Get tenant id for current Az Context $TenantId = (Get-AzContext).Tenant.Id @@ -123,7 +123,7 @@ function Initialize-AzOpsRepository { #Handle migration from old folder structure by checking for parenthesis pattern $MigrationRequired = (Get-ChildItem -Recurse -Force -Path $global:AzOpsState -File | Where-Object { $_.Name -like "Microsoft.Management-managementGroups_$TenantId.parameters.json" } | Select-Object -ExpandProperty FullName -First 1) -notmatch '\((.*)\)' if ($MigrationRequired) { - Write-AzOpsLog -Level Verbose -Topic "Initialize-AzOpsRepository" -Message "Migration from old to new structure required. All artifacts will be lost." + Write-AzOpsLog -Level Verbose -Topic "Initialize-AzOpsRepository" -Message "Migration from old to new structure required. All artifacts will be lost" } if ($PSBoundParameters['Force'] -or $true -eq $MigrationRequired) { # Force will delete $global:AzOpsState directory diff --git a/src/public/Invoke-AzOpsGitPull.ps1 b/src/public/Invoke-AzOpsGitPull.ps1 index 6d0d92b3..5eaef39f 100644 --- a/src/public/Invoke-AzOpsGitPull.ps1 +++ b/src/public/Invoke-AzOpsGitPull.ps1 @@ -64,7 +64,7 @@ function Invoke-AzOpsGitPull { Write-AzOpsLog -Level Information -Topic "git" -Message "Creating new commit" Start-AzOpsNativeExecution { - git commit -m 'System commit' + git commit -m 'System pull commit' } | Out-Host Write-AzOpsLog -Level Information -Topic "git" -Message "Pushing new changes to origin" @@ -72,101 +72,119 @@ function Invoke-AzOpsGitPull { git push origin system -f } | Out-Null - # GitHub Labels - Write-AzOpsLog -Level Information -Topic "rest" -Message "Checking if label (system) exists" - # TODO: Replace REST call when GH CLI paging support is available - $params = @{ - Uri = ($global:GitHubApiUrl + "/repos/" + $global:GitHubRepository + "/labels") - Headers = @{ - "Authorization" = ("Bearer " + $global:GitHubToken) - } - } - $response = Invoke-RestMethod -Method "Get" @params | Where-Object -FilterScript { $_.name -like "system" } - - if (-not $response) { - # GitHub Labels - Create - Write-AzOpsLog -Level Information -Topic "rest" -Message "Creating new label (system)" - # TODO: Replace REST call when GH CLI paging support is available - $params = @{ - Uri = ($global:GitHubApiUrl + "/repos/" + $global:GitHubRepository + "/labels") - Headers = @{ - "Authorization" = ("Bearer " + $global:GitHubToken) - "Content-Type" = "application/json" + switch ($global:SCMPlatform) { + "GitHub" { + # GitHub Labels - Get + Write-AzOpsLog -Level Information -Topic "rest" -Message "Checking if label (system) exists" + # TODO: Replace REST call when GH CLI paging support is available + $params = @{ + Uri = ($global:GitHubApiUrl + "/repos/" + $global:GitHubRepository + "/labels") + Headers = @{ + "Authorization" = ("Bearer " + $global:GitHubToken) + } + } + $response = Invoke-RestMethod -Method "Get" @params | Where-Object -FilterScript { $_.name -like "system" } + + if (-not $response) { + # GitHub Labels - Create + Write-AzOpsLog -Level Information -Topic "rest" -Message "Creating new label (system)" + # TODO: Replace REST call when GH CLI paging support is available + $params = @{ + Uri = ($global:GitHubApiUrl + "/repos/" + $global:GitHubRepository + "/labels") + Headers = @{ + "Authorization" = ("Bearer " + $global:GitHubToken) + "Content-Type" = "application/json" + } + Body = (@{ + "name" = "system" + "description" = "[AzOps] Do not delete" + "color" = "db9436" + } | ConvertTo-Json) + } + $response = Invoke-RestMethod -Method "Post" @params } - Body = (@{ - "name" = "system" - "description" = "[AzOps] Do not delete" - "color" = "db9436" - } | ConvertTo-Json) - } - $response = Invoke-RestMethod -Method "Post" @params - } - Write-AzOpsLog -Level Information -Topic "rest" -Message "Checking if pull request exists" - # TODO: Replace REST call when GH CLI paging support is available - $params = @{ - Uri = ($global:GitHubApiUrl + "/repos/" + $global:GitHubRepository + ("/pulls?state=open&head=") + $global:GitHubRepository + ":system") - Headers = @{ - "Authorization" = ("Bearer " + $global:GitHubToken) - } - } - $response = Invoke-RestMethod -Method "Get" @params - - # GitHub Pull Request - Create - if (-not $response) { - Write-AzOpsLog -Level Information -Topic "gh" -Message "Creating new pull request" - Start-AzOpsNativeExecution { - gh pr create --title $global:GitHubPullRequest --body "Auto-generated PR triggered by Azure Resource Manager" --label "system" --repo $global:GitHubRepository - } | Out-Host - } - else { - Write-AzOpsLog -Level Information -Topic "gh" -Message "Skipping pull request creation" - } + # GitHub PUll Request - List + Write-AzOpsLog -Level Information -Topic "rest" -Message "Checking if pull request exists" + # TODO: Replace REST call when GH CLI paging support is available + $params = @{ + Uri = ($global:GitHubApiUrl + "/repos/" + $global:GitHubRepository + ("/pulls?state=open&head=") + $global:GitHubRepository + ":system") + Headers = @{ + "Authorization" = ("Bearer " + $global:GitHubToken) + } + } + $response = Invoke-RestMethod -Method "Get" @params - # GitHub Pull Request - Merge - if ($global:GitHubAutoMerge -eq 1) { - Write-AzOpsLog -Level Information -Topic "rest" -Message "Retrieving new pull request" - $params = @{ - Uri = ($global:GitHubApiUrl + "/repos/" + $global:GitHubRepository + ("/pulls?state=open&head=") + $global:GitHubRepository + ":system") - Headers = @{ - "Authorization" = ("Bearer " + $global:GitHubToken) + # GitHub Pull Request - Create + if (-not $response) { + Write-AzOpsLog -Level Information -Topic "gh" -Message "Creating new pull request" + Start-AzOpsNativeExecution { + gh pr create --title $global:GitHubPullRequest --body "Auto-generated PR triggered by Azure Resource Manager" --label "system" --repo $global:GitHubRepository + } | Out-Host } - } - $response = Invoke-RestMethod -Method "Get" @params - - Write-AzOpsLog -Level Information -Topic "gh" -Message "Merging new pull request" - $attempt = 1 - $retryCount = 6 - $unmerged = $true - do { - $attempt = $attempt + 1 - try { + else { + Write-AzOpsLog -Level Information -Topic "gh" -Message "Skipping pull request creation" + } + + # GitHub Pull Request - Wait + Start-Sleep -Seconds 5 + + # GitHub Pull Request - Merge + if ($global:GitHubAutoMerge -eq 1) { + Write-AzOpsLog -Level Information -Topic "rest" -Message "Retrieving new pull request" + $params = @{ + Uri = ($global:GitHubApiUrl + "/repos/" + $global:GitHubRepository + ("/pulls?state=open&head=") + $global:GitHubRepository + ":system") + Headers = @{ + "Authorization" = ("Bearer " + $global:GitHubToken) + } + } + $response = Invoke-RestMethod -Method "Get" @params + + Write-AzOpsLog -Level Information -Topic "gh" -Message "Merging new pull request" Start-AzOpsNativeExecution { gh pr merge $response[0].number --squash --delete-branch -R $global:GitHubRepository } | Out-Host - $unmerged = $false } - catch { - Write-AzOpsLog -Level Warning -Topic "gh" -Message "Retrying pull request merge, attempt $attempt" - Start-Sleep -Seconds 5 + else { + Write-AzOpsLog -Level Information -Topic "gh" -Message "Skipping pull request merge" } } - while ($unmerged -and ($attempt -lt $retryCount)) + "AzureDevOps" { + Write-AzOpsLog -Level Information -Topic "az" -Message "Checking if pull request exists" + $response = Start-AzOpsNativeExecution { + az repos pr list --status active --output json + } | ConvertFrom-Json | ForEach-Object { $_ | Where-Object -FilterScript { $_.sourceRefName -eq "refs/heads/system" } } + + # Azure DevOps Pull Request - Create + if ($null -eq $response) { + Write-AzOpsLog -Level Information -Topic "az" -Message "Creating new pull request" + Start-AzOpsNativeExecution { + az repos pr create --source-branch "refs/heads/system" --target-branch "refs/heads/main" --title $global:AzDevOpsPullRequest --description "Auto-generated PR triggered by Azure Resource Manager `nNew or modified resources discovered in Azure" + } | Out-Host + } + else { + Write-AzOpsLog -Level Information -Topic "az" -Message "Skipping pull request creation" + } - if ($unmerged -eq $true) { - $params = @{ - Headers = @{ - "Authorization" = ("Bearer " + $global:GitHubToken) + # Azure DevOps Pull Request - Wait + Start-Sleep -Second 5 + + # Azure DevOps Pull Request - Merge + if ($global:AzDevOpsAutoMerge -eq 1) { + Write-AzOpsLog -Level Information -Topic "az" -Message "Retrieving new pull request" + $response = Start-AzOpsNativeExecution { + az repos pr list --status active --source-branch "refs/heads/system" --target-branch "refs/heads/main" --output json + } | ConvertFrom-Json + + Write-AzOpsLog -Level Information -Topic "az" -Message "Merging new pull request" + Start-AzOpsNativeExecution { + az repos pr update --id $response.pullRequestId --auto-complete --delete-source-branch --status completed --squash true } - Body = (@{ - "body" = "$(Get-Content -Path "$PSScriptRoot/../auxiliary/merge/README.md" -Raw)" - } | ConvertTo-Json) } - Invoke-RestMethod -Method "POST" -Uri ($global:GitHubApiUrl + "/repos/" + $global:GitHubRepository + "/issues/" + $response[0].number + "/comments") @params | Out-Null } - } - else { - Write-AzOpsLog -Level Information -Topic "gh" -Message "Skipping pull request merge" + default { + Write-AzOpsLog -Level Error -Topic "none" -Message "Could not determine SCM platform. Current value is $global:SCMPlatform" + } } } } diff --git a/src/public/Invoke-AzOpsGitPush.ps1 b/src/public/Invoke-AzOpsGitPush.ps1 index dde18a6a..24c237c8 100644 --- a/src/public/Invoke-AzOpsGitPush.ps1 +++ b/src/public/Invoke-AzOpsGitPush.ps1 @@ -17,7 +17,10 @@ function Invoke-AzOpsGitPush { else { $skipPolicy = $false } - #Ensure git on the host has info about origin + + # Skip AzDevOps Run + $skip = $false + Write-AzOpsLog -Level Information -Topic "git" -Message "Fetching latest origin changes" Start-AzOpsNativeExecution { git fetch origin @@ -25,6 +28,11 @@ function Invoke-AzOpsGitPush { if ($global:AzOpsStrictMode -eq 1) { Write-AzOpsLog -Level Information -Topic "pwsh" -Message "AzOpsStrictMode is set to 1, verifying pull before push" + + Write-AzOpsLog -Level Information -Topic "git" -Message "Fetching latest origin changes" + Start-AzOpsNativeExecution { + git fetch origin + } | Out-Host Write-AzOpsLog -Level Information -Topic "git" -Message "Checking out origin branch (main)" Start-AzOpsNativeExecution { @@ -54,30 +62,51 @@ function Invoke-AzOpsGitPush { git reset --hard } | Out-Host - Write-AzOpsLog -Level Information -Topic "git" -Message "Checking if local branch ($global:GitHubHeadRef) exists" - $branch = Start-AzOpsNativeExecution { - git branch --list $global:GitHubHeadRef - } - - if ($branch) { - Write-AzOpsLog -Level Information -Topic "git" -Message "Checking out existing local branch ($global:GitHubHeadRef)" - Start-AzOpsNativeExecution { - git checkout $global:GitHubHeadRef - } | Out-Host - } - else { - Write-AzOpsLog -Level Information -Topic "git" -Message "Checking out new local branch ($global:GitHubHeadRef)" - Start-AzOpsNativeExecution { - git checkout -b $global:GitHubHeadRef origin/$global:GitHubHeadRef - } | Out-Host + switch ($global:SCMPlatform) { + "GitHub" { + Write-AzOpsLog -Level Information -Topic "git" -Message "Checking if local branch ($global:GitHubHeadRef) exists" + $branch = Start-AzOpsNativeExecution { + git branch --list $global:GitHubHeadRef + } + + if ($branch) { + Write-AzOpsLog -Level Information -Topic "git" -Message "Checking out existing local branch ($global:GitHubHeadRef)" + Start-AzOpsNativeExecution { + git checkout $global:GitHubHeadRef + } | Out-Host + } + else { + Write-AzOpsLog -Level Information -Topic "git" -Message "Checking out new local branch ($global:GitHubHeadRef)" + Start-AzOpsNativeExecution { + git checkout -b $global:GitHubHeadRef origin/$global:GitHubHeadRef + } | Out-Host + } + } + "AzureDevOps" { + Write-AzOpsLog -Level Information -Topic "git" -Message "Checking if local branch ($global:AzDevOpsHeadRef) exists" + $branch = Start-AzOpsNativeExecution { + git branch --list $global:AzDevOpsHeadRef + } + + if ($branch) { + Write-AzOpsLog -Level Information -Topic "git" -Message "Checking out existing local branch ($global:AzDevOpsHeadRef)" + Start-AzOpsNativeExecution { + git checkout $global:AzDevOpsHeadRef + } | Out-Host + } + else { + Write-AzOpsLog -Level Information -Topic "git" -Message "Checking out new local branch ($global:AzDevOpsHeadRef)" + Start-AzOpsNativeExecution { + git checkout -b $global:AzDevOpsHeadRef origin/$global:AzDevOpsHeadRef + } | Out-Host + } + } } if ($diff) { Write-AzOpsLog -Level Information -Topic "git" -Message "Formatting diff changes" $diff = $diff -join "," - } - if ($null -ne $diff) { Write-AzOpsLog -Level Information -Topic "git" -Message "Changes:" $output = @() $diff.Split(",") | ForEach-Object { @@ -85,153 +114,215 @@ function Invoke-AzOpsGitPush { $output += "`n`n" Write-AzOpsLog -Level Information -Topic "git" -Message $_ } - Write-AzOpsLog -Level Information -Topic "git" -Message "Branch is not consistent with Azure" - Write-AzOpsLog -Level Information -Topic "rest" -Message "Writing comment to pull request" - Write-AzOpsLog -Level Verbose -Topic "rest" -Message "Uri: $global:GitHubComments" - $params = @{ - Headers = @{ - "Authorization" = ("Bearer " + $global:GitHubToken) + + switch ($global:SCMPlatform) { + "GitHub" { + Write-AzOpsLog -Level Information -Topic "rest" -Message "Writing comment to pull request" + Write-AzOpsLog -Level Verbose -Topic "rest" -Message "Uri: $global:GitHubComments" + $params = @{ + Headers = @{ + "Authorization" = ("Bearer " + $global:GitHubToken) + "Content-Type" = "application/json" + } + Body = (@{ + "body" = "$(Get-Content -Path "$PSScriptRoot/../auxiliary/guidance/strict/github/README.md" -Raw) `n Changes: `n`n$output" + } | ConvertTo-Json) + } + Invoke-RestMethod -Method "Post" -Uri $global:GitHubComments @params | Out-Null + exit 1 + } + "AzureDevOps" { + Write-AzOpsLog -Level Information -Topic "rest" -Message "Writing comment to pull request" + $params = @{ + Uri = ($global:AzDevOpsApiUrl + $global:AzDevOpsProjectId + "/_apis/git/repositories/" + $global:AzDevOpsRepository + "/pullRequests/" + $global:AzDevOpsPullRequestId + "/threads?api-version=5.1") + Method = "Post" + Headers = @{ + "Authorization" = ("Bearer " + $global:AzDevOpsToken) + "Content-Type" = "application/json" + } + Body = (@{ + comments = @( + (@{ + "parentCommentId" = 0 + "content" = "$(Get-Content -Path "$PSScriptRoot/../auxiliary/guidance/strict/azdevops/README.md" -Raw) `n Changes: `n`n$output" + "commentType" = 1 + }) + ) + } | ConvertTo-Json -Depth 5) + } + Invoke-RestMethod @params + exit 1 + } + default { + Write-AzOpsLog -Level Error -Topic "rest" -Message "Could not determine SCM platform from SCMPLATFORM. Current value is $global:SCMPlatform" } - Body = (@{ - "body" = "$(Get-Content -Path "$PSScriptRoot/../auxiliary/guidance/strict/README.md" -Raw) `n Changes: `n`n$output" - } | ConvertTo-Json) } - Invoke-RestMethod -Method "POST" -Uri $global:GitHubComments @params | Out-Null - exit 1 } else { Write-AzOpsLog -Level Information -Topic "git" -Message "Branch is consistent with Azure" } - #At this stage branch for the PR is checked out successfully. - } - else { - Write-AzOpsLog -Level Information -Topic "pwsh" -Message "AzOpsStrictMode is set to 0, skipping pull before push" + } } process { - # Write-AzOpsLog -Level Information -Topic "git" -Message "Pulling latest changes" - # Start-AzOpsNativeExecution { - # git pull - # } | Out-Host - - # Changes - Write-AzOpsLog -Level Information -Topic "git" -Message "Checking for additions / modifications / deletions" - $changeSet = @() - $changeSet = Start-AzOpsNativeExecution { - git diff origin/main --ignore-space-at-eol --name-status - } + switch ($global:SCMPlatform) { + "GitHub" { + $changeSet = @() + $changeSet = Start-AzOpsNativeExecution { + git diff origin/main --ignore-space-at-eol --name-status + } + } + "AzureDevOps" { + Write-AzOpsLog -Level Information -Topic "git" -Message "Switching to branch" + Start-AzOpsNativeExecution { + git checkout $global:AzDevOpsHeadRef + } | Out-Host - if (!$changeSet) { - Write-AzOpsLog -Level Information -Topic "git" -Message "No changes detected" - } - else { - Write-AzOpsLog -Level Information -Topic "git" -Message "Iterating through changes" + $commitMessage = Start-AzOpsNativeExecution { + git log -1 --pretty=format:%s + } + Write-AzOpsLog -Level Verbose -Topic "git" -Message "Commit message: $commitMessage" + + if ($commitMessage -match "System push commit") { + $skip = $true + } + + if ($skip -eq $true) { + $changeSet = @() + } + else { + $changeSet = @() + $changeSet = Start-AzOpsNativeExecution { + git diff origin/main --ignore-space-at-eol --name-status + } + } + } } - $deleteSet = @() - $addModifySet = @() - foreach ($change in $changeSet) { - $filename = ($change -split "`t")[-1] - if (($change -split "`t" | Select-Object -first 1) -eq 'D') { - $deleteSet += $filename + if ($changeSet) { + Write-AzOpsLog -Level Information -Topic "git" -Message "Deployment required" + + $deleteSet = @() + $addModifySet = @() + foreach ($change in $changeSet) { + $filename = ($change -split "`t")[-1] + if (($change -split "`t" | Select-Object -first 1) -eq 'D') { + $deleteSet += $filename + } + elseif (($change -split "`t" | Select-Object -first 1) -eq 'A' -or 'M' -or 'R') { + $addModifySet += $filename + } } - elseif (($change -split "`t" | Select-Object -first 1) -eq 'A' -or 'M' -or 'R') { - $addModifySet += $filename + + Write-AzOpsLog -Level Information -Topic "git" -Message "Add / Modify:" + $addModifySet | ForEach-Object { + Write-AzOpsLog -Level Information -Topic "git" -Message $_ } - } - Write-AzOpsLog -Level Information -Topic "git" -Message "Add / Modify:" - $addModifySet | ForEach-Object { - Write-AzOpsLog -Level Information -Topic "git" -Message $_ - } + Write-AzOpsLog -Level Information -Topic "git" -Message "Delete:" + $deleteSet | ForEach-Object { + Write-AzOpsLog -Level Information -Topic "git" -Message $_ + } - Write-AzOpsLog -Level Information -Topic "git" -Message "Delete:" - $deleteSet | ForEach-Object { - Write-AzOpsLog -Level Information -Topic "git" -Message $_ - } + $addModifySet ` + | Where-Object -FilterScript { $_ -match '/*.subscription.json$' } ` + | Sort-Object -Property $_ ` + | ForEach-Object { + Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking new state deployment - *.subscription.json for a file $_" + New-AzOpsStateDeployment -filename $_ + } - # Deployment - $addModifySet ` - | Where-Object -FilterScript { $_ -match '/*.subscription.json$' } ` - | Sort-Object -Property $_ ` - | ForEach-Object { - Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking new state deployment - *.subscription.json for a file $_" - New-AzOpsStateDeployment -filename $_ - } + $addModifySet ` + | Where-Object -FilterScript { $_ -match '/*.providerfeatures.json$' } ` + | Sort-Object -Property $_ ` + | ForEach-Object { + Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking new state deployment - *.providerfeatures.json for a file $_" + New-AzOpsStateDeployment -filename $_ + } - $addModifySet ` - | Where-Object -FilterScript { $_ -match '/*.providerfeatures.json$' } ` - | Sort-Object -Property $_ ` - | ForEach-Object { - Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking new state deployment - *.providerfeatures.json for a file $_" - New-AzOpsStateDeployment -filename $_ - } + $addModifySet ` + | Where-Object -FilterScript { $_ -match '/*.resourceproviders.json$' } ` + | Sort-Object -Property $_ ` + | ForEach-Object { + Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking new state deployment - *.resourceproviders.json for a file $_" + New-AzOpsStateDeployment -filename $_ + } - $addModifySet ` - | Where-Object -FilterScript { $_ -match '/*.resourceproviders.json$' } ` - | Sort-Object -Property $_ ` - | ForEach-Object { - Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking new state deployment - *.resourceproviders.json for a file $_" - New-AzOpsStateDeployment -filename $_ + $addModifySet ` + | Where-Object -FilterScript { $_ -match '/*.parameters.json$' } ` + | Sort-Object -Property $_ ` + | Foreach-Object { + Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking new state deployment - *.parameters.json for a file $_" + New-AzOpsStateDeployment -filename $_ + } } - - $addModifySet ` - | Where-Object -FilterScript { $_ -match '/*.parameters.json$' } ` - | Sort-Object -Property $_ ` - | Foreach-Object { - Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking new state deployment - *.parameters.json for a file $_" - New-AzOpsStateDeployment -filename $_ + else { + Write-AzOpsLog -Level Information -Topic "git" -Message "Deployment not required" } } end { - Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking post refresh process" - - Write-AzOpsLog -Level Information -Topic "git" -Message "Fetching latest origin changes" - Start-AzOpsNativeExecution { - git fetch origin - } | Out-Host - - Write-AzOpsLog -Level Information -Topic "git" -Message "Checking out existing local branch ($global:GitHubHeadRef)" - Start-AzOpsNativeExecution { - git checkout $global:GitHubHeadRef - } | Out-Host - - Write-AzOpsLog -Level Information -Topic "git" -Message "Pulling origin branch ($global:GitHubHeadRef) changes" - Start-AzOpsNativeExecution { - git pull origin $global:GitHubHeadRef - } | Out-Host - - Write-AzOpsLog -Level Information -Topic "git" -Message "Merging origin branch ($global:GitHubBaseRef) changes" - Start-AzOpsNativeExecution { - git merge origin/$global:GitHubHeadRef --no-commit - } | Out-Host - - Write-AzOpsLog -Level Information -Topic "Initialize-AzOpsRepository" -Message "Invoking repository initialization" - Initialize-AzOpsRepository -InvalidateCache -Rebuild -SkipResourceGroup:$skipResourceGroup -SkipPolicy:$skipPolicy - - Write-AzOpsLog -Level Information -Topic "git" -Message "Adding azops file changes" - Start-AzOpsNativeExecution { - git add $global:AzOpsState - } | Out-Host - - Write-AzOpsLog -Level Information -Topic "git" -Message "Checking for additions / modifications / deletions" - $status = Start-AzOpsNativeExecution { - git status --short - } - - if ($status) { - Write-AzOpsLog -Level Information -Topic "git" -Message "Creating new commit" - Start-AzOpsNativeExecution { - git commit -m 'System commit' - } | Out-Host - - Write-AzOpsLog -Level Information -Topic "git" -Message "Pushing new changes to origin ($global:GitHubHeadRef)" + if ($skip -eq $false) { + switch ($global:SCMPlatform) { + "GitHub" { + Write-AzOpsLog -Level Information -Topic "git" -Message "Checking out existing local branch ($global:GitHubHeadRef)" + Start-AzOpsNativeExecution { + git checkout $global:GitHubHeadRef + } | Out-Host + + Write-AzOpsLog -Level Information -Topic "git" -Message "Pulling origin branch ($global:GitHubHeadRef) changes" + Start-AzOpsNativeExecution { + git pull origin $global:GitHubHeadRef + } | Out-Host + } + "AzureDevOps" { + Write-AzOpsLog -Level Information -Topic "git" -Message "Checking out existing local branch ($global:AzDevOpsHeadRef)" + Start-AzOpsNativeExecution { + git checkout $global:AzDevOpsHeadRef + } | Out-Host + + Write-AzOpsLog -Level Information -Topic "git" -Message "Pulling origin branch ($global:AzDevOpsHeadRef) changes" + Start-AzOpsNativeExecution { + git pull origin $global:AzDevOpsHeadRef + } | Out-Host + } + } + + Write-AzOpsLog -Level Information -Topic "Initialize-AzOpsRepository" -Message "Invoking repository initialization" + Initialize-AzOpsRepository -InvalidateCache -Rebuild -SkipResourceGroup:$skipResourceGroup -SkipPolicy:$skipPolicy + + Write-AzOpsLog -Level Information -Topic "git" -Message "Adding azops file changes" Start-AzOpsNativeExecution { - git push origin $global:GitHubHeadRef + git add $global:AzOpsState } | Out-Host + + Write-AzOpsLog -Level Information -Topic "git" -Message "Checking for additions / modifications / deletions" + $status = Start-AzOpsNativeExecution { + git status --short + } + + if ($status) { + Write-AzOpsLog -Level Information -Topic "git" -Message "Creating new commit" + Start-AzOpsNativeExecution { + git commit -m 'System push commit' + } | Out-Host + + switch ($global:SCMPlatform) { + "GitHub" { + Write-AzOpsLog -Level Information -Topic "git" -Message "Pushing new changes to origin ($global:GitHubHeadRef)" + Start-AzOpsNativeExecution { + git push origin $global:GitHubHeadRef + } | Out-Host + } + "AzureDevOps" { + Write-AzOpsLog -Level Information -Topic "git" -Message "Pushing new changes to origin ($global:AzDevOpsHeadRef)" + Start-AzOpsNativeExecution { + git push origin $global:AzDevOpsHeadRef + } | Out-Host + } + } + } } } - } \ No newline at end of file diff --git a/tests/AzOps.IAB.Tests.ps1 b/tests/AzOps.IAB.Tests.ps1 index 824bfceb..2aa99c80 100644 --- a/tests/AzOps.IAB.Tests.ps1 +++ b/tests/AzOps.IAB.Tests.ps1 @@ -64,7 +64,7 @@ Describe "Tenant E2E Deployment (Integration Test)" -Tag "integration", "e2e", " Write-AzOpsLog -Level Information -Topic "AzOps.IAB.Tests" -Message "Running Remove-AzOpsManagementGroup" Remove-AzOpsManagementGroup -GroupName 'Tailspin' } - Write-AzOpsLog -Level Information -Topic "AzOps.IAB.Tests" -Message "Tailspin Management Group hierarchy removed." + Write-AzOpsLog -Level Information -Topic "AzOps.IAB.Tests" -Message "Tailspin Management Group hierarchy removed" #endregion # Task: Initialize azops/ @@ -228,8 +228,7 @@ Describe "Tenant E2E Deployment (Integration Test)" -Tag "integration", "e2e", " AfterAll { # Cleaning up Tailspin Management Group - if(Get-AzManagementGroup -GroupName 'Tailspin' -ErrorAction SilentlyContinue) - { + if (Get-AzManagementGroup -GroupName 'Tailspin' -ErrorAction SilentlyContinue) { Write-AzOpsLog -Level Verbose -Topic "AzOps.IAB.Tests" -Message "Cleaning up Tailspin Management Group" Remove-AzOpsManagementGroup -groupName 'Tailspin' }