1
+ name : Build and deploy Docusaurus site to Azure Blob Storage
2
+
3
+ on :
4
+ push :
5
+ branches :
6
+ - main
7
+ - dev
8
+ workflow_dispatch :
9
+ inputs :
10
+ environment :
11
+ description : ' Environment to deploy to'
12
+ required : true
13
+ default : ' development'
14
+ type : choice
15
+ options :
16
+ - development
17
+ - production
18
+
19
+ jobs :
20
+ determine-environment :
21
+ runs-on : ubuntu-latest
22
+ outputs :
23
+ environment : ${{ steps.set-env.outputs.environment }}
24
+ steps :
25
+ - name : Determine environment
26
+ id : set-env
27
+ run : |
28
+ if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
29
+ echo "environment=${{ github.event.inputs.environment }}" >> $GITHUB_OUTPUT
30
+ elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
31
+ echo "environment=production" >> $GITHUB_OUTPUT
32
+ else
33
+ echo "environment=development" >> $GITHUB_OUTPUT
34
+ fi
35
+
36
+ build :
37
+ runs-on : self-hosted
38
+ needs : determine-environment
39
+ environment : ${{ needs.determine-environment.outputs.environment }}
40
+ permissions :
41
+ contents : read
42
+
43
+ steps :
44
+ - name : Check out source code
45
+ uses : actions/checkout@v4
46
+
47
+ - name : Set up Node.js
48
+ uses : actions/setup-node@v3
49
+ with :
50
+ node-version : ' 22.x'
51
+
52
+ - name : Cache Node.js dependencies
53
+ uses : actions/cache@v3
54
+ with :
55
+ path : ~/.npm
56
+ key : ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
57
+ restore-keys : |
58
+ ${{ runner.os }}-node-
59
+
60
+ - name : Cache Docusaurus build
61
+ uses : actions/cache@v3
62
+ id : cache-build
63
+ with :
64
+ path : |
65
+ .docusaurus
66
+ build
67
+ key : ${{ runner.os }}-docusaurus-build-${{ hashFiles('src/**', 'docs/**', 'blog/**', 'docusaurus.config.js', 'sidebars.js', 'package-lock.json') }}
68
+ restore-keys : |
69
+ ${{ runner.os }}-docusaurus-build-
70
+
71
+ - name : Cache webpack
72
+ uses : actions/cache@v3
73
+ with :
74
+ path : node_modules/.cache
75
+ key : ${{ runner.os }}-webpack-${{ hashFiles('**/package-lock.json') }}
76
+ restore-keys : |
77
+ ${{ runner.os }}-webpack-
78
+
79
+ - name : Install dependencies and build site
80
+ run : |
81
+ npm ci
82
+
83
+ # Check if we have a valid cached build
84
+ if [[ "${{ steps.cache-build.outputs.cache-hit }}" == "true" ]]; then
85
+ echo "Build cache found, checking if rebuild needed..."
86
+ # Docusaurus will intelligently rebuild only what's changed
87
+ else
88
+ echo "No build cache found, performing full build..."
89
+ fi
90
+
91
+ # Run build - Docusaurus will use its internal caching
92
+ npm run build
93
+ env :
94
+ NODE_OPTIONS : " --max-old-space-size=16384"
95
+ DOCUSAURUS_URL : " https://${{ secrets.STORAGE_ACCOUNT_NAME }}.z13.web.core.windows.net"
96
+ # Add any other environment-specific build variables here
97
+ NODE_ENV : ${{ needs.determine-environment.outputs.environment }}
98
+
99
+ - name : Upload artifact for deployment
100
+ uses : actions/upload-artifact@v4
101
+ with :
102
+ name : build-output
103
+ path : build/
104
+
105
+ deploy :
106
+ runs-on : ubuntu-latest
107
+ needs : [build, determine-environment]
108
+ environment : ${{ needs.determine-environment.outputs.environment }}
109
+
110
+ steps :
111
+ - name : Download build artifact
112
+ uses : actions/download-artifact@v4
113
+ with :
114
+ name : build-output
115
+ path : build/
116
+
117
+ - name : Install azcopy
118
+ run : |
119
+ # Download and install azcopy for faster uploads
120
+ wget -O azcopy.tar.gz https://aka.ms/downloadazcopy-v10-linux
121
+ tar -xf azcopy.tar.gz --strip-components=1
122
+ sudo mv azcopy /usr/local/bin/
123
+ azcopy --version
124
+
125
+ - name : Upload to Azure Blob Storage with AzCopy and comprehensive MIME types
126
+ run : |
127
+ echo "Deploying to ${{ needs.determine-environment.outputs.environment }} environment"
128
+ echo "Starting high-performance sync of changed files with proper MIME types..."
129
+
130
+ # Create SAS token for azcopy (more secure than using key directly)
131
+ end_date=$(date -u -d "30 minutes" '+%Y-%m-%dT%H:%MZ')
132
+ sas_token=$(az storage container generate-sas \
133
+ --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} \
134
+ --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} \
135
+ --name '$web' \
136
+ --permissions dlrw \
137
+ --expiry $end_date \
138
+ --output tsv)
139
+
140
+ # Create comprehensive content type mapping file for azcopy
141
+ cat > content-type-map.json << EOF
142
+ {
143
+ "*.css": "text/css",
144
+ "*.js": "application/javascript",
145
+ "*.mjs": "application/javascript",
146
+ "*.json": "application/json",
147
+ "*.html": "text/html",
148
+ "*.htm": "text/html",
149
+ "*.xml": "application/xml",
150
+ "*.txt": "text/plain",
151
+ "*.md": "text/markdown",
152
+
153
+ "*.png": "image/png",
154
+ "*.jpg": "image/jpeg",
155
+ "*.jpeg": "image/jpeg",
156
+ "*.gif": "image/gif",
157
+ "*.webp": "image/webp",
158
+ "*.avif": "image/avif",
159
+ "*.svg": "image/svg+xml",
160
+ "*.bmp": "image/bmp",
161
+ "*.tiff": "image/tiff",
162
+ "*.ico": "image/x-icon",
163
+
164
+ "*.woff": "font/woff",
165
+ "*.woff2": "font/woff2",
166
+ "*.ttf": "font/ttf",
167
+ "*.otf": "font/otf",
168
+ "*.eot": "application/vnd.ms-fontobject",
169
+
170
+ "*.pdf": "application/pdf",
171
+ "*.doc": "application/msword",
172
+ "*.docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
173
+ "*.xls": "application/vnd.ms-excel",
174
+ "*.xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
175
+ "*.ppt": "application/vnd.ms-powerpoint",
176
+ "*.pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
177
+ "*.odt": "application/vnd.oasis.opendocument.text",
178
+ "*.ods": "application/vnd.oasis.opendocument.spreadsheet",
179
+ "*.odp": "application/vnd.oasis.opendocument.presentation",
180
+
181
+ "*.zip": "application/zip",
182
+ "*.rar": "application/vnd.rar",
183
+ "*.7z": "application/x-7z-compressed",
184
+ "*.tar": "application/x-tar",
185
+ "*.gz": "application/gzip",
186
+ "*.bz2": "application/x-bzip2",
187
+
188
+ "*.mp4": "video/mp4",
189
+ "*.webm": "video/webm",
190
+ "*.avi": "video/x-msvideo",
191
+ "*.mov": "video/quicktime",
192
+ "*.wmv": "video/x-ms-wmv",
193
+
194
+ "*.mp3": "audio/mpeg",
195
+ "*.wav": "audio/wav",
196
+ "*.ogg": "audio/ogg",
197
+ "*.m4a": "audio/mp4",
198
+
199
+ "*.csv": "text/csv",
200
+ "*.rtf": "application/rtf",
201
+ "*.epub": "application/epub+zip",
202
+ "*.mobi": "application/x-mobipocket-ebook"
203
+ }
204
+ EOF
205
+
206
+ # Use azcopy sync with comprehensive content type mapping
207
+ azcopy sync "./build/" \
208
+ "https://${{ secrets.STORAGE_ACCOUNT_NAME }}.blob.core.windows.net/\$web?$sas_token" \
209
+ --delete-destination=true \
210
+ --compare-hash=MD5 \
211
+ --log-level=INFO \
212
+ --cap-mbps=0 \
213
+ --block-size-mb=4 \
214
+ --content-type-map="content-type-map.json"
215
+
216
+ echo "Sync completed with comprehensive MIME types!"
217
+
218
+ - name : Fallback MIME type setting for critical files
219
+ run : |
220
+ echo "Setting MIME types for critical files as fallback (in case azcopy mapping failed)..."
221
+
222
+ # Install Azure CLI if not available
223
+ if ! command -v az &> /dev/null; then
224
+ curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
225
+ fi
226
+
227
+ # Set MIME types for most critical files (CSS and JS) that affect styling
228
+ echo "Ensuring CSS files have correct MIME type..."
229
+ az storage blob update-batch \
230
+ --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} \
231
+ --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} \
232
+ --source '$web' \
233
+ --pattern "*.css" \
234
+ --content-type "text/css" \
235
+ --if-unmodified-since "1970-01-01T00:00:00Z" \
236
+ --no-progress || echo "CSS MIME type update completed (some files may have been skipped)"
237
+
238
+ echo "Ensuring JS files have correct MIME type..."
239
+ az storage blob update-batch \
240
+ --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} \
241
+ --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} \
242
+ --source '$web' \
243
+ --pattern "*.js" \
244
+ --content-type "application/javascript" \
245
+ --if-unmodified-since "1970-01-01T00:00:00Z" \
246
+ --no-progress || echo "JS MIME type update completed (some files may have been skipped)"
247
+
248
+ echo "Critical MIME types verified!"
249
+
250
+ - name : Purge CDN endpoint (if configured)
251
+ run : |
252
+ if [[ -n "${{ secrets.CDN_ENDPOINT_NAME }}" ]] && [[ -n "${{ secrets.CDN_PROFILE_NAME }}" ]] && [[ -n "${{ secrets.CDN_RESOURCE_GROUP }}" ]]; then
253
+ echo "Note: CDN purge requires Azure login. Skipping CDN purge when using storage key authentication."
254
+ echo "To use CDN purge, you'll need to use Azure AD authentication or purge CDN manually."
255
+ else
256
+ echo "CDN configuration not found, skipping CDN purge."
257
+ fi
258
+
259
+ - name : Display deployment URL
260
+ run : |
261
+ echo "🚀 Deployment complete!"
262
+ echo "Environment: ${{ needs.determine-environment.outputs.environment }}"
263
+ echo "URL: https://${{ secrets.STORAGE_ACCOUNT_NAME }}.z13.web.core.windows.net"
264
+ if [[ -n "${{ secrets.CUSTOM_DOMAIN }}" ]]; then
265
+ echo "Custom Domain: ${{ secrets.CUSTOM_DOMAIN }}"
266
+ fi
267
+ echo "All files deployed with proper MIME types for optimal browser compatibility!"
0 commit comments