Skip to content

Commit a50df00

Browse files
ADMU CI Migration (#102)
* Admu spit tests by matrix * rm env var * workspace location * checkout ADMU * env ci * pester matrix * ci and invoke pester * set matrix variable * split tests * pass build tests * start migration version * windows latest and test * cache writeout * change shell * invoke-ps2exe * Import/Install Module before build * enclose expression * print modules + install if needed * import module * import-module * import requried powershell modules * JumpCloud Module Name * no need to install aws tools * cache shell * env vars for testing + split tests * mock windows drive + circleCI * mock windows drive * mock get-windows drive * mock windows drive * prevent system from being recorded twice in permission validation * new module changelog location * build variables * ADMU Script test * command body test * re-arrange build step * build params * module validation tests * build tests * test release steps * nuspec version * out null sync * out null and exe path * Admu Exe Path * release workflow order * list out artifacts * admu artifact path + build / sign exe status * artifact location * build / sign status output * Nuspec files limitation * Build-ADMU complie fix + remove unnecessary files * nuspec file def * nuspec filter * nuspec file filter [skip ci] * windows pack with backslashes * ignore ADMU.ps1 changes, no need to commit * Add ADMU.ps1 to gitignore, no need to commit * Sa 3609 admu gha migrate ci ken (#103) * Create new test files * test * fix error * fix test * test * test * fix test * test * test * test * matrix add * test * test * test * test * test fix * test * cleanup * test * remove ADMU.ps1, update changelog + PSD1 * Invoke pester migariton tests * require codeowners file * comments cleanup * codeowners + ModuleChanglog generation * codeowners [skip ci] * codeowner [skip ci] * release date * only release on merge --------- Co-authored-by: Ken Maranion <97972790+kmaranionjc@users.noreply.github.com> Co-authored-by: Ken Maranion <ken.maranion@jumpcloud.com>
1 parent 0e124b8 commit a50df00

27 files changed

+1589
-1496
lines changed

.circleci/config.yml

Lines changed: 0 additions & 400 deletions
This file was deleted.

.github/CODEOWNERS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# ADMU Code Owners
2+
3+
* @TheJumpCloud/solutions-architecture

.github/workflows/admu-ci.yml

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
name: ADMU Module CI
2+
3+
# env:
4+
# define env vars
5+
6+
on:
7+
pull_request:
8+
branches:
9+
- master
10+
types: [opened, synchronize, reopened, labeled, unlabeled]
11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
13+
cancel-in-progress: true
14+
# define jobs
15+
jobs:
16+
Filter-Branch:
17+
runs-on: ubuntu-latest
18+
if: contains(github.event.pull_request.labels.*.name, 'ADMU')
19+
steps:
20+
- run: echo "Building JumpCloud Module 'ADMU'"
21+
Check-PR-Labels:
22+
needs: ["Filter-Branch"]
23+
runs-on: ubuntu-latest
24+
outputs:
25+
RELEASE_TYPE: ${{ steps.validate.outputs.RELEASE_TYPE }}
26+
steps:
27+
- name: Validate-PR-Version-Labels
28+
id: validate
29+
shell: pwsh
30+
run: |
31+
$PR_LABEL_LIST=$(curl -s "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels" | jq -r '.[].name')
32+
if ("ADMU" -in $PR_LABEL_LIST) {
33+
write-host "Starting Build for PowerShell Module Release"
34+
}
35+
# validate type from label list:
36+
$types = @('major', 'minor', 'patch', 'manual')
37+
$typeCount = 0
38+
foreach ($item in $PR_LABEL_LIST) {
39+
if ($item -in $types) {
40+
write-host "$item"
41+
$typeCount += 1
42+
$RELEASE_TYPE = $item
43+
}
44+
}
45+
46+
if ($typeCount -eq 1) {
47+
echo "RELEASE_TYPE=$RELEASE_TYPE" >> $env:GITHUB_OUTPUT
48+
} else {
49+
throw "Multiple or invalid release types were found on PR"
50+
exit 1
51+
}
52+
env:
53+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
54+
Validate-Env-Variables:
55+
needs: ["Filter-Branch", "Check-PR-Labels"]
56+
runs-on: ubuntu-latest
57+
steps:
58+
- env:
59+
RELEASE_TYPE: ${{ needs.Check-PR-Labels.outputs.RELEASE_TYPE }}
60+
shell: pwsh
61+
run: |
62+
# validate release type variables
63+
$env:RELEASE_TYPE | Should -BeIn @('major','minor','patch','manual')
64+
Setup-Build-Dependancies:
65+
needs: ["Filter-Branch", "Check-PR-Labels", "Validate-Env-Variables"]
66+
runs-on: windows-latest
67+
timeout-minutes: 10
68+
steps:
69+
- uses: actions/checkout@v4
70+
- name: Setup PowerShell Module Cache
71+
id: cacher
72+
uses: actions/cache@v3
73+
with:
74+
path: 'C:\Users\runneradmin\Documents\PowerShell\Modules\'
75+
key: PS-Dependancies
76+
- name: Install dependencies
77+
if: steps.cacher.outputs.cache-hit != 'true'
78+
shell: pwsh
79+
run: |
80+
Set-PSRepository PSGallery -InstallationPolicy Trusted
81+
82+
If (!(Get-PackageProvider -Name:('NuGet') -ListAvailable -ErrorAction:('SilentlyContinue'))) {
83+
Write-Host ('[status]Installing package provider NuGet');
84+
Install-PackageProvider -Name:('NuGet') -Scope:('CurrentUser') -Force
85+
}
86+
# define dependancies for this ci workflow:
87+
$PSDependencies = @{
88+
'PowerShellGet' = @{Repository = 'PSGallery'; RequiredVersion = '3.0.12-beta' }
89+
'ps2exe' = @{Repository = 'PSGallery'; RequiredVersion = '1.0.13' }
90+
'PlatyPS' = @{Repository = 'PSGallery'; RequiredVersion = '0.14.2' }
91+
'JumpCloud.SDK.V1' = @{Repository = 'PSGallery'; RequiredVersion = 'latest'}
92+
'JumpCloud.SDK.V2' = @{Repository = 'PSGallery'; RequiredVersion = 'latest'}
93+
'JumpCloud.SDK.DirectoryInsights' = @{Repository = 'PSGallery'; RequiredVersion = 'latest'}
94+
'JumpCloud' = @{Repository = 'PSGallery'; RequiredVersion = 'latest'}
95+
}
96+
foreach ($RequiredModule in $PSDependencies.Keys) {
97+
If ([System.String]::IsNullOrEmpty((Get-InstalledModule | Where-Object { $_.Name -eq $RequiredModule }))) {
98+
$latestModule = find-module $RequiredModule
99+
Write-Host "[status] latest module: $RequiredModule; latest version: $($latestModule.Version)"
100+
Write-Host("[status] Installing module: '$RequiredModule'; version: $($PSDependencies[$RequiredModule].RequiredVersion) from $($PSDependencies[$RequiredModule].Repository)")
101+
if ($($PSDependencies[$RequiredModule].RequiredVersion) -eq "latest"){
102+
Install-Module -Name $RequiredModule -Repository:($($PSDependencies[$RequiredModule].Repository))-Force
103+
} else {
104+
Install-Module -Name $RequiredModule -Repository:($($PSDependencies[$RequiredModule].Repository)) -RequiredVersion:($($PSDependencies[$RequiredModule].RequiredVersion)) -AllowPrerelease -Force
105+
}
106+
}
107+
}
108+
Build-Module:
109+
needs: ["Setup-Build-Dependancies", "Check-PR-Labels"]
110+
runs-on: windows-latest
111+
timeout-minutes: 10
112+
steps:
113+
- uses: actions/checkout@v4
114+
- uses: actions/cache@v3
115+
with:
116+
path: 'C:\Users\runneradmin\Documents\PowerShell\Modules\'
117+
key: PS-Dependancies
118+
- name: Build ADMU Module
119+
shell: powershell
120+
env:
121+
RELEASE_TYPE: ${{ needs.Check-PR-Labels.outputs.RELEASE_TYPE }}
122+
run: |
123+
. "${{ github.workspace }}/Deploy/build.ps1" -ModuleVersionType $env:RELEASE_TYPE -ModuleName "JumpCloud.ADMU"
124+
- name: Upload Nuspec
125+
uses: actions/upload-artifact@v3
126+
with:
127+
name: jumpcloud-admu-build
128+
path: |
129+
${{ github.workspace }}/Jumpcloud-ADMU/JumpCloud.ADMU.nuspec
130+
${{ github.workspace }}/Jumpcloud-ADMU/Docs/*.md
131+
${{ github.workspace }}/Jumpcloud-ADMU/Exe/*.exe
132+
${{ github.workspace }}/Jumpcloud-ADMU/Powershell/Form.ps1
133+
${{ github.workspace }}/Jumpcloud-ADMU/JumpCloud.ADMU.psd1
134+
retention-days: 1
135+
Test-Module:
136+
needs: ["Setup-Build-Dependancies", "Check-PR-Labels", "Build-Module"]
137+
runs-on: windows-latest
138+
timeout-minutes: 75
139+
strategy:
140+
fail-fast: false
141+
matrix:
142+
job_group: [0, 1, 2, 3]
143+
steps:
144+
- uses: actions/checkout@v4
145+
- name: Download artifacts
146+
uses: actions/download-artifact@v3
147+
with:
148+
name: jumpcloud-admu-build
149+
- uses: actions/cache@v3
150+
with:
151+
path: 'C:\Users\runneradmin\Documents\PowerShell\Modules\'
152+
key: PS-Dependancies
153+
- name: Test PWSH Module
154+
shell: powershell
155+
env:
156+
RELEASE_TYPE: ${{ needs.Check-PR-Labels.outputs.RELEASE_TYPE }}
157+
PESTER_APIKEY: ${{ secrets.PESTER_APIKEY }}
158+
PESTER_ORGID: ${{ secrets.PESTER_ORGID }}
159+
PESTER_CONNECTKEY: ${{ secrets.PESTER_CONNECTKEY }}
160+
run: |
161+
$env:job_group = ${{ matrix.job_group }}
162+
# build before test
163+
$installedModules = Get-ChildItem "C:\Users\runneradmin\Documents\PowerShell\Modules\"
164+
Write-Host "[status] InstalledModules:"
165+
$installedModules
166+
# Explicitly import required modules for powershell shell:
167+
$requiredModules = ('ps2exe', 'JumpCloud.SDK.DirectoryInsights', 'JumpCloud.SDK.V1', 'JumpCloud.SDK.V2', 'JumpCloud')
168+
foreach ($module in $requiredModules){
169+
$modulePSD1 = Get-ChildItem "C:\Users\runneradmin\Documents\PowerShell\Modules\$module" -Recurse -filter "*.psd1"
170+
Write-Host "[status] Importing: $module at path $($modulePSD1.fullname)"
171+
Import-Module "$($modulePSD1.fullname)" -force
172+
}
173+
. "./jumpcloud-ADMU/Powershell/InvokePester.ps1" $env:RELEASE_TYPE

.github/workflows/admu-release.yml

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
name: Release and Publish ADMU Module
2+
on:
3+
pull_request:
4+
types:
5+
- closed
6+
branches:
7+
- master
8+
jobs:
9+
Check-If-Merged:
10+
if: github.event.pull_request.merged == true
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Check if Merged
14+
run: echo {GITHUB_HEAD_REF} merged into master
15+
16+
Filter-Branch:
17+
runs-on: ubuntu-latest
18+
if: contains(github.event.pull_request.labels.*.name, 'ADMU')
19+
steps:
20+
- run: echo "Building JumpCloud Module 'ADMU'"
21+
Check-PR-Labels:
22+
needs: ["Filter-Branch", "Check-If-Merged"]
23+
runs-on: ubuntu-latest
24+
outputs:
25+
RELEASE_TYPE: ${{ steps.validate.outputs.RELEASE_TYPE }}
26+
steps:
27+
- name: Validate-PR-Version-Labels
28+
id: validate
29+
shell: pwsh
30+
run: |
31+
$PR_LABEL_LIST=$(curl -s "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels" | jq -r '.[].name')
32+
if ("ADMU" -in $PR_LABEL_LIST) {
33+
write-host "Starting Build for ADMU Module Release"
34+
}
35+
# validate type from label list:
36+
$types = @('major', 'minor', 'patch', 'manual')
37+
$typeCount = 0
38+
foreach ($item in $PR_LABEL_LIST) {
39+
if ($item -in $types) {
40+
write-host "$item"
41+
$typeCount += 1
42+
$RELEASE_TYPE = $item
43+
}
44+
}
45+
46+
if ($typeCount -eq 1) {
47+
echo "RELEASE_TYPE=$RELEASE_TYPE" >> $env:GITHUB_OUTPUT
48+
} else {
49+
throw "Multiple or invalid release types were found on PR"
50+
exit 1
51+
}
52+
env:
53+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
54+
Setup-Build-Dependancies:
55+
needs: ["Filter-Branch", "Check-PR-Labels"]
56+
runs-on: windows-latest
57+
timeout-minutes: 10
58+
steps:
59+
- uses: actions/checkout@v4
60+
- name: Setup PowerShell Module Cache
61+
id: cacher
62+
uses: actions/cache@v3
63+
with:
64+
path: 'C:\Users\runneradmin\Documents\PowerShell\Modules\'
65+
key: PS-Dependancies
66+
- name: Install dependencies
67+
if: steps.cacher.outputs.cache-hit != 'true'
68+
shell: pwsh
69+
run: |
70+
Set-PSRepository PSGallery -InstallationPolicy Trusted
71+
72+
If (!(Get-PackageProvider -Name:('NuGet') -ListAvailable -ErrorAction:('SilentlyContinue'))) {
73+
Write-Host ('[status]Installing package provider NuGet');
74+
Install-PackageProvider -Name:('NuGet') -Scope:('CurrentUser') -Force
75+
}
76+
# define dependancies for this ci workflow:
77+
$PSDependencies = @{
78+
'PowerShellGet' = @{Repository = 'PSGallery'; RequiredVersion = '3.0.12-beta' }
79+
'ps2exe' = @{Repository = 'PSGallery'; RequiredVersion = '1.0.13' }
80+
'PlatyPS' = @{Repository = 'PSGallery'; RequiredVersion = '0.14.2' }
81+
'JumpCloud.SDK.V1' = @{Repository = 'PSGallery'; RequiredVersion = 'latest'}
82+
'JumpCloud.SDK.V2' = @{Repository = 'PSGallery'; RequiredVersion = 'latest'}
83+
'JumpCloud.SDK.DirectoryInsights' = @{Repository = 'PSGallery'; RequiredVersion = 'latest'}
84+
'JumpCloud' = @{Repository = 'PSGallery'; RequiredVersion = 'latest'}
85+
}
86+
foreach ($RequiredModule in $PSDependencies.Keys) {
87+
If ([System.String]::IsNullOrEmpty((Get-InstalledModule | Where-Object { $_.Name -eq $RequiredModule }))) {
88+
$latestModule = find-module $RequiredModule
89+
Write-Host "[status] latest module: $RequiredModule; latest version: $($latestModule.Version)"
90+
Write-Host("[status] Installing module: '$RequiredModule'; version: $($PSDependencies[$RequiredModule].RequiredVersion) from $($PSDependencies[$RequiredModule].Repository)")
91+
if ($($PSDependencies[$RequiredModule].RequiredVersion) -eq "latest"){
92+
Install-Module -Name $RequiredModule -Repository:($($PSDependencies[$RequiredModule].Repository))-Force
93+
} else {
94+
Install-Module -Name $RequiredModule -Repository:($($PSDependencies[$RequiredModule].Repository)) -RequiredVersion:($($PSDependencies[$RequiredModule].RequiredVersion)) -AllowPrerelease -Force
95+
}
96+
}
97+
}
98+
Build-Sign-ADMU:
99+
runs-on: windows-latest
100+
needs: ["Setup-Build-Dependancies", "Check-PR-Labels"]
101+
steps:
102+
- uses: actions/checkout@v4
103+
- uses: actions/cache@v3
104+
with:
105+
path: "/home/runner/.local/share/powershell/Modules/"
106+
key: PS-Dependancies
107+
- name: Build ADMU Module
108+
shell: powershell
109+
env:
110+
RELEASE_TYPE: ${{ needs.Check-PR-Labels.outputs.RELEASE_TYPE }}
111+
run: |
112+
. "${{ github.workspace }}/Deploy/build.ps1" -ModuleVersionType $env:RELEASE_TYPE -ModuleName "JumpCloud.ADMU"
113+
- name: Pack nuspec
114+
shell: pwsh
115+
run: |
116+
nuget pack "${{ github.workspace }}/jumpcloud-ADMU/JumpCloud.ADMU.nuspec"
117+
- name: Validate NuPkg File
118+
shell: pwsh
119+
run: |
120+
$NupkgPathDirectory = (Get-ChildItem -Path:("./*.nupkg")).Directory
121+
$nupkgPath = (Get-ChildItem -Path:("./*.nupkg")).FullName
122+
Write-Host "NuPkg Path: $nupkgPath"
123+
mkdir $NupkgPathDirectory/nupkg_module
124+
unzip $nupkgPath -d $NupkgPathDirectory/nupkg_module
125+
$moduleRootFiles = Get-ChildItem -File -Path:("$NupkgPathDirectory/nupkg_module")
126+
$moduleRootDirectories = Get-ChildItem -Directory -Path:("$NupkgPathDirectory/nupkg_module")
127+
Write-Host "Module Files:\n$moduleRootFiles"
128+
Write-Host "Module Directories:\n$moduleRootDirectories"
129+
- name: Setup Code Signing Variables
130+
shell: bash
131+
run: |
132+
# Create Client Cert File
133+
echo "${{ secrets.SM_CLIENT_CERT_FILE_B64 }}" | base64 --decode > /d/Certificate_pkcs12.p12
134+
# Create Environment Variables
135+
echo "::set-output name=version::${GITHUB_REF#refs/tags/v}"
136+
echo "SM_HOST=${{ secrets.SM_HOST }}" >> "$GITHUB_ENV"
137+
echo "SM_API_KEY=${{ secrets.SM_API_KEY }}" >> "$GITHUB_ENV"
138+
echo "SM_CLIENT_CERT_FILE=D:\\Certificate_pkcs12.p12" >> "$GITHUB_ENV"
139+
echo "SM_CLIENT_CERT_PASSWORD=${{ secrets.SM_CLIENT_CERT_PASSWORD }}" >> "$GITHUB_ENV"
140+
echo "C:\Program Files (x86)\Windows Kits\10\App Certification Kit" >> $GITHUB_PATH
141+
echo "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools" >> $GITHUB_PATH
142+
echo "C:\Program Files\DigiCert\DigiCert One Signing Manager Tools" >> $GITHUB_PATH
143+
- name: Setup SSM KSP for Code Signing
144+
shell: cmd
145+
run: |
146+
curl -X GET https://one.digicert.com/signingmanager/api-ui/v1/releases/smtools-windows-x64.msi/download -H "x-api-key:%SM_API_KEY%" -o smtools-windows-x64.msi
147+
msiexec /i smtools-windows-x64.msi /quiet /qn
148+
smksp_registrar.exe list > nul 2>&1
149+
smctl.exe keypair ls > nul 2>&1
150+
C:\Windows\System32\certutil.exe -csp "DigiCert Signing Manager KSP" -key -user > nul 2>&1
151+
smksp_cert_sync.exe > nul 2>&1
152+
- name: Sign ADMU EXE
153+
shell: pwsh
154+
env:
155+
SM_CODE_SIGNING_CERT_SHA1_HASH: ${{ secrets.SM_CODE_SIGNING_CERT_SHA1_HASH }}
156+
run: |
157+
${{ github.workspace }}/Deploy/Sign.ps1
158+
- name: Upload Release Artifacts
159+
uses: actions/upload-artifact@v3
160+
with:
161+
name: jumpcloud-admu
162+
path: |
163+
${{ github.workspace }}/Jumpcloud-ADMU/Exe/*.exe
164+
${{ github.workspace }}/Jumpcloud-ADMU/JumpCloud.ADMU.nuspec
165+
${{ github.workspace }}/JumpCloud.ADMU.*.nupkg
166+
167+
Draft-GH-Release:
168+
needs: [Build-Sign-ADMU]
169+
runs-on: ubuntu-latest
170+
steps:
171+
- uses: actions/checkout@v4
172+
- name: Download ADMU artifact
173+
uses: actions/download-artifact@v3
174+
with:
175+
name: jumpcloud-admu
176+
- name: Build Draft Release
177+
run: |
178+
VERSION=$(grep -Po '(\d+\.\d+\.\d+)' ${{ github.workspace }}/jumpcloud-ADMU/JumpCloud.ADMU.psd1)
179+
TITLE="JumpCloud ADMU v$VERSION"
180+
CHANGELOG=$(cat ${{ github.workspace }}/ModuleChangelog.md |awk "/^## $VERSION/{ f = 1; next } /## [0-9]+.[0-9]+.[0-9]+/{ f = 0 } f")
181+
TAG="v$VERSION"
182+
BODY="$TITLE $CHANGELOG"
183+
# draft release
184+
(gh release view $TAG && echo "Release exists for $TAG") || gh release create $TAG --title "$TITLE" --notes "$BODY" --draft
185+
# upload signed artifacts
186+
ls -la ${{ github.workspace }}/jumpcloud-ADMU/Exe/
187+
gh release upload $TAG ${{ github.workspace }}/jumpcloud-ADMU/Exe/gui_jcadmu.exe ${{ github.workspace }}/jumpcloud-ADMU/Exe/uwp_jcadmu.exe
188+
env:
189+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
190+
Manual-Approval-Release:
191+
needs: ["Draft-GH-Release"]
192+
environment: PublishToPSGallery
193+
runs-on: ubuntu-latest
194+
steps:
195+
- name: Manual Approval for Release
196+
run: echo "Awaiting approval from required reviewers before continuing"
197+
Deploy-Nupkg:
198+
needs: [Manual-Approval-Release, Build-Sign-ADMU]
199+
runs-on: ubuntu-latest
200+
steps:
201+
- name: Download ADMU artifact
202+
uses: actions/download-artifact@v3
203+
with:
204+
name: jumpcloud-admu
205+
- name: Publish
206+
shell: pwsh
207+
run: |
208+
# add nuget source for PSGallery:
209+
dotnet nuget add source "https://www.powershellgallery.com/api/v2/package" --name PSGallery
210+
# get nupkg artifact:
211+
$nupkgPath = (Get-ChildItem -Path:("./*.nupkg")).FullName
212+
# test
213+
$nupkgPath | Should -Exist
214+
Write-Host "Nupkg Artifact Restored: $nupkgPath"
215+
# nuget push from here:
216+
# TODO: TO PUBLISH UNCOMMENT BELOW:
217+
# dotnet nuget push $nupkgPath --source PSGallery --api-key $env:NuGetApiKey
218+
env:
219+
NuGetApiKey: ${{ secrets.NUGETAPIKEY }}

0 commit comments

Comments
 (0)