Skip to content

Instantly share code, notes, and snippets.

@arjunumenon
Last active December 29, 2022 15:38
Show Gist options
  • Save arjunumenon/b0ebb2c3d37ae50c055dd5caaa5ec582 to your computer and use it in GitHub Desktop.
Save arjunumenon/b0ebb2c3d37ae50c055dd5caaa5ec582 to your computer and use it in GitHub Desktop.
Script files for CI CD Setup for SPFx
<#
.SYNOPSIS
Create Azure AD App Registration
.DESCRIPTION
.EXAMPLE
.\aad-app-add-aadapp.ps1 -AppName "AUM CI-CD Deployment App"
Create AAD App without Certificate and Admin Consent
.EXAMPLE
.\aad-app-add-aadapp.ps1 -AppName "AUM CI-CD Deployment App" -CertificatePath ".\AUM CI-CD Deployment App Certificate.pfx" -CertificatePassword "TempP@ssw0rd" -AutoAdminConsent
Create AAD App WITH Certificate and Admin Consent
#>
Param(
[Parameter(Mandatory = $true)]
[string]$AppName,
[Parameter(Mandatory = $false)]
[string]$APIPermissionList = "https://microsoft.sharepoint-df.com/Sites.FullControl.All, https://graph.microsoft.com/Sites.Read.All",
[Parameter(Mandatory = $false)]
[switch]$AutoAdminConsent = $false,
[Parameter(Mandatory = $false)]
[string]$CertificatePath
)
function executeAADAppCreation {
# Checking Login status and initiate login if not logged
$LoginStatus = m365 status
if ($LoginStatus -eq "Logged out") {
Write-Host "Not logged in. Initiating Login process"
m365 login
}
$AddedApp = $null
# Get the Certificate String from PFX File
# It will prompt for the password and you will have to enter the same password which was given while generation
$EncodedCertificateString = [System.Convert]::ToBase64String((
Get-PfxCertificate -FilePath $CertificatePath).GetRawCertData())
if ($AutoAdminConsent) {
$AddedApp = (m365 aad app add --name $AppName --apisApplication $APIPermissionList --redirectUris "https://login.microsoftonline.com/common/oauth2/nativeclient" --platform publicClient --certificateBase64Encoded $EncodedCertificateString --grantAdminConsent --output json) | ConvertFrom-Json
Write-Host "AAD App Created with details. App ID : $($AddedApp.appId). Object ID : $($AddedApp.objectId). Tenant ID : $($AddedApp.tenantId)"
}
else {
$AddedApp = (m365 aad app add --name $AppName --apisApplication $APIPermissionList --redirectUris "https://login.microsoftonline.com/common/oauth2/nativeclient" --platform publicClient --certificateBase64Encoded $EncodedCertificateString --output json) | ConvertFrom-Json
Write-Host "AAD App Created with details. App ID : $($AddedApp.appId). Object ID : $($AddedApp.objectId). Tenant ID : $($AddedApp.tenantId)"
# Manually Opening the URL with the browser
Write-Host "Open this URL for consenting the permission - https://login.microsoftonline.com/$($AddedApp.tenantId)/v2.0/adminconsent?client_id=$($AddedApp.appId)&scope=.default"
}
}
executeAADAppCreation
<#
.SYNOPSIS
Creates a Self Signed Certificate for use in server to server authentication
.DESCRIPTION
.EXAMPLE
.\Create-SelfSignedCertificate.ps1 -CommonName "MyCert" -StartDate 2015-11-21 -EndDate 2017-11-21
This will create a new self signed certificate with the common name "CN=MyCert". During creation you will be asked to provide a password to protect the private key.
.EXAMPLE
.\Create-SelfSignedCertificate.ps1 -CommonName "MyCert" -StartDate 2015-11-21 -EndDate 2017-11-21 -Password "MyPassword"
This will create a new self signed certificate with the common name "CN=MyCert". The password as specified in the Password parameter will be used to protect the private key
#>
Param(
[Parameter(Mandatory=$true)]
[string]$CommonName,
[Parameter(Mandatory=$true)]
[DateTime]$StartDate,
[Parameter(Mandatory=$true)]
[DateTime]$EndDate,
[Parameter(Mandatory=$true)]
[string]$Password
)
function CreateSelfSignedCertificate{
$cert = New-SelfSignedCertificate -Subject "CN=$CommonName" -FriendlyName $CommonName -NotBefore $StartDate -NotAfter $EndDate -CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -KeySpec Signature -KeyLength 2048 -KeyAlgorithm RSA -HashAlgorithm SHA256
# Export Certificate from Variable to cert file to the location where script is executed
Export-Certificate -Cert $cert -FilePath ".\$CommonName.cer"
# Secure the file with password for enhanced security
$mypwd = ConvertTo-SecureString -String "$Password" -Force -AsPlainText
# Exporting the file to PFX file with Password
Export-PfxCertificate -Cert $cert -FilePath ".\$CommonName.pfx" -Password $mypwd
}
CreateSelfSignedCertificate
<#
.SYNOPSIS
Adds the App to the SharePoint App Catalog. Script could be used for CI/CD setup in Azure DevOps
.DESCRIPTION
.EXAMPLE
.\m365-spo-login.ps1 -certificateFile "$(caCertificate.secureFilePath)" --password "" --appId "$(AppId)" --tenant "$(TenantId)"
Initiate Login in the Ci-CD Pipeline
.EXAMPLE
.\m365-spo-login.ps1 -certificateFile "C:\Arjun\dev-rnd\SPFx-CI-CD-Setup-GH\CI-CD-Setup\onetime-aad-setup\AUM CI-CD Deployment App Certificate.pfx" -password "TempP@ssw0rd" -appId "7ccd6d8e-a2ff-41ad-a3b2-176047c68ad1" -TenantId "095efa67-57fa-40c7-b7cc-e96dc3e5780c"
Initiate Login directly from the machine
#>
Param(
[Parameter(Mandatory = $true)]
[string]$certificateFile,
[Parameter(Mandatory = $false)]
[string]$password,
[Parameter(Mandatory = $true)]
[string]$appId,
[Parameter(Mandatory=$true)]
[string]$TenantId
)
function m365loginCertificate{
m365 login --authType certificate --certificateFile $certificateFile --password $password --appId $appId --tenant $TenantId
m365 status
}
m365loginCertificate
# Variable Group 'Deployment - SharePoint Environment' was defined in the Variables tab
trigger:
branches:
include:
- refs/heads/main
paths:
exclude:
- /CI-CD-Setup
name: $(Date:yyyyMMdd)$(Rev:.r)_
jobs:
- job: Job_1
displayName: SPFx Package Building Agent
pool:
vmImage: ubuntu-20.04
steps:
- checkout: self
- task: NodeTool@0
displayName: Install Node 14.15.0
inputs:
versionSpec: 14.15.0
- task: Npm@1
displayName: npm install
inputs:
workingDir: SPFx-CICD-1
verbose: false
- task: gulp@0
displayName: SPFx - Bundle Solution
inputs:
gulpFile: $(ProjectFolder)/gulpfile.js
targets: bundle
arguments: --ship
cwd: $(ProjectFolder)
- task: gulp@0
displayName: SPFx - Ship the solution
inputs:
gulpFile: $(ProjectFolder)/gulpfile.js
targets: package-solution
arguments: --ship
cwd: $(ProjectFolder)
- task: CopyFiles@2
displayName: 'Copy Files to: $(build.artifactstagingdirectory)/$(ProjectFolder)/drop'
inputs:
SourceFolder: $(ProjectFolder)
Contents: $(SolutionPackageLocation)/$(PackageName)
TargetFolder: $(build.artifactstagingdirectory)/$(ProjectFolder)/drop
- task: CopyFiles@2
displayName: 'Copy Script Files to: $(build.artifactstagingdirectory)/$(ProjectFolder)/drop'
inputs:
SourceFolder: CI-CD-Setup/scripts-powershell
Contents: '*'
TargetFolder: $(build.artifactstagingdirectory)/$(ProjectFolder)/drop
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: drop'
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/$(ProjectFolder)/drop
...

