-
Notifications
You must be signed in to change notification settings - Fork 0
286 lines (255 loc) · 10.5 KB
/
template-test-build-and-publish-to-azure.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
name: Full Publish Pipeline Template Workflow
# This template will test, build, create a new release with the .zip artifacts, and deploy to Azure Functions.
#
# To create a new release, the <AssemblyVersion> of the csproj must be updated. If it's the same, no new release
# will be created.
#
# If publishToAzure input is set to true, the workflow will also deploy the new release to the Azure Functions App.
on:
workflow_call:
inputs:
dotnetVersion:
description: '[Required] The version of .NET to use. Example: "8.0.x"'
required: true
type: string
targetPlatform:
description: '[Required] The target platform for the build. Example: "win-x64"'
required: true
type: string
targetRuntime:
description: '[Required] The target runtime for the build. Example: "net8.0"'
required: true
type: string
projectFolder:
description: '[Required] The folder where the project is located. Example: "Raccoon.Ninja.AzFn.DataApi"'
required: true
type: string
projectFile:
description: '[Required] The project file. Example: "Raccoon.Ninja.AzFn.DataApi.csproj"'
required: true
type: string
releaseFilePrefix:
description: '[Required] The prefix for the release file. Example: "AzFnDataApi"'
required: true
type: string
publishToAzure:
description: '[Required] If true, the workflow will deploy the new release to the Azure Functions App.'
required: true
type: boolean
secrets:
githubToken:
description: '[Required] The GitHub token to use for the workflow.'
required: true
azureFunctionAppName:
description: '[Required only if publishToAzure is true] The name of the Azure Functions App to deploy to.'
required: false
azurePublishProfile:
description: '[Required only if publishToAzure is true] The Azure Publish Profile for deployment.'
required: false
jobs:
set_release_version:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.set_version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Define next release version
id: set_version
run: echo "version=$(cat ${{ inputs.projectFolder }}/${{ inputs.projectFile }} | grep -oP '(?<=<AssemblyVersion>).*(?=<\/AssemblyVersion>)')" >> $GITHUB_OUTPUT
test:
needs: set_release_version
permissions:
deployments: write
contents: write
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ inputs.dotnetVersion }}
- name: Test
run: dotnet test ${{ inputs.projectFolder }}/${{ inputs.projectFile }} --verbosity normal
check_tag:
needs: [set_release_version, test]
runs-on: ubuntu-latest
env:
VERSION: ${{ needs.set_release_version.outputs.version }}
outputs:
tag_exists: ${{ steps.check_tag.outputs.tag_exists }}
proceed_with_publish: ${{ steps.check_tag.outputs.proceed_with_publish }}
artifact_name: ${{ steps.set_artifact_name.outputs.artifact_name }}
steps:
- name: Set Artifact Name
id: set_artifact_name
run: |
echo "artifact_name=${{ inputs.releaseFilePrefix }}_${{ inputs.targetPlatform }}_${{ env.VERSION }}" >> $GITHUB_OUTPUT
- name: Check if this version is already built
id: check_tag
run: |
TAG_EXISTS=$(curl -o /dev/null -s -w "%{http_code}\n" -H "Authorization: token ${{ secrets.githubToken }}" https://api.github.com/repos/${{ github.repository }}/git/refs/tags/${{ env.VERSION }})
if [[ "$TAG_EXISTS" -eq 200 ]]; then
echo "Tag exists. Checking for release asset."
RELEASE_ID=$(curl -s -H "Authorization: token ${{ secrets.githubToken }}" https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ env.VERSION }} | jq -r '.id')
if [[ -z "$RELEASE_ID" || "$RELEASE_ID" == "null" ]]; then
echo "Release ID is empty or null. Proceeding to publish."
echo "tag_exists=false" >> $GITHUB_OUTPUT
echo "proceed_with_publish=true" >> $GITHUB_OUTPUT
exit 0
fi
RAW_RESPONSE=$(curl -s -H "Authorization: token ${{ secrets.githubToken }}" https://api.github.com/repos/${{ github.repository }}/releases/$RELEASE_ID/assets)
echo "Raw Response: $RAW_RESPONSE"
JSON_TYPE=$(echo "$RAW_RESPONSE" | jq -r 'type')
if [[ "$JSON_TYPE" == "object" ]]; then
echo "RAW_RESPONSE is a JSON object."
# Check if RAW_RESPONSE contains a "message" field with the value "Not Found"
MESSAGE_VALUE=$(echo "$RAW_RESPONSE" | jq -r '.message // ""')
if [[ "$MESSAGE_VALUE" == "Not Found" ]]; then
echo "No assets found for this release. Proceeding to publish."
echo "tag_exists=true" >> $GITHUB_OUTPUT
echo "proceed_with_publish=true" >> $GITHUB_OUTPUT
exit 0
elif [[ ! -z "$MESSAGE_VALUE" ]]; then
echo "An unexpected error occurred: $MESSAGE_VALUE. Exiting."
exit 1
fi
elif [[ "$JSON_TYPE" == "array" ]]; then
echo "RAW_RESPONSE is a JSON array."
ASSET_EXISTS=$(echo "$RAW_RESPONSE" | jq -r '.[] | select(.name=="${{ steps.set_artifact_name.outputs.artifact_name }}.zip").id')
if [[ ! -z "$ASSET_EXISTS" ]]; then
echo "Release asset exists. No need to publish."
echo "tag_exists=true" >> $GITHUB_OUTPUT
echo "proceed_with_publish=false" >> $GITHUB_OUTPUT
else
echo "Release asset does not exist. Proceeding to publish."
echo "tag_exists=true" >> $GITHUB_OUTPUT
echo "proceed_with_publish=true" >> $GITHUB_OUTPUT
fi
else
echo "RAW_RESPONSE is neither a JSON object nor an array. Type: $JSON_TYPE"
exit 1
fi
else
echo "Tag does not exist. Proceeding to publish."
echo "tag_exists=false" >> $GITHUB_OUTPUT
echo "proceed_with_publish=true" >> $GITHUB_OUTPUT
fi
validate_azure_inputs_for_publishing:
if: inputs.publishToAzure == true
runs-on: ubuntu-latest
steps:
- name: Check Azure Function App Name
run: |
if [ -z "${{ secrets.azureFunctionAppName }}" ]; then
echo "Azure Function App Name (azureFunctionAppName) is empty or not set."
exit 1
else
echo "Azure Function App Name is set to '${{ secrets.azureFunctionAppName }}'."
fi
- name: Check Azure Publish Profile
run: |
if [ -z "${{ secrets.azurePublishProfile }}" ]; then
echo "Azure Publish Profile (azurePublishProfile) is empty or not set."
exit 1
else
echo "Azure Publish Profile is set."
fi
build_info:
needs: [set_release_version, check_tag]
runs-on: ubuntu-latest
steps:
- name: Checkout
run: |
echo "Version: ${{ needs.set_release_version.outputs.version }}"
echo "Tag Exists: ${{ needs.check_tag.outputs.tag_exists }}"
echo "Proceed with Publish: ${{ needs.check_tag.outputs.proceed_with_publish }}"
echo "Artifact Name: ${{ needs.check_tag.outputs.artifact_name }}"
build:
needs: [set_release_version, check_tag]
if: needs.check_tag.outputs.proceed_with_publish == 'true'
permissions:
deployments: write
contents: write
runs-on: windows-latest
env:
VERSION: ${{ needs.set_release_version.outputs.version }}
ARTIFACT_NAME: ${{ needs.check_tag.outputs.artifact_name }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ inputs.dotnetVersion }}
- name: Build
run: dotnet build --configuration Release
- name: Publish Project
shell: pwsh
run: |
pushd './${{ inputs.projectFolder }}'
dotnet build --configuration Release --output ./output
popd
- name: Compressing artifact
run: |
$currentPath = Get-Location
Compress-Archive -Path "$currentPath\${{ inputs.projectFolder }}\output\*" -DestinationPath "${{ env.ARTIFACT_NAME }}.zip"
- name: Uploading artifact
id: upload_artifact
uses: actions/upload-artifact@v3
with:
name: "${{ env.ARTIFACT_NAME }}"
path: "${{ env.ARTIFACT_NAME }}.zip"
if-no-files-found: error
deploy:
needs: [ set_release_version, check_tag, build ]
permissions:
contents: write
runs-on: ubuntu-latest
env:
VERSION: ${{ needs.set_release_version.outputs.version }}
ARTIFACT_NAME: ${{ needs.check_tag.outputs.artifact_name }}
steps:
- name: Where Am I? What is going on?
run: |
echo "$(pwd) | ${{ env.VERSION }}"
ls -la
- name: Checkout
uses: actions/checkout@v4
- name: Setup Git
run: |
git config user.name "GitHub Actions"
git config user.email "github-actions@github.com"
- name: Downloading artifact
uses: actions/download-artifact@v3
with:
name: "${{ env.ARTIFACT_NAME }}"
- name: Extracting artifact
run: |
unzip "${{ env.ARTIFACT_NAME }}.zip" -d "./output"
- name: 'Publish to Azure Functions App'
uses: Azure/functions-action@v1
if: inputs.publishToAzure == true
with:
app-name: ${{ secrets.azureFunctionAppName }}
slot-name: 'Production'
package: './output'
publish-profile: ${{ secrets.azurePublishProfile }}
- name: Create Tag
if: needs.check_tag.outputs.tag_exists == false
run: |
git tag ${{ env.VERSION }}
git push origin ${{ env.VERSION }}
- name: Create Release
id: create_release
uses: softprops/action-gh-release@v1
env:
token: ${{ secrets.githubToken }}
with:
tag_name: ${{ env.VERSION }}
name: ${{ env.VERSION }}
draft: false
prerelease: false
fail_on_unmatched_files: true
files: "${{ env.ARTIFACT_NAME }}.zip"