Skip to content

Commit efe894a

Browse files
committed
Added custom automation SDK Workflow for releasing
1 parent a2c14d0 commit efe894a

File tree

3 files changed

+393
-22
lines changed

3 files changed

+393
-22
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,369 @@
1+
name: Automation Master Workflow
2+
3+
# Controls when the workflow will run
4+
on:
5+
# Allows you to run this workflow from another workflow
6+
workflow_call:
7+
outputs:
8+
quality_gate:
9+
description: "Results from Skyline Quality Gate."
10+
value: ${{ jobs.validate_skyline_quality_gate.outputs.quality }}
11+
#artifact-id-release:
12+
artifact-id:
13+
description: "Artifact ID of uploaded Package if successful."
14+
value: ${{ jobs.artifact_creation_registration.outputs.artifact-id }}
15+
# artifact-id-development:
16+
# description: "Artifact ID of dev uploaded Package if successful."
17+
inputs:
18+
referenceName:
19+
required: true
20+
type: string
21+
runNumber:
22+
required: true
23+
type: string
24+
referenceType:
25+
required: true
26+
type: string
27+
repository:
28+
required: true
29+
type: string
30+
owner:
31+
required: true
32+
type: string
33+
sonarCloudProjectName:
34+
required: true
35+
type: string
36+
secrets:
37+
api-key:
38+
required: false
39+
sonarCloudToken:
40+
required: true
41+
azureToken:
42+
required: false
43+
44+
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
45+
jobs:
46+
validate_skyline_quality_gate:
47+
name: SDK Skyline Quality Gate
48+
runs-on: windows-latest
49+
env:
50+
detected-unit-tests: none
51+
outputs:
52+
quality: ${{ steps.quality-step.outputs.results }}
53+
steps:
54+
- uses: actions/checkout@v4
55+
with:
56+
fetch-depth: 0
57+
58+
- name: Initialize
59+
run: |
60+
echo "workspace" ${{ github.workspace }}
61+
echo "ref name" ${{ inputs.referenceName }}
62+
echo "run number" ${{ inputs.runNumber }}
63+
echo "ref type" ${{ inputs.referenceType }}
64+
echo "repository" ${{ inputs.repository }}
65+
66+
- name: Set up JDK 17
67+
uses: actions/setup-java@v4
68+
with:
69+
java-version: 17
70+
distribution: 'zulu'
71+
72+
- name: Find .sln file
73+
id: findSlnFile
74+
run: |
75+
echo solutionFilePath=$(find . -type f -name '*.sln') >> $GITHUB_OUTPUT
76+
shell: bash
77+
- name: Detect .csproj files
78+
id: detectCsprojFiles
79+
run: |
80+
$csprojFileCount = Get-ChildItem . -Recurse -File -Filter *.csproj | Measure-Object | Select-Object -ExpandProperty Count
81+
$result = "false"
82+
if($csprojFileCount -gt 0){ $result = "true" }
83+
Write-Output "csproj-file-present=$($result)" >> $Env:GITHUB_OUTPUT
84+
shell: pwsh
85+
# TODO: Refactor this in the future to a single stage with a loop that adds all the sources you specify.
86+
- name: Enable Skyline GitHub NuGet Registry
87+
if: inputs.owner == 'SkylineCommunications'
88+
run: |
89+
$SOURCE_NAME="PrivateGitHubNugets"
90+
$SOURCE_URL="https://nuget.pkg.github.com/SkylineCommunications/index.json"
91+
92+
# Check if the source exists. If it does, update it.
93+
if (dotnet nuget list source | Select-String -Pattern $SOURCE_NAME) {
94+
Write-Host "Updating existing source $SOURCE_NAME."
95+
dotnet nuget update source $SOURCE_NAME --source $SOURCE_URL --username USERNAME --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text
96+
} else {
97+
Write-Host "Adding new source $SOURCE_NAME."
98+
dotnet nuget add source $SOURCE_URL --name $SOURCE_NAME --username USERNAME --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text
99+
}
100+
shell: pwsh
101+
102+
- name: Enable Skyline Azure Cloud NuGet Registry
103+
env:
104+
AZURE_TOKEN_EXISTS: ${{ secrets.azureToken }}
105+
if: env.AZURE_TOKEN_EXISTS != null && inputs.owner == 'SkylineCommunications'
106+
run: |
107+
$SOURCE_NAME="CloudNuGets"
108+
$SOURCE_URL="https://pkgs.dev.azure.com/skyline-cloud/Cloud_NuGets/_packaging/CloudNuGet/nuget/v3/index.json"
109+
110+
# Check if the source exists. If it does, update it.
111+
if (dotnet nuget list source | Select-String -Pattern $SOURCE_NAME) {
112+
Write-Host "Updating existing source $SOURCE_NAME."
113+
dotnet nuget update source $SOURCE_NAME --source $SOURCE_URL --username az --password ${{ secrets.azureToken }} --store-password-in-clear-text
114+
} else {
115+
Write-Host "Adding new source $SOURCE_NAME."
116+
dotnet nuget add source $SOURCE_URL --name $SOURCE_NAME --username az --password ${{ secrets.azureToken }} --store-password-in-clear-text
117+
}
118+
119+
- name: Enable Skyline Azure Private NuGet Registry
120+
env:
121+
AZURE_TOKEN_EXISTS: ${{ secrets.azureToken }}
122+
if: env.AZURE_TOKEN_EXISTS != null && inputs.owner == 'SkylineCommunications'
123+
run: |
124+
$SOURCE_NAME="PrivateAzureNuGets"
125+
$SOURCE_URL="https://pkgs.dev.azure.com/skyline-cloud/_packaging/skyline-private-nugets/nuget/v3/index.json"
126+
127+
# Check if the source exists. If it does, update it.
128+
if (dotnet nuget list source | Select-String -Pattern $SOURCE_NAME) {
129+
Write-Host "Updating existing source $SOURCE_NAME."
130+
dotnet nuget update source $SOURCE_NAME --source $SOURCE_URL --username az --password ${{ secrets.azureToken }} --store-password-in-clear-text
131+
} else {
132+
Write-Host "Adding new source $SOURCE_NAME."
133+
dotnet nuget add source $SOURCE_URL --name $SOURCE_NAME --username az --password ${{ secrets.azureToken }} --store-password-in-clear-text
134+
}
135+
136+
- name: Building
137+
if: steps.detectCsprojFiles.outputs.csproj-file-present == 'true'
138+
run: dotnet build "${{ steps.findSlnFile.outputs.solutionFilePath }}" -p:DefineConstants="DCFv1%3BDBInfo%3BALARM_SQUASHING" --configuration Release -nodeReuse:false
139+
140+
- name: Unit Tests
141+
# when not using MSTest you'll need to install coverlet.collector nuget in your test solutions
142+
id: unit-tests
143+
if: steps.detectCsprojFiles.outputs.csproj-file-present == 'true'
144+
run: dotnet test "${{ steps.findSlnFile.outputs.solutionFilePath }}" --filter TestCategory!=IntegrationTest --logger "trx;logfilename=unitTestResults.trx" --collect "XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura,opencover
145+
continue-on-error: true
146+
147+
- name: Install SonarCloud scanner
148+
if: steps.detectCsprojFiles.outputs.csproj-file-present == 'true'
149+
run: |
150+
dotnet tool install dotnet-sonarscanner --global
151+
152+
- name: Prepare SonarCloud Variables
153+
id: prepSonarCloudVar
154+
if: steps.detectCsprojFiles.outputs.csproj-file-present == 'true'
155+
run: |
156+
import os
157+
env_file = os.getenv('GITHUB_ENV')
158+
with open(env_file, "a") as myfile:
159+
myfile.write("lowerCaseOwner=" + str.lower("${{ inputs.owner }}"))
160+
shell: python
161+
162+
- name: Get SonarCloud Status
163+
id: get-sonarcloud-status
164+
if: steps.detectCsprojFiles.outputs.csproj-file-present == 'true'
165+
run: |
166+
echo "sonarCloudProjectStatus=$(curl https://${{ secrets.sonarCloudToken }}@sonarcloud.io/api/qualitygates/project_status?projectKey=${{ inputs.sonarCloudProjectName }})" >> $env:GITHUB_OUTPUT
167+
continue-on-error: true
168+
169+
- name: Trigger Initial Analysis
170+
if: steps.detectCsprojFiles.outputs.csproj-file-present == 'true' && fromJson(steps.get-sonarcloud-status.outputs.sonarCloudProjectStatus).projectStatus.status == 'NONE'
171+
env:
172+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
173+
SONAR_TOKEN: ${{ secrets.sonarCloudToken }}
174+
run: |
175+
dotnet sonarscanner begin /k:"${{ inputs.sonarCloudProjectName }}" /o:"${{ env.lowerCaseOwner }}" /d:sonar.token="${{ secrets.sonarCloudToken }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/TestResults/**/coverage.opencover.xml" /d:sonar.cs.vstest.reportsPaths="**/TestResults/**.trx"
176+
dotnet build "${{ steps.findSlnFile.outputs.solutionFilePath }}" -p:DefineConstants="DCFv1%3BDBInfo%3BALARM_SQUASHING" --configuration Release -nodeReuse:false
177+
dotnet sonarscanner end /d:sonar.token="${{ secrets.sonarCloudToken }}"
178+
continue-on-error: true
179+
180+
- name: Analyze
181+
if: steps.detectCsprojFiles.outputs.csproj-file-present == 'true'
182+
env:
183+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
184+
SONAR_TOKEN: ${{ secrets.sonarCloudToken }}
185+
run: |
186+
dotnet sonarscanner begin /k:"${{ inputs.sonarCloudProjectName }}" /o:"${{ env.lowerCaseOwner }}" /d:sonar.token="${{ secrets.sonarCloudToken }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/TestResults/**/coverage.opencover.xml" /d:sonar.cs.vstest.reportsPaths="**/TestResults/**.trx"
187+
dotnet build "${{ steps.findSlnFile.outputs.solutionFilePath }}" -p:DefineConstants="DCFv1%3BDBInfo%3BALARM_SQUASHING" --configuration Release -nodeReuse:false
188+
dotnet sonarscanner end /d:sonar.token="${{ secrets.sonarCloudToken }}"
189+
continue-on-error: true
190+
191+
- name: SonarCloud Quality Gate check
192+
id: sonarcloud-quality-gate-check
193+
if: steps.detectCsprojFiles.outputs.csproj-file-present == 'true'
194+
uses: sonarsource/sonarqube-quality-gate-action@master
195+
with:
196+
scanMetadataReportFile: .sonarqube/out/.sonar/report-task.txt
197+
continue-on-error: true
198+
# Force to fail step after specific time.
199+
timeout-minutes: 5
200+
env:
201+
SONAR_TOKEN: ${{ secrets.sonarCloudToken }}
202+
203+
- name: Quality Gate
204+
id: quality-step
205+
run: |
206+
if "${{ steps.detectCsprojFiles.outputs.csproj-file-present }}" == "false":
207+
print("Quality gate skipped as no .csproj files were detected.")
208+
exit(0)
209+
if "${{ steps.unit-tests.outcome }}" == "failure" or "${{ steps.sonarcloud-quality-gate-check.outcome }}" == "failure" or "${{ steps.sonarcloud-quality-gate-check.outputs.quality-gate-status }}" == "FAILED":
210+
print("Quality gate failed due to:")
211+
if "${{ steps.unit-tests.outcome }}" == "failure":
212+
print("- Test failures")
213+
if "${{ steps.sonarcloud-quality-gate-check.outcome }}" == "failure":
214+
print("- Could not retrieve SonarCloud quality gate status")
215+
if "${{ steps.sonarcloud-quality-gate-check.outputs.quality-gate-status }}" == "FAILED":
216+
print("- Code analysis quality gate failed")
217+
if "${{ steps.unit-tests.outcome }}" == "failure" or "${{ steps.sonarcloud-quality-gate-check.outcome }}" == "failure" or "${{ steps.sonarcloud-quality-gate-check.outputs.quality-gate-status }}" == "FAILED":
218+
exit(1)
219+
shell: python
220+
221+
artifact_creation:
222+
name: Artifact Creation
223+
runs-on: ubuntu-latest
224+
steps:
225+
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
226+
- uses: actions/checkout@v4
227+
228+
- name: Find .sln file
229+
id: findSlnFile
230+
run: |
231+
echo solutionFilePath=$(find . -type f -name '*.sln') >> $GITHUB_OUTPUT
232+
shell: bash
233+
234+
# TODO: Refactor this in the future to a single stage with a loop that adds all the sources you specify.
235+
- name: Enable Skyline GitHub NuGet Registry
236+
if: inputs.owner == 'SkylineCommunications'
237+
run: |
238+
$SOURCE_NAME="PrivateGitHubNugets"
239+
$SOURCE_URL="https://nuget.pkg.github.com/SkylineCommunications/index.json"
240+
241+
# Check if the source exists. If it does, update it.
242+
if (dotnet nuget list source | Select-String -Pattern $SOURCE_NAME) {
243+
Write-Host "Updating existing source $SOURCE_NAME."
244+
dotnet nuget update source $SOURCE_NAME --source $SOURCE_URL --username USERNAME --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text
245+
} else {
246+
Write-Host "Adding new source $SOURCE_NAME."
247+
dotnet nuget add source $SOURCE_URL --name $SOURCE_NAME --username USERNAME --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text
248+
}
249+
shell: pwsh
250+
251+
- name: Enable Skyline Azure Cloud NuGet Registry
252+
env:
253+
AZURE_TOKEN_EXISTS: ${{ secrets.azureToken }}
254+
if: env.AZURE_TOKEN_EXISTS != null && inputs.owner == 'SkylineCommunications'
255+
run: |
256+
$SOURCE_NAME="CloudNuGets"
257+
$SOURCE_URL="https://pkgs.dev.azure.com/skyline-cloud/Cloud_NuGets/_packaging/CloudNuGet/nuget/v3/index.json"
258+
259+
# Check if the source exists. If it does, update it.
260+
if (dotnet nuget list source | Select-String -Pattern $SOURCE_NAME) {
261+
Write-Host "Updating existing source $SOURCE_NAME."
262+
dotnet nuget update source $SOURCE_NAME --source $SOURCE_URL --username az --password ${{ secrets.azureToken }} --store-password-in-clear-text
263+
} else {
264+
Write-Host "Adding new source $SOURCE_NAME."
265+
dotnet nuget add source $SOURCE_URL --name $SOURCE_NAME --username az --password ${{ secrets.azureToken }} --store-password-in-clear-text
266+
}
267+
shell: pwsh
268+
269+
- name: Enable Skyline Azure Private NuGet Registry
270+
env:
271+
AZURE_TOKEN_EXISTS: ${{ secrets.azureToken }}
272+
if: env.AZURE_TOKEN_EXISTS != null && inputs.owner == 'SkylineCommunications'
273+
run: |
274+
$SOURCE_NAME="PrivateAzureNuGets"
275+
$SOURCE_URL="https://pkgs.dev.azure.com/skyline-cloud/_packaging/skyline-private-nugets/nuget/v3/index.json"
276+
277+
# Check if the source exists. If it does, update it.
278+
if (dotnet nuget list source | Select-String -Pattern $SOURCE_NAME) {
279+
Write-Host "Updating existing source $SOURCE_NAME."
280+
dotnet nuget update source $SOURCE_NAME --source $SOURCE_URL --username az --password ${{ secrets.azureToken }} --store-password-in-clear-text
281+
} else {
282+
Write-Host "Adding new source $SOURCE_NAME."
283+
dotnet nuget add source $SOURCE_URL --name $SOURCE_NAME --username az --password ${{ secrets.azureToken }} --store-password-in-clear-text
284+
}
285+
shell: pwsh
286+
287+
- name: NuGet restore solution
288+
run: dotnet restore "${{ steps.findSlnFile.outputs.solutionFilePath }}"
289+
290+
- name: Install .NET Tools
291+
run: |
292+
dotnet tool install -g Skyline.DataMiner.CICD.Tools.Packager --version 2.0.*
293+
294+
- name: Create package name
295+
id: packageName
296+
run: |
297+
tempName="${{ inputs.repository }}"
298+
echo name=${tempName//[\"\/\\<>|:*?]/_} >> $GITHUB_OUTPUT
299+
shell: bash
300+
301+
- name: Create dmapp package
302+
if: inputs.referenceType == 'tag'
303+
run: dataminer-package-create dmapp "${{ github.workspace }}" --type automation --version ${{ inputs.referenceName }} --output "${{ github.workspace }}" --name "${{ steps.packageName.outputs.name }}"
304+
305+
- name: Create dmapp package
306+
if: inputs.referenceType != 'tag'
307+
run: dataminer-package-create dmapp "${{ github.workspace }}" --type automation --build-number ${{ inputs.runNumber }} --output "${{ github.workspace }}" --name "${{ steps.packageName.outputs.name }}"
308+
309+
- uses: actions/upload-artifact@v4
310+
with:
311+
name: DataMiner Installation Package
312+
path: "${{ github.workspace }}/${{ steps.packageName.outputs.name }}.dmapp"
313+
314+
artifact_creation_registration:
315+
name: Artifact Registration and Upload
316+
if: inputs.referenceType == 'tag'
317+
runs-on: ubuntu-latest
318+
needs: [validate_skyline_quality_gate,artifact_creation]
319+
env:
320+
result-artifact-id: none
321+
outputs:
322+
artifact-id: ${{ env.result-artifact-id }}
323+
steps:
324+
- uses: actions/checkout@v4
325+
with:
326+
fetch-depth: 0
327+
328+
- name: Find branch
329+
id: findBranch
330+
run: |
331+
#!/bin/bash
332+
set -e # Exit immediately if a command exits with a non-zero status.
333+
334+
# Capture the branches containing the tag and process them
335+
branches="$(git branch --contains tags/${{ inputs.referenceName }} -r | grep 'origin/' | grep -vE '.*/.*/' | sed 's#origin/##' | paste -sd ",")"
336+
337+
# Append to GitHub Actions output
338+
echo "branch=${branches}" >> $GITHUB_OUTPUT
339+
shell: bash
340+
341+
- name: Target Branch
342+
id: showResult
343+
run: echo "${{ steps.findBranch.outputs.branch }}"
344+
345+
- name: Retrieve Installation Package
346+
id: retrieveInstallationPackage
347+
uses: actions/download-artifact@v4
348+
with:
349+
name: DataMiner Installation Package
350+
path: _DataMinerInstallationPackage
351+
352+
- name: Find Installation package
353+
id: findInstallationPackage
354+
run: |
355+
IFS=$'\n'
356+
echo dmappPackageName=$(find _DataMinerInstallationPackage -type f -name '*.dmapp') >> $GITHUB_OUTPUT
357+
unset IFS
358+
shell: bash
359+
- name: Install .NET Tools
360+
run: |
361+
dotnet tool install -g Skyline.DataMiner.CICD.Tools.CatalogUpload --version 3.0.*
362+
dotnet tool install -g Skyline.DataMiner.CICD.Tools.GitHubToCatalogYaml --version 1.0.*
363+
364+
- name: Upload to Catalog
365+
id: uploadToCatalog
366+
run: echo "id=$(dataminer-catalog-upload with-registration --path-to-artifact "${{ steps.findInstallationPackage.outputs.dmappPackageName }}" --artifact-version ${{ inputs.referenceName }} --branch "${{ steps.findBranch.outputs.branch }}" --dm-catalog-token ${{ secrets.api-key }})" >> $GITHUB_OUTPUT
367+
368+
- name: (Release) Set artifact Id
369+
run: echo "result-artifact-id=${{ steps.uploadToCatalog.outputs.id }}" >> $GITHUB_ENV

0 commit comments

Comments
 (0)