About

Script files used for the blog whch explains CICD in SPFx environment

<#
.SYNOPSIS
Adds the App to the SharePoint App Catalog
.DESCRIPTION
.EXAMPLE
.\spo-app-add.ps1 -PackageFolder "$(System.DefaultWorkingDirectory)/$(ProjectFolder)/drop/$(SolutionPackageLocation)/" -packageName "$(PackageName)" -URL "$(SiteCollection)"
Installing the App command from CI-CD Pipeline
.EXAMPLE
.\spo-app-add.ps1 -PackageFolder "C:\Arjun\Codes\m365-ci-cd-solution\SPFx-CI-CD-Setup\SPFx-CICD-1\sharepoint\solution\" -packageName "sp-fx-cicd-1.sppkg" -URL "https://contoso.sharepoint.com/sites/M365CLI"
Installing the app from base machine
#>
Param(
[Parameter(Mandatory = $true)]
[string]$PackageFolder,
[Parameter(Mandatory = $true)]
[string]$packageName,
[Parameter(Mandatory = $true)]
[string]$URL,
[Parameter(Mandatory=$false)]
[boolean]$IsAdd = $true,
[Parameter(Mandatory=$false)]
[boolean]$IsDeploy = $true,
[Parameter(Mandatory=$false)]
[boolean]$IsInstall = $true
)
function addCustomApp{
$CompletePath = "$PackageFolder/$packageName"
Write-Host "Deploying the Package from the path : "$CompletePath
#Check if App is already installed
$IsDeployed = checkIfAppIsInstalled -packageName $packageName -URL $URL
if($IsAdd)
{
Write-Host "App not Available. Adding the app to App Catalog with Package Name : $packageName"
$AppId = m365 spo app add --filePath $CompletePath --appCatalogScope sitecollection --appCatalogUrl $URL --overwrite --output text
Write-Host "Added the App to the Site Collection. App ID : $AppId"
}
if($IsDeploy)
{
#Deploy the app
deployCustomApp -URL $URL -AppId $AppId
Write-Host "Deployed App with ID : $AppId"
}
if($IsInstall)
{
#Install Custom App
if($IsDeployed)
{
Write-Host "App is already deployed. Hence skipping installation"
}
else
{
Write-Host "App with name $packageName is not deployed. Installing it now"
installCustomApp -URL $URL -AppId $AppId
}
}
}
function deployCustomApp{
param (
[Parameter(Mandatory = $true)]
[string]$AppId,
[Parameter(Mandatory = $true)]
[string]$URL
)
Write-Host "Deploying App with ID : $AppId"
m365 spo app deploy --id $AppId --appCatalogScope sitecollection --appCatalogUrl $URL
}
function installCustomApp{
param (
[Parameter(Mandatory = $true)]
[string]$AppId,
[Parameter(Mandatory = $true)]
[string]$URL
)
Write-Host "Installing App with ID : $AppId"
m365 spo app install --id $AppId --siteUrl $URL --appCatalogScope sitecollection
}
function checkIfAppIsInstalled{
param (
[Parameter(Mandatory = $true)]
[string]$packageName,
[Parameter(Mandatory = $true)]
[string]$URL
)
$IsDeployed = (m365 spo app get --name $packageName --appCatalogScope sitecollection --appCatalogUrl $URL --output json --query "{Deployed: Deployed}") | ConvertFrom-Json
return $IsDeployed.Deployed
}
addCustomApp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment