Skip to content
This repository has been archived by the owner on Nov 19, 2024. It is now read-only.

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
scottdurow committed Sep 15, 2024
0 parents commit eca34c9
Show file tree
Hide file tree
Showing 770 changed files with 97,551 additions and 0 deletions.
231 changes: 231 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
name: Build

permissions:
id-token: write
packages: write
contents: write

on:
workflow_dispatch:
inputs:
forceRebuild:
description: 'Force rebuild even if there are no changes'
required: false
type: boolean
default: false

# Run build on pull requests but don't create a release yet
pull_request:
branches-ignore:
- release/*
- releases/*

# Run build on push to a release branch
push:
branches:
- main
- release/*
- releases/*

concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}
cancel-in-progress: true

jobs:
Build:
# Needs to be windows so that the nuget package inclusion of the .NET Framework will resolve
runs-on: windows-latest
name: ${{ matrix.solutionName }}
environment: solution-checker
strategy:
matrix:
include: ${{ fromJson(vars.SOLUTIONS_CONFIG) }}

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Semantic Versioning
uses: paulhatch/[email protected]
id: get_version
with:
tag_prefix: "v"
major_pattern: "(MAJOR-${{ matrix.solutionName }})"
minor_pattern: "(MINOR-${{ matrix.solutionName }})"
namespace: "${{ matrix.solutionName }}"
# Optional path to check for changes. If any changes are detected in the path the
# 'changed' output will true. Enter multiple paths separated by spaces.
change_path: "${{ matrix.changeScope}}"
user_format_type: "csv"
debug: true


- name: Check if changes detected
if: steps.get_version.outputs.changed == 'false'
run: |
echo "No changes detected in '${{ matrix.changeScope}}/${{ matrix.solutionSubFolder}}', build cancelled."
shell: pwsh

- name: Check that there is not already a release that is deployed with this tag
# This is a check to ensure that the release is not already deployed
# Skip if the build is forced
if: github.event_name != 'pull_request' && (steps.get_version.outputs.changed == 'true' || github.event.inputs.forceRebuild == 'true')
uses: actions/github-script@v7
with:
debug: true
script: |
const releaseTag = '${{ steps.get_version.outputs.version_tag }}';
const repo = context.repo;
// Find the release by tag name
const { data: releases } = await github.rest.repos.listReleases(repo);
const release = releases.find(r => r.tag_name === releaseTag);
if (release && !release.draft) {
console.log(`Release ${releaseTag} is already deployed.`);
core.setFailed(`Release ${releaseTag} is already deployed.`);
}
- name: Install pac
uses: microsoft/powerplatform-actions/actions-install@v1
with:
add-tools-to-path: true

- name: Update Solution Versions (within the scope)
if: steps.get_version.outputs.changed == 'true' || github.event.inputs.forceRebuild == 'true'
run: |
$major = ${{ steps.get_version.outputs.major }}
$minor = ${{ steps.get_version.outputs.minor }}
$patch = ${{ steps.get_version.outputs.patch }}
$increment = ${{ steps.get_version.outputs.increment }}
$path = "${{ github.workspace }}/${{ matrix.changeScope }}"
$paddedPatch = "{0:000}" -f $patch
$paddedIncrement = "{0:000}" -f $increment
function UpdateFileContent($fileFilter, $matchPattern, $replacePattern) {
Write-Output "Update File Content: $fileFilter, $matchPattern, $replacePattern"
$filesToUpdate = Get-ChildItem -Path $path -Recurse -Filter $fileFilter
foreach ($file in $filesToUpdate) {
Write-Output "Updating version in $($file.FullName)"
$content = Get-Content -Path $file.FullName -Raw
$updatedContent = $content -replace $matchPattern, $replacePattern
Set-Content -Path $file.FullName -Value $updatedContent
}
}
# Find all .csproj and update AssemblyVersion
# Information on versioning plugins:
# https://learn.microsoft.com/en-us/power-apps/developer/data-platform/register-plug-in#assembly-versioning
UpdateFileContent "*.csproj" "<AssemblyVersion>[0-9]+(\.[0-9]+)*</AssemblyVersion>" "<AssemblyVersion>$($major).$($minor).$($patch).$($increment)</AssemblyVersion>"
# Find all .dll.data.xml and update version
UpdateFileContent "*.dll.data.xml" ' Version=[0-9]+(\.[0-9]+)*,' " Version=$($major).$($minor).$($patch).$($increment),"
# Find all RootComponents in Solution.Xml and update version
# <RootComponent type="91" id="{539003b6-e003-43c6-8be6-aaa55b4e0337}" schemaName="ContosoRealEstate.BusinessLogic, Version=1.0.0.0, Culture=neutral, PublicKeyToken=997b77ea5fb469e5" behavior="0" />
UpdateFileContent "Solution.xml" '(?<=<RootComponent type="91"[^>]*?Version=)[0-9]+(\.[0-9]+)*,' "$($major).$($minor).$($patch).$($increment),"
# Find all ControlManifest.Input.xml and update version
# Alternatives are to use the following - but cannot control the entire version
# pac can be used, but throws an error if no manifest found - and doesn't update the whole version
# pac pcf version --allmanifests --patchversion ${{ steps.get_version.outputs.patch }} --updatetarget project
UpdateFileContent "ControlManifest.Input.xml" '(?<!(resx" )|(css" )|(React" )|(Fluent" )|(xml ))version="[0-9]+(\.[0-9]+)*"' "version=""$($major).$($minor).$($paddedPatch)$($paddedIncrement)"""
# Find all solution.xml and update version
# pac can be used, but doesn't update the whole version
# pac solution version --revisionversion <number> --solutionPath "./<folder>"
# pac solution version --buildversion <number> --solutionPath "./<folder>"
UpdateFileContent "Solution.xml" "<Version>[0-9]+(\.[0-9]+)*</Version>" "<Version>$($major).$($minor).$($patch).$($increment)</Version>"
shell: pwsh
working-directory: "./${{ matrix.changeScope}}"

- name: Setup .NET
if: steps.get_version.outputs.changed == 'true' || github.event.inputs.forceRebuild == 'true'
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x

- name: Build
if: steps.get_version.outputs.changed == 'true' || github.event.inputs.forceRebuild == 'true'
run: dotnet build -c Release
working-directory: "./${{ matrix.changeScope}}/${{ matrix.solutionSubFolder}}"

- name: Auth pac
if: steps.get_version.outputs.changed == 'true' || github.event.inputs.forceRebuild == 'true'
run: |
pac auth create --githubFederated --tenant ${{ secrets.PAC_DEPLOY_AZURE_TENANT_ID }} --applicationId ${{ secrets.PAC_DEPLOY_CLIENT_ID }} --environment ${{ secrets.PAC_DEPLOY_ENV_URL }}
shell: pwsh

- name: Run pac solution check
if: steps.get_version.outputs.changed == 'true' || github.event.inputs.forceRebuild == 'true'
run: |
$solutionPath = "${{ github.workspace }}/${{ matrix.changeScope}}/${{ matrix.solutionSubFolder}}/bin/"
$solutionFile = "${{ matrix.solutionName }}.zip"
$outputPath = "$solutionPath/SolutionChecker"
if (Test-Path $outputPath) {
Remove-Item -Path $outputPath -Recurse -Force
}
# Run pac solution check - exclude bundle.js from the check due to false positives with transpiled code
pac solution check -p $solutionPath/$solutionFile -ef bundle.js -o $outputPath
$sarifFilePath = Get-ChildItem -Path $outputPath -Filter "*.zip" -Recurse | Select-Object -First 1
Expand-Archive -Path $sarifFilePath.FullName -DestinationPath $outputPath
$sarifFilePath = Get-ChildItem -Path $outputPath -Filter "*.sarif" -Recurse | Select-Object -First 1
$sarifContent = Get-Content -Path $sarifFilePath.FullName -Raw | ConvertFrom-Json
$criticalIssues = 0
$highIssues = 0
foreach ($run in $sarifContent.runs) {
foreach ($result in $run.results) {
$severity = $result.properties.severity
if ($severity -eq "Critical") {
$criticalIssues++
} elseif ($severity -eq "High") {
$highIssues++
}
}
}
Write-Output "Critical Issues: $criticalIssues"
Write-Output "High Issues: $highIssues"
if ($criticalIssues -gt 0 -or $highIssues -gt 0) {
Write-Error "Build failed due to critical or high severity issues from Solution Checker."
exit 1
}
shell: pwsh
working-directory: "."

- name: Publish Artifacts
uses: actions/upload-artifact@v4
with:
name: build-artifacts-${{ matrix.solutionName }}
path: '${{ matrix.changeScope }}/${{ matrix.solutionSubFolder }}/bin/**'
overwrite: true

- name: Create release artifact list
if: github.event_name != 'pull_request' && (steps.get_version.outputs.changed == 'true' || github.event.inputs.forceRebuild == 'true')
id: get_artifacts
run: |
$files = Get-ChildItem -Path "./${{ matrix.changeScope }}/data" -Filter "*data.zip" -Recurse | ForEach-Object { $_.FullName }
if ($null -eq $files) {
$files = @() # Initialize as an empty array if it is null
}
$files += "${{ matrix.changeScope }}/${{ matrix.solutionSubFolder }}/bin/${{ matrix.solutionName }}_managed.zip"
$files += "${{ matrix.changeScope }}/${{ matrix.solutionSubFolder }}/bin/${{ matrix.solutionName }}.zip"
$filesOutput = $files -join "`n"
echo "RELEASE_ARTIFACTS<<EOF" >> $env:GITHUB_OUTPUT
echo $filesOutput >> $env:GITHUB_OUTPUT
echo "EOF" >> $env:GITHUB_OUTPUT
shell: powershell

- name: Create Release
if: github.event_name != 'pull_request' && startsWith(github.ref, 'refs/heads/release') && (steps.get_version.outputs.changed == 'true' || github.event.inputs.forceRebuild == 'true')
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
files: ${{ steps.get_artifacts.outputs.RELEASE_ARTIFACTS}}
tag_name: ${{ steps.get_version.outputs.version_tag }}
name: ${{ steps.get_version.outputs.version_tag }}
draft: ${{ github.event_name == 'pull_request' }} ## Create a draft release if this is just a pull request
target_commitish: ${{ github.sha }}
prerelease: false
46 changes: 46 additions & 0 deletions .github/workflows/deploy-environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# This workflow is triggered by the parent workflow and deploys the required solutions to the specified environment
# The solutions are deployed in sequential order one at a time
name: _Deploy Environment

on:
workflow_call:
inputs:
environment:
required: true
type: string
stageAndUpgrade:
required: false
type: string # workflow calls use strings instead of booleans
default: 'true'
secrets:
PAC_DEPLOY_CLIENT_ID:
required: true
PAC_DEPLOY_ENV_URL:
required: true
PAC_DEPLOY_AZURE_TENANT_ID:
required: true
PLUGIN_MANAGED_IDENTITY_APP_ID:
required: true

# Note: The environment secrets are defined here, but acutally provided by the environment that the
# child workflow runs under. They don't exist as repo secrets
# See: https://github.com/actions/runner/issues/1490
jobs:
Deploy:
strategy:
max-parallel: 1
matrix:
include: ${{ fromJson(vars.SOLUTIONS_CONFIG) }}

uses: ./.github/workflows/import-solution.yml
with:
environment: ${{ inputs.environment}}
solutionName: ${{ matrix.solutionName }}
stageAndUpgrade: ${{ inputs.stageAndUpgrade }}
secrets:
PAC_DEPLOY_CLIENT_ID: ${{ secrets.PAC_DEPLOY_CLIENT_ID }}
PAC_DEPLOY_ENV_URL: ${{ secrets.PAC_DEPLOY_ENV_URL }}
PAC_DEPLOY_AZURE_TENANT_ID: ${{ secrets.PAC_DEPLOY_AZURE_TENANT_ID }}
PLUGIN_MANAGED_IDENTITY_APP_ID: ${{ secrets.PLUGIN_MANAGED_IDENTITY_APP_ID }}


67 changes: 67 additions & 0 deletions .github/workflows/deploy-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# This workflow is triggered manually
# It will deploy the latest solutions to the development, testing, and production environments
name: Deploy

permissions:
id-token: write
packages: write
contents: write

on:
workflow_dispatch:
inputs:
stageAndUpgrade:
description: 'Stage and Upgrade'
type: boolean
default: false

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

# Note: The environment secrets are defined here, but acutally provided by the environment that the
# child workflow runs under. They don't exist as repo secrets
# See: https://github.com/actions/runner/issues/1490
jobs:
development:
uses: ./.github/workflows/deploy-environment.yml
with:
environment: 'development'
stageAndUpgrade: ${{ github.event.inputs.stageAndUpgrade }}
secrets:
PAC_DEPLOY_CLIENT_ID: ${{ secrets.PAC_DEPLOY_CLIENT_ID }}
PAC_DEPLOY_ENV_URL: ${{ secrets.PAC_DEPLOY_ENV_URL }}
PAC_DEPLOY_AZURE_TENANT_ID: ${{ secrets.PAC_DEPLOY_AZURE_TENANT_ID }}
PLUGIN_MANAGED_IDENTITY_APP_ID: ${{ secrets.PLUGIN_MANAGED_IDENTITY_APP_ID }}
name: Development

testing:
if: false
uses: ./.github/workflows/deploy-environment.yml
with:
environment: 'testing'
stageAndUpgrade: ${{ github.event.inputs.stageAndUpgrade }}
secrets:
PAC_DEPLOY_CLIENT_ID: ${{ secrets.PAC_DEPLOY_CLIENT_ID }}
PAC_DEPLOY_ENV_URL: ${{ secrets.PAC_DEPLOY_ENV_URL }}
PAC_DEPLOY_AZURE_TENANT_ID: ${{ secrets.PAC_DEPLOY_AZURE_TENANT_ID }}
PLUGIN_MANAGED_IDENTITY_APP_ID: ${{ secrets.PLUGIN_MANAGED_IDENTITY_APP_ID }}
needs: development
name: Testing

production:
if: false
uses: ./.github/workflows/deploy-environment.yml
with:
environment: 'production'
stageAndUpgrade: ${{ github.event.inputs.stageAndUpgrade =='true' }}
secrets:
PAC_DEPLOY_CLIENT_ID: ${{ secrets.PAC_DEPLOY_CLIENT_ID }}
PAC_DEPLOY_ENV_URL: ${{ secrets.PAC_DEPLOY_ENV_URL }}
PAC_DEPLOY_AZURE_TENANT_ID: ${{ secrets.PAC_DEPLOY_AZURE_TENANT_ID }}
PLUGIN_MANAGED_IDENTITY_APP_ID: ${{ secrets.PLUGIN_MANAGED_IDENTITY_APP_ID }}
needs: [testing, development]
name: Production



Loading

0 comments on commit eca34c9

Please sign in to comment.