-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathaction.yaml
480 lines (426 loc) · 21.7 KB
/
action.yaml
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
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
name: "Deploy Apache Airflow DAGs to Astro"
description: "Test your DAGs and deploy your Astro project to a Deployment on Astro, Astronomer's managed Airflow service."
author: "Astronomer"
branding:
icon: "upload-cloud"
color: "purple"
inputs:
root-folder:
required: false
default: ""
description: "Path to the Astro project, or dbt project for dbt deploys."
parse:
required: false
default: false
description: "If true DAGs will be parsed before deploying to Astro."
pytest:
required: false
default: false
description: "if true custom pytests will be ran before deploying to Astro."
pytest-file:
required: false
default: tests/
description: "Specify custom pytest files to run with the pytest command."
force:
required: false
default: false
description: "If true your code will be force deployed to Astronomer. Mostly used to skip parse test on image deploys."
image-name:
required: false
default: no-custom-image
description: "Specify a custom built image to deploy to an Asto Deployment. To be used with 'deploy-type' set to 'image-and-dags' or 'infer'"
action:
required: false
default: deploy
description: "Specify what action you would like to take. Use this option to create or delete deployment previews. Specify either 'deploy', 'create-deployment-preview', 'delete-deployment-preview', or 'deploy-deployment-preview'. If using 'deploy' or 'deploy-deployment-preview' one should also specify 'deploy-type'."
deployment-name:
required: false
description: "The name of the Deployment you want to make preview from or are deploying to."
deployment-id:
required: false
description: "The id of the Deployment you to make a preview from or are deploying to."
workspace:
required: false
description: "Workspace id to select. Only required when `ASTRO_API_TOKEN` is given an organization token."
preview-name:
required: false
description: "Custom preview name. By default this is <branch-name>_<deployment-name>."
copy-connections:
required: false
default: true
description: "Copy connections from the original Deployment to the new deployment preview."
copy-airflow-variables:
required: false
default: true
description: "Copy Airflow variables from the original Deployment to the new deployment preview."
copy-pools:
required: false
default: true
description: "Copy pools from the original Deployment to the new deployment preview."
cli-version:
required: false
default: ""
description: "The desired Astro CLI version to use"
checkout:
required: false
default: true
description: "Whether to checkout the repo as the first step. Set this to false if you want to modify repo contents before invoking the action"
description:
required: false
description: >
A description to set for deploying to Astro. This is equivalent to running `astro deploy --description "..."` with the Astro CLI.
The description is visible in the Deploy History tab in your Astro Deployment, and can be helpful to explain what triggered a deploy.
For example, to display the most recent commit that resulted in an Astro deploy, you could configure
`description: "Deployed from commit ..."` with the value of `github.event.after`.
This would display e.g. "Deployed from commit da39a3ee5e6b4b0d3255bfef95601890afd80709".
Reference: https://docs.github.com/en/webhooks/webhook-events-and-payloads#push.
deploy-image:
required: false
default: false
description: "If true image and DAGs will deploy. NOTE: This option is deprecated and will be removed in a future release. Use `deploy-type: image-and-dags` instead."
deploy-type:
required: false
default: "infer"
description: "Specify the type of deploy you would like to do. Use this option to deploy only DAGs or the image or DBT project. Specify either 'infer', 'dags-only', 'image-and-dags', or 'dbt'. 'infer' option would infer between DAG only deploy and image and DAG deploy based on updated files."
build-secrets:
required: false
description: "Mimics docker build --secret flag. See https://docs.docker.com/build/building/secrets/ for more information. Example input 'id=mysecret,src=secrets.txt'"
mount-path:
required: false
default: ""
description: "Path to mount dbt project in Airflow, for reference by DAGs. Default /usr/local/airflow/dbt/{dbt project name}"
checkout-submodules:
required: false
default: false
description: "Whether to checkout submodules when cloning the repository: `false` to disable (default), `true` to checkout submodules or `recursive` to recursively checkout submodules. Works only when `checkout` is set to `true`."
outputs:
preview-id:
description: "The ID of the created deployment preview. Only works when action=create-deployment-preview"
value: ${{ steps.deployment-preview.outputs.FINAL_DEPLOYMENT_ID }}
runs:
using: "composite"
steps:
- name: checkout repo
uses: actions/checkout@v4
if: inputs.checkout == 'true'
with:
fetch-depth: 0 # Fetch all history
ref: ${{ github.event.after }}
clean: false
submodules: ${{ inputs.checkout-submodules }}
- name: Warn about deprecated deploy-image option
if: inputs.deploy-image == true
shell: bash
run: |
echo "The 'deploy-image' option is deprecated and will be removed in 1.0 release. Use 'deploy-type: image-and-dags' instead."
- name: Install Astro CLI
run: |
echo ::group::Install Astro CLI
CLI_VERSION=${{ inputs.cli-version }}
# if Astro CLI is pre-installed, fetch it's version
if command -v astro &> /dev/null; then
# "astro version" commands returns the CLI version, its output is of the form: "Astro CLI Version: 1.29.0"
CLI_VERSION=$(astro version | awk '{print $4}')
fi
# Check if the Astro CLI version is less than 1.28.1 for dbt-deploy
if [[ "${{ inputs.deploy-type }}" == "dbt" && $CLI_VERSION != "" ]]; then
#install semver to compare versions
npm install -g semver
REQUIRED_VERSION="1.28.1"
CURRENT_VERSION=$(astro version | awk '{print $4}')
if ! semver -r ">${REQUIRED_VERSION}" "${CURRENT_VERSION}"; then
echo "DBT Deploy requires Astro CLI version $REQUIRED_VERSION or higher"
exit 1
fi
fi
# skip Astro CLI installation if already installed
if command -v astro &> /dev/null; then
echo "Astro CLI is already installed"
exit 0
fi
# check if CLI_VERSION does not starts with "v", then add "v" to it
if [[ $CLI_VERSION != "" && $CLI_VERSION != v* ]]; then
CLI_VERSION=v$CLI_VERSION
fi
if [[ $CLI_VERSION == "" ]]; then
curl -sSL https://install.astronomer.io | sudo bash -s
else
curl -sSL https://install.astronomer.io | sudo bash -s -- $CLI_VERSION
fi
echo ::endgroup::
shell: bash
- name: Determine Deploy Deployment
run: |
echo ::group::Determine Deploy Deployment
# validate action input
if [[ ${{ inputs.action }} != create-deployment-preview && ${{ inputs.action }} != delete-deployment-preview && ${{ inputs.action }} != deploy-deployment-preview && ${{ inputs.action }} != deploy ]]; then
echo ERROR: you specified an improper action input. Action must be deploy, deploy-deployment-preview, create-deployment-preview, or delete-deployment-preview.
exit 1 # terminate and indicate error
fi
# Select workspace if specified
if [[ "${{ inputs.workspace }}" != "" ]]; then
astro workspace switch ${{ inputs.workspace }}
fi
# error if both deployment name and id are used
if [[ "${{ inputs.deployment-name }}" != "" && "${{ inputs.deployment-id }}" != "" ]]; then
echo ERROR: cannot specify both a Deployment ID and Name
exit 1 # terminate and indicate error
fi
# figure out deployment id
if [[ "${{ inputs.deployment-name }}" != "" ]]; then
# get deployment-id
DEPLOYMENT_ID="$(astro deployment inspect --clean-output -n "${{ inputs.deployment-name }}" --key metadata.deployment_id)"
fi
if [[ "${{ inputs.deployment-id }}" != "" ]]; then
DEPLOYMENT_ID="${{ inputs.deployment-id }}"
fi
# create deployment preview if action is create-deployment-preview
if [[ ${{ inputs.action }} == create-deployment-preview ]]; then
if [[ "${{ inputs.deployment-name }}" == "" && "${{ inputs.deployment-id }}" == "" ]]; then
echo ERROR: cannot create a deployment preview without specifying a deployment name or id
exit 1 # terminate and indicate error
fi
if [[ "${{ inputs.preview-name }}" != "" ]]; then
BRANCH_DEPLOYMENT_NAME="${{ inputs.preview-name }}"
else
# get branch name
DEPLOYMENT_NAME="$(astro deployment inspect $DEPLOYMENT_ID --clean-output --key configuration.name)"
if [[ ${GITHUB_HEAD_REF##*/} != "" ]]; then
BRANCH_DEPLOYMENT_NAME=${GITHUB_HEAD_REF##*/}_$DEPLOYMENT_NAME
else
branch_ref="${{ github.ref }}"
branch_name="${branch_ref##*/}"
BRANCH_DEPLOYMENT_NAME=${branch_name}_$DEPLOYMENT_NAME
fi
BRANCH_DEPLOYMENT_NAME="${BRANCH_DEPLOYMENT_NAME// /_}"
echo $BRANCH_DEPLOYMENT_NAME
fi
# Create template of deployment to be copied with
astro deployment inspect $DEPLOYMENT_ID --clean-output --template > deployment-preview-template.yaml # automatically creates deployment-preview-template.yaml file
# Add name to deployment template file
sed -i "s| name:.*| name: ${BRANCH_DEPLOYMENT_NAME}|g" deployment-preview-template.yaml
# Create new deployment preview based on the deployment template file
astro deployment create --deployment-file deployment-preview-template.yaml
# TODO: we need to add wait for deployment to be created, otherwise operation to copy airflow resources like connection is flaky if webserver is not up by then
# Get final Deployment ID
echo "FINAL_DEPLOYMENT_ID=$(astro deployment inspect --clean-output -n $BRANCH_DEPLOYMENT_NAME --key metadata.deployment_id)" >> $GITHUB_OUTPUT
# Get original Deployment ID
echo "ORIGINAL_DEPLOYMENT_ID=$DEPLOYMENT_ID" >> $GITHUB_OUTPUT
fi
# delete deployment preview and skip deploy if action is delete-deployment-preview
if [[ ${{ inputs.action }} == delete-deployment-preview ]]; then
if [[ "${{ inputs.deployment-name }}" == "" && "${{ inputs.deployment-id }}" == "" ]]; then
echo ERROR: cannot delete a deployment preview without specifying a deployment name or id
exit 1 # terminate and indicate error
fi
if [[ "${{ inputs.preview-name }}" != "" ]]; then
BRANCH_DEPLOYMENT_NAME="${{ inputs.preview-name }}"
else
DEPLOYMENT_NAME="$(astro deployment inspect $DEPLOYMENT_ID --clean-output --key configuration.name)"
BRANCH_DEPLOYMENT_NAME=${{ github.event.ref }}_$DEPLOYMENT_NAME
BRANCH_DEPLOYMENT_NAME="${BRANCH_DEPLOYMENT_NAME// /_}"
fi
# delete branch deployment
astro deployment delete -n $BRANCH_DEPLOYMENT_NAME -f
fi
# # deploy to deployment preview if action is deploy-deployment-preview
if [[ ${{ inputs.action }} == deploy-deployment-preview ]]; then
if [[ "${{ inputs.deployment-name }}" == "" && "${{ inputs.deployment-id }}" == "" ]]; then
echo ERROR: cannot deploy to a deployment preview without specifying a deployment name or id
exit 1 # terminate and indicate error
fi
if [[ "${{ inputs.preview-name }}" != "" ]]; then
BRANCH_DEPLOYMENT_NAME="${{ inputs.preview-name }}"
else
DEPLOYMENT_NAME="$(astro deployment inspect $DEPLOYMENT_ID --clean-output --key configuration.name)"
if [[ ${GITHUB_HEAD_REF##*/} != "" ]]; then
BRANCH_DEPLOYMENT_NAME=${GITHUB_HEAD_REF##*/}_$DEPLOYMENT_NAME
else
# BRANCH_DEPLOYMENT_NAME=${{ github.event.ref }}_$DEPLOYMENT_NAME
branch_ref="${{ github.ref }}"
branch_name="${branch_ref##*/}"
BRANCH_DEPLOYMENT_NAME=${branch_name}_$DEPLOYMENT_NAME
fi
BRANCH_DEPLOYMENT_NAME="${BRANCH_DEPLOYMENT_NAME// /_}"
fi
# Get Deployment ID
echo "FINAL_DEPLOYMENT_ID=$(astro deployment inspect --clean-output -n $BRANCH_DEPLOYMENT_NAME --key metadata.deployment_id)" >> $GITHUB_OUTPUT
fi
# if action is deploy or dbt deploy simply set final Deployment id to Deployment id to streamline the deployment id reference in rest of the workflow
if [[ ${{ inputs.action }} == deploy ]]; then
echo "FINAL_DEPLOYMENT_ID=$DEPLOYMENT_ID" >> $GITHUB_OUTPUT
fi
echo ::endgroup::
shell: bash
id: deployment-preview
- name: Determine if DAG Deploy is enabled
run: |
echo ::group::Determine if DAG Deploy is enabled
if [[ ${{ inputs.action }} != create-deployment-preview && ${{ inputs.action }} != delete-deployment-preview ]]; then
echo "DAG_DEPLOY_ENABLED=$(astro deployment inspect ${{steps.deployment-preview.outputs.FINAL_DEPLOYMENT_ID}} --clean-output --key configuration.dag_deploy_enabled)" >> $GITHUB_OUTPUT
else
echo "DAG_DEPLOY_ENABLED=false" >> $GITHUB_OUTPUT
fi
echo ::endgroup::
shell: bash
id: dag-deploy-enabled
- name: Get DBT Deploy Options
if: ${{ inputs.deploy-type == 'dbt' }}
run: |
echo ::group::Get DBT Deploy Options
cd ${{ inputs.root-folder }}
branch=$(echo "${GITHUB_REF#refs/heads/}")
echo "Branch pushed to: $branch"
git fetch origin $branch
files=$(git diff --name-only ${{ github.event.before }} ${{ github.event.after }})
echo "Files changed: $files"
DBT_DEPLOY=false
for file in $files; do
if [[ $file =~ ^"${{ inputs.root-folder }}".* ]]; then
echo $file is part of configured root folder, so would be triggering a dbt deploy
DBT_DEPLOY=true
fi
done
options=""
if [[ $dbt_deploy == 1 ]]; then
# Add mount path option
if [[ "${{ inputs.mount-path }}" != "" ]]; then
options="$options --mount-path=${{ inputs.mount-path }}"
fi
# Add description option
if [[ "${{ inputs.description }}" != "" ]]; then
options="$options --description '${{ inputs.description }}'"
fi
fi
echo "DBT_DEPLOY=$DBT_DEPLOY" >> $GITHUB_OUTPUT
echo "DBT_OPTIONS=$options" >> $GITHUB_OUTPUT
echo ::endgroup::
shell: bash
id: dbt-deploy-options
- name: Get Deploy Type
if: ${{ inputs.deploy-type == 'infer' || inputs.deploy-type == 'dags-only' || inputs.deploy-type == 'image-and-dags' }}
run: |
# infer based on files changed to deploy only dags or image and dags
echo ::group::Get Deploy Type
cd ${{ inputs.root-folder }}
branch=$(echo "${GITHUB_REF#refs/heads/}")
echo "Branch pushed to: $branch"
git fetch origin $branch
files=$(git diff --name-only ${{ github.event.before }} ${{ github.event.after }})
echo "files changed: $files"
DAGS_ONLY_DEPLOY=false
SKIP_IMAGE_OR_DAGS_DEPLOY=true
# This for loop checks for following cases:
# 1. If no file is part of the input root folder, then it skips deploy
# 2. If any file is not part of the dags folder, then it triggers a full image build
# 3. If all files are part of the dags folder and input root folder, then it triggers a DAG-only deploy
for file in $files; do
if [[ $file =~ ^"${{ inputs.root-folder }}".* ]]; then
echo $file is part of the input root folder
SKIP_IMAGE_OR_DAGS_DEPLOY=false
if [[ $file == *"dags/"* && ${{ inputs.deploy-type }} != 'image-and-dags' ]]; then
echo $file is part of dags folder, triggering a DAG-only deploy
DAGS_ONLY_DEPLOY=true
break
fi
fi
done
# Note: the order of these following checks is important to ensure that we skip/trigger deploy correctly in following cases:
# 1. When there is no change in the input root folder we should skip deploy, but not when it's deployment preview create action
# 2. When user has passed a custom image then we would need to deploy the image
# 3. When the action is deployment preview delete, then we should skip any form of deploy
if [[ $SKIP_IMAGE_OR_DAGS_DEPLOY == true ]]; then
# skip all deploy steps
DAGS_ONLY_DEPLOY=false
fi
# check if user has passed a custom image or the action has created a new deployment preview, then we would need to deploy the image
if [[ ${{ inputs.image-name }} != "no-custom-image" || ${{ steps.dag-deploy-enabled.outputs.DAG_DEPLOY_ENABLED }} == false || ${{ inputs.action }} == create-deployment-preview ]]; then
SKIP_IMAGE_OR_DAGS_DEPLOY=false
DAGS_ONLY_DEPLOY=false
fi
if [[ ${{ inputs.action }} == delete-deployment-preview ]]; then
# skip all deploy steps
SKIP_IMAGE_OR_DAGS_DEPLOY=true
DAGS_ONLY_DEPLOY=false
fi
echo "DAGS_ONLY_DEPLOY=$DAGS_ONLY_DEPLOY" >> $GITHUB_OUTPUT
echo "SKIP_IMAGE_OR_DAGS_DEPLOY=$SKIP_IMAGE_OR_DAGS_DEPLOY" >> $GITHUB_OUTPUT
echo ::endgroup::
shell: bash
id: deploy-type
# If only DAGs changed and dag deploys is enabled, do a DAG-only deploy
- name: Setup image or dags deploy options
if: ${{ inputs.deploy-type == 'infer' || inputs.deploy-type == 'dags-only' || inputs.deploy-type == 'image-and-dags' }}
run: |
echo ::group::Setup image or dags deploy options
options=""
# add parse option
if [[ ${{ inputs.parse }} == true ]]; then
options="--parse"
fi
# add pytest option
if [[ ${{ inputs.pytest }} == true ]]; then
options="$options --pytest --test ${{ inputs.pytest-file }}"
fi
# add custom image option
if [[ ${{ inputs.image-name }} != no-custom-image && inputs.deploy-type != "dags-only" ]]; then
options="$options --image-name ${{ inputs.image-name }}"
fi
# add force option
if [[ ${{ inputs.force }} == true ]]; then
options="$options --force"
fi
# Add description option
if [[ "${{ inputs.description }}" != '' ]]; then
options="$options --description '${{ inputs.description }}'"
fi
# Add build-secrets option
if [[ "${{ inputs.build-secrets }}" != '' ]]; then
options="$options --build-secrets '${{ inputs.build-secrets }}'"
fi
echo "OPTIONS=$options" >> $GITHUB_OUTPUT
echo ::endgroup::
shell: bash
id: deploy-options
- name: DAG Deploy to Astro
if: ${{ (inputs.deploy-type == 'dags-only' || inputs.deploy-type == 'infer') && steps.deploy-type.outputs.DAGS_ONLY_DEPLOY == 'true' }}
run: |
echo ::group::DAG Deploy to Astro
# Deploy only dags
cd ${{ inputs.root-folder }}
astro deploy ${{steps.deployment-preview.outputs.FINAL_DEPLOYMENT_ID}} --dags ${{steps.deploy-options.outputs.OPTIONS}}
echo ::endgroup::
shell: bash
# If any other files changed or dag deploys is disabled, deploy the entire Astro project
- name: Image and DAG Deploy to Astro
if: ${{ inputs.deploy-image == true || ( (inputs.deploy-type == 'image-and-dags' || inputs.deploy-type == 'infer') && steps.deploy-type.outputs.DAGS_ONLY_DEPLOY == 'false' && steps.deploy-type.outputs.SKIP_IMAGE_OR_DAGS_DEPLOY == 'false' ) }}
run: |
echo ::group::Image and DAG Deploy to Astro
# Deploy image and DAGs
cd ${{ inputs.root-folder }}
astro deploy ${{steps.deployment-preview.outputs.FINAL_DEPLOYMENT_ID}} ${{steps.deploy-options.outputs.OPTIONS}}
echo ::endgroup::
shell: bash
- name: DBT Deploy to Astro
if: ${{ inputs.deploy-type == 'dbt' && steps.dbt-deploy-options.outputs.DBT_DEPLOY == 'true' }}
run: |
echo ::group::DBT Deploy to Astro
cd ${{ inputs.root-folder }}
astro dbt deploy ${{steps.deployment-preview.outputs.FINAL_DEPLOYMENT_ID}} ${{steps.dbt-deploy-options.outputs.DBT_OPTIONS}}
echo ::endgroup::
shell: bash
- name: Copy Airflow Connections, Variables, and Pools
if: ${{ inputs.action == 'create-deployment-preview' }}
run: |
echo ::group::Copy Airflow Connections, Variables, and Pools
if [[ ${{ inputs.copy-connections }} == true ]]; then
astro deployment connection copy --source-id ${{steps.deployment-preview.outputs.ORIGINAL_DEPLOYMENT_ID}} --target-id ${{steps.deployment-preview.outputs.FINAL_DEPLOYMENT_ID}}
fi
if [[ ${{ inputs.copy-airflow-variables }} == true ]]; then
astro deployment airflow-variable copy --source-id ${{steps.deployment-preview.outputs.ORIGINAL_DEPLOYMENT_ID}} --target-id ${{steps.deployment-preview.outputs.FINAL_DEPLOYMENT_ID}}
fi
if [[ ${{ inputs.copy-pools }} == true ]]; then
astro deployment pool copy --source-id ${{steps.deployment-preview.outputs.ORIGINAL_DEPLOYMENT_ID}} --target-id ${{steps.deployment-preview.outputs.FINAL_DEPLOYMENT_ID}}
fi
echo ::endgroup::
shell: bash