Skip to content

Commit b21a46e

Browse files
authored
Convert to new split pipeline approach for CI/CD (#278)
* new split pipelines * specify channel * fix pip jq install * fixes and cleanup * add new lines * add docs and clean up naming * use shared image * rename * strip quotes from location * fix env var * remove succeeded condition * remove extra deploy yml * no pr trigger * remove unused template * remove unused pipeline * add more docs and add to bootstrap * linting * fix model package to show logs * Squashed commit of the following: commit 01af8da Author: j-so <jenns@microsoft.com> Date: Fri Jun 12 14:15:35 2020 -0700 fixed failure handling commit 1e6f906 Author: j-so <jenns@microsoft.com> Date: Fri Jun 12 14:03:09 2020 -0700 test failed conda dep commit a8030d7 Author: j-so <jenns@microsoft.com> Date: Fri Jun 12 13:55:00 2020 -0700 test package fail commit c7845aa Author: j-so <jenns@microsoft.com> Date: Fri Jun 12 13:46:27 2020 -0700 fail on deploy error' * Squashed commit of the following: commit 5af6eeb Author: j-so <jenns@microsoft.com> Date: Mon Jun 15 18:31:15 2020 -0700 fix bootstrap commit f61e103 Merge: 2796b40 08bb6f4 Author: j-so <jenns@microsoft.com> Date: Mon Jun 15 18:30:21 2020 -0700 Merge branch 'master' into jenns/splitpipeline_docfix commit 2796b40 Author: j-so <jenns@microsoft.com> Date: Mon Jun 15 18:30:00 2020 -0700 remove old pipeline commit 08bb6f4 Author: David Tesar <david.tesar@microsoft.com> Date: Mon Jun 15 14:09:12 2020 -0700 Simplify docs flow (#297) commit cd762ec Author: jotaylo <jotaylo@microsoft.com> Date: Mon Jun 15 12:28:23 2020 -0700 Move instruction to install AML extension to Azure Devops setup instructions (#298) * remove need for model build id * fix batch scoring * use model version for batch scoring * linting * Squashed commit of the following: commit 493ed3e Author: j-so <jenns@microsoft.com> Date: Mon Jun 22 16:42:07 2020 -0700 mark as output commit 1ca7a59 Author: j-so <jenns@microsoft.com> Date: Mon Jun 22 16:12:10 2020 -0700 fix import commit 743e301 Author: j-so <jenns@microsoft.com> Date: Mon Jun 22 15:59:43 2020 -0700 more fixes commit 44abcac Author: j-so <jenns@microsoft.com> Date: Mon Jun 22 15:50:49 2020 -0700 fix batch scoring * improve the docs * fix secret access * pass to cli task and impove naming
1 parent bcdac5c commit b21a46e

23 files changed

+456
-295
lines changed

.pipelines/diabetes_regression-batchscoring-ci.yml

+30-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,27 @@
11
# Continuous Integration (CI) pipeline that orchestrates the batch scoring of the diabetes_regression model.
22

3+
# Runtime parameters to select artifacts
4+
parameters:
5+
- name : artifactBuildId
6+
displayName: Model Train CI Build ID. Default is 'latest'.
7+
type: string
8+
default: latest
9+
10+
pr: none
11+
12+
# Trigger this pipeline on model-train pipeline completion
313
resources:
414
containers:
515
- container: mlops
616
image: mcr.microsoft.com/mlops/python:latest
7-
17+
pipelines:
18+
- pipeline: model-train-ci
19+
source: Model-Train-Register-CI # Name of the triggering pipeline
20+
trigger:
21+
branches:
22+
include:
23+
- master
824

9-
pr: none
1025
trigger:
1126
branches:
1227
include:
@@ -34,7 +49,13 @@ stages:
3449
timeoutInMinutes: 0
3550
steps:
3651
- template: code-quality-template.yml
52+
- template: diabetes_regression-get-model-id-artifact-template.yml
53+
parameters:
54+
projectId: '$(resources.pipeline.model-train-ci.projectID)'
55+
pipelineId: '$(resources.pipeline.model-train-ci.pipelineID)'
56+
artifactBuildId: ${{ parameters.artifactBuildId }}
3757
- task: AzureCLI@1
58+
displayName: "Publish Batch Scoring Pipeline"
3859
name: publish_batchscore
3960
inputs:
4061
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
@@ -45,20 +66,24 @@ stages:
4566
export SUBSCRIPTION_ID=$(az account show --query id -o tsv)
4667
# Invoke the Python building and publishing a training pipeline
4768
python -m ml_service.pipelines.diabetes_regression_build_parallel_batchscore_pipeline
48-
69+
env:
70+
SCORING_DATASTORE_ACCESS_KEY: $(SCORING_DATASTORE_ACCESS_KEY)
71+
4972
- job: "Run_Batch_Score_Pipeline"
5073
displayName: "Run Batch Scoring Pipeline"
51-
dependsOn: "Build_Batch_Scoring_Pipeline"
74+
dependsOn: ["Build_Batch_Scoring_Pipeline"]
5275
timeoutInMinutes: 240
5376
pool: server
5477
variables:
5578
pipeline_id: $[ dependencies.Build_Batch_Scoring_Pipeline.outputs['publish_batchscore.pipeline_id']]
79+
model_name: $[ dependencies.Build_Batch_Scoring_Pipeline.outputs['get_model.MODEL_NAME']]
80+
model_version: $[ dependencies.Build_Batch_Scoring_Pipeline.outputs['get_model.MODEL_VERSION']]
5681
steps:
5782
- task: ms-air-aiagility.vss-services-azureml.azureml-restApi-task.MLPublishedPipelineRestAPITask@0
5883
displayName: 'Invoke Batch Scoring pipeline'
5984
inputs:
6085
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
6186
PipelineId: '$(pipeline_id)'
6287
ExperimentName: '$(EXPERIMENT_NAME)'
63-
PipelineParameters: '"ParameterAssignments": {"model_name": "$(MODEL_NAME)"}'
88+
PipelineParameters: '"ParameterAssignments": {"model_name": "$(model_name)", "model_version": "$(model_version)"}'
6489

.pipelines/diabetes_regression-cd.yml

+161
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# Continuous Integration (CI) pipeline that orchestrates the deployment of the diabetes_regression model.
2+
3+
# Runtime parameters to select artifacts
4+
parameters:
5+
- name : artifactBuildId
6+
displayName: Model Train CI Build ID. Default is 'latest'.
7+
type: string
8+
default: latest
9+
10+
pr: none
11+
12+
# Trigger this pipeline on model-train pipeline completion
13+
trigger: none
14+
resources:
15+
containers:
16+
- container: mlops
17+
image: mcr.microsoft.com/mlops/python:latest
18+
pipelines:
19+
- pipeline: model-train-ci
20+
source: Model-Train-Register-CI # Name of the triggering pipeline
21+
trigger:
22+
branches:
23+
include:
24+
- master
25+
26+
variables:
27+
- template: diabetes_regression-variables-template.yml
28+
- group: devopsforai-aml-vg
29+
30+
stages:
31+
- stage: 'Deploy_ACI'
32+
displayName: 'Deploy to ACI'
33+
condition: variables['ACI_DEPLOYMENT_NAME']
34+
jobs:
35+
- job: "Deploy_ACI"
36+
displayName: "Deploy to ACI"
37+
container: mlops
38+
timeoutInMinutes: 0
39+
steps:
40+
- download: none
41+
- template: diabetes_regression-get-model-id-artifact-template.yml
42+
parameters:
43+
projectId: '$(resources.pipeline.model-train-ci.projectID)'
44+
pipelineId: '$(resources.pipeline.model-train-ci.pipelineID)'
45+
artifactBuildId: ${{ parameters.artifactBuildId }}
46+
- task: AzureCLI@1
47+
displayName: 'Install AzureML CLI'
48+
inputs:
49+
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
50+
scriptLocation: inlineScript
51+
workingDirectory: $(Build.SourcesDirectory)
52+
inlineScript: 'az extension add -n azure-cli-ml'
53+
- task: AzureCLI@1
54+
displayName: "Deploy to ACI (CLI)"
55+
inputs:
56+
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
57+
scriptLocation: inlineScript
58+
workingDirectory: $(Build.SourcesDirectory)/$(SOURCES_DIR_TRAIN)/scoring
59+
inlineScript: |
60+
set -e # fail on error
61+
62+
az ml model deploy --name $(ACI_DEPLOYMENT_NAME) --model '$(MODEL_NAME):$(MODEL_VERSION)' \
63+
--ic inference_config.yml \
64+
--dc deployment_config_aci.yml \
65+
-g $(RESOURCE_GROUP) --workspace-name $(WORKSPACE_NAME) \
66+
--overwrite -v
67+
- task: AzureCLI@1
68+
displayName: 'Smoke test'
69+
inputs:
70+
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
71+
scriptLocation: inlineScript
72+
inlineScript: |
73+
set -e # fail on error
74+
export SUBSCRIPTION_ID=$(az account show --query id -o tsv)
75+
python -m ml_service.util.smoke_test_scoring_service --type ACI --service "$(ACI_DEPLOYMENT_NAME)"
76+
77+
- stage: 'Deploy_AKS'
78+
displayName: 'Deploy to AKS'
79+
dependsOn: Deploy_ACI
80+
condition: and(succeeded(), variables['AKS_DEPLOYMENT_NAME'])
81+
jobs:
82+
- job: "Deploy_AKS"
83+
displayName: "Deploy to AKS"
84+
container: mlops
85+
timeoutInMinutes: 0
86+
steps:
87+
- template: diabetes_regression-get-model-id-artifact-template.yml
88+
parameters:
89+
projectId: '$(resources.pipeline.model-train-ci.projectID)'
90+
pipelineId: '$(resources.pipeline.model-train-ci.pipelineID)'
91+
artifactBuildId: ${{ parameters.artifactBuildId }}
92+
- task: AzureCLI@1
93+
displayName: 'Install AzureML CLI'
94+
inputs:
95+
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
96+
scriptLocation: inlineScript
97+
workingDirectory: $(Build.SourcesDirectory)
98+
inlineScript: 'az extension add -n azure-cli-ml'
99+
- task: AzureCLI@1
100+
displayName: "Deploy to AKS (CLI)"
101+
inputs:
102+
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
103+
scriptLocation: inlineScript
104+
workingDirectory: $(Build.SourcesDirectory)/$(SOURCES_DIR_TRAIN)/scoring
105+
inlineScript: |
106+
set -e # fail on error
107+
108+
az ml model deploy --name $(AKS_DEPLOYMENT_NAME) --model '$(MODEL_NAME):$(MODEL_VERSION)' \
109+
--compute-target $(AKS_COMPUTE_NAME) \
110+
--ic inference_config.yml \
111+
--dc deployment_config_aks.yml \
112+
-g $(RESOURCE_GROUP) --workspace-name $(WORKSPACE_NAME) \
113+
--overwrite -v
114+
- task: AzureCLI@1
115+
displayName: 'Smoke test'
116+
inputs:
117+
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
118+
scriptLocation: inlineScript
119+
inlineScript: |
120+
set -e # fail on error
121+
export SUBSCRIPTION_ID=$(az account show --query id -o tsv)
122+
python -m ml_service.util.smoke_test_scoring_service --type AKS --service "$(AKS_DEPLOYMENT_NAME)"
123+
124+
- stage: 'Deploy_Webapp'
125+
displayName: 'Deploy to Webapp'
126+
condition: variables['WEBAPP_DEPLOYMENT_NAME']
127+
jobs:
128+
- job: "Deploy_Webapp"
129+
displayName: "Package and deploy model"
130+
container: mlops
131+
timeoutInMinutes: 0
132+
steps:
133+
- template: diabetes_regression-get-model-id-artifact-template.yml
134+
parameters:
135+
projectId: '$(resources.pipeline.model-train-ci.projectID)'
136+
pipelineId: '$(resources.pipeline.model-train-ci.pipelineID)'
137+
artifactBuildId: ${{ parameters.artifactBuildId }}
138+
- template: diabetes_regression-package-model-template.yml
139+
parameters:
140+
modelId: $(MODEL_NAME):$(MODEL_VERSION)
141+
scoringScriptPath: '$(Build.SourcesDirectory)/$(SOURCES_DIR_TRAIN)/scoring/score.py'
142+
condaFilePath: '$(Build.SourcesDirectory)/$(SOURCES_DIR_TRAIN)/conda_dependencies.yml'
143+
- script: echo $(IMAGE_LOCATION) >image_location.txt
144+
displayName: "Write image location file"
145+
- task: AzureWebAppContainer@1
146+
name: WebAppDeploy
147+
displayName: 'Azure Web App on Container Deploy'
148+
inputs:
149+
azureSubscription: '$(AZURE_RM_SVC_CONNECTION)'
150+
appName: '$(WEBAPP_DEPLOYMENT_NAME)'
151+
resourceGroupName: '$(RESOURCE_GROUP)'
152+
imageName: '$(IMAGE_LOCATION)'
153+
- task: AzureCLI@1
154+
displayName: 'Smoke test'
155+
inputs:
156+
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
157+
scriptLocation: inlineScript
158+
inlineScript: |
159+
set -e # fail on error
160+
export SUBSCRIPTION_ID=$(az account show --query id -o tsv)
161+
python -m ml_service.util.smoke_test_scoring_service --type Webapp --service "$(WebAppDeploy.AppServiceApplicationUrl)/score"

.pipelines/diabetes_regression-ci-image.yml

+5-10
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,9 @@ variables:
3030
value: 'scoring/scoreB.py'
3131

3232
steps:
33-
- task: AzureCLI@1
34-
inputs:
35-
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
36-
scriptLocation: inlineScript
37-
workingDirectory: $(Build.SourcesDirectory)
38-
inlineScript: |
39-
set -e
40-
export SUBSCRIPTION_ID=$(az account show --query id -o tsv)
41-
python3 -m ml_service.util.create_scoring_image
42-
displayName: 'Create Scoring Image'
33+
- template: diabetes_regression-package-model-template.yml
34+
parameters:
35+
modelId: $(MODEL_NAME):$(MODEL_VERSION)
36+
scoringScriptPath: '$(Build.SourcesDirectory)/$(SOURCES_DIR_TRAIN)/$(SCORE_SCRIPT)'
37+
condaFilePath: '$(Build.SourcesDirectory)/$(SOURCES_DIR_TRAIN)/conda_dependencies.yml'
4338

.pipelines/diabetes_regression-ci.yml

+5-114
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Continuous Integration (CI) pipeline that orchestrates the training, evaluation, registration, deployment, and testing of the diabetes_regression model.
1+
# Continuous Integration (CI) pipeline that orchestrates the training, evaluation, and registration of the diabetes_regression model.
22

33
resources:
44
containers:
@@ -27,7 +27,6 @@ pool:
2727
stages:
2828
- stage: 'Model_CI'
2929
displayName: 'Model CI'
30-
condition: not(variables['MODEL_BUILD_ID'])
3130
jobs:
3231
- job: "Model_CI_Pipeline"
3332
displayName: "Model CI Pipeline"
@@ -48,8 +47,8 @@ stages:
4847
displayName: 'Publish Azure Machine Learning Pipeline'
4948

5049
- stage: 'Trigger_AML_Pipeline'
51-
displayName: 'Train model'
52-
condition: and(succeeded(), not(variables['MODEL_BUILD_ID']))
50+
displayName: 'Train and evaluate model'
51+
condition: succeeded()
5352
variables:
5453
BUILD_URI: '$(SYSTEM.COLLECTIONURI)$(SYSTEM.TEAMPROJECT)/_build/results?buildId=$(BUILD.BUILDID)'
5554
jobs:
@@ -91,116 +90,8 @@ stages:
9190
- job: "Training_Run_Report"
9291
dependsOn: "Run_ML_Pipeline"
9392
condition: always()
94-
displayName: "Determine if evaluation succeeded and new model is registered"
93+
displayName: "Publish artifact if new model was registered"
9594
container: mlops
9695
timeoutInMinutes: 0
9796
steps:
98-
- template: diabetes_regression-get-model-version-template.yml
99-
100-
- stage: 'Deploy_ACI'
101-
displayName: 'Deploy to ACI'
102-
dependsOn: Trigger_AML_Pipeline
103-
condition: and(or(succeeded(), variables['MODEL_BUILD_ID']), variables['ACI_DEPLOYMENT_NAME'])
104-
jobs:
105-
- job: "Deploy_ACI"
106-
displayName: "Deploy to ACI"
107-
container: mlops
108-
timeoutInMinutes: 0
109-
steps:
110-
- template: diabetes_regression-get-model-version-template.yml
111-
- task: ms-air-aiagility.vss-services-azureml.azureml-model-deploy-task.AMLModelDeploy@0
112-
displayName: 'Azure ML Model Deploy'
113-
inputs:
114-
azureSubscription: $(WORKSPACE_SVC_CONNECTION)
115-
modelSourceType: manualSpec
116-
modelName: '$(MODEL_NAME)'
117-
modelVersion: $(MODEL_VERSION)
118-
inferencePath: '$(Build.SourcesDirectory)/$(SOURCES_DIR_TRAIN)/scoring/inference_config.yml'
119-
deploymentTarget: ACI
120-
deploymentName: $(ACI_DEPLOYMENT_NAME)
121-
deployConfig: '$(Build.SourcesDirectory)/$(SOURCES_DIR_TRAIN)/scoring/deployment_config_aci.yml'
122-
overwriteExistingDeployment: true
123-
- task: AzureCLI@1
124-
displayName: 'Smoke test'
125-
inputs:
126-
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
127-
scriptLocation: inlineScript
128-
inlineScript: |
129-
set -e # fail on error
130-
export SUBSCRIPTION_ID=$(az account show --query id -o tsv)
131-
python -m ml_service.util.smoke_test_scoring_service --type ACI --service "$(ACI_DEPLOYMENT_NAME)"
132-
133-
- stage: 'Deploy_AKS'
134-
displayName: 'Deploy to AKS'
135-
dependsOn: Deploy_ACI
136-
condition: and(succeeded(), variables['AKS_DEPLOYMENT_NAME'])
137-
jobs:
138-
- job: "Deploy_AKS"
139-
displayName: "Deploy to AKS"
140-
container: mlops
141-
timeoutInMinutes: 0
142-
steps:
143-
- template: diabetes_regression-get-model-version-template.yml
144-
- task: ms-air-aiagility.vss-services-azureml.azureml-model-deploy-task.AMLModelDeploy@0
145-
displayName: 'Azure ML Model Deploy'
146-
inputs:
147-
azureSubscription: $(WORKSPACE_SVC_CONNECTION)
148-
modelSourceType: manualSpec
149-
modelName: '$(MODEL_NAME)'
150-
modelVersion: $(MODEL_VERSION)
151-
inferencePath: '$(Build.SourcesDirectory)/$(SOURCES_DIR_TRAIN)/scoring/inference_config.yml'
152-
deploymentTarget: AKS
153-
aksCluster: $(AKS_COMPUTE_NAME)
154-
deploymentName: $(AKS_DEPLOYMENT_NAME)
155-
deployConfig: '$(Build.SourcesDirectory)/$(SOURCES_DIR_TRAIN)/scoring/deployment_config_aks.yml'
156-
overwriteExistingDeployment: true
157-
- task: AzureCLI@1
158-
displayName: 'Smoke test'
159-
inputs:
160-
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
161-
scriptLocation: inlineScript
162-
inlineScript: |
163-
set -e # fail on error
164-
export SUBSCRIPTION_ID=$(az account show --query id -o tsv)
165-
python -m ml_service.util.smoke_test_scoring_service --type AKS --service "$(AKS_DEPLOYMENT_NAME)"
166-
167-
- stage: 'Deploy_Webapp'
168-
displayName: 'Deploy to Webapp'
169-
dependsOn: Trigger_AML_Pipeline
170-
condition: and(or(succeeded(), variables['MODEL_BUILD_ID']), variables['WEBAPP_DEPLOYMENT_NAME'])
171-
jobs:
172-
- job: "Deploy_Webapp"
173-
displayName: "Deploy to Webapp"
174-
container: mlops
175-
timeoutInMinutes: 0
176-
steps:
177-
- template: diabetes_regression-get-model-version-template.yml
178-
- task: AzureCLI@1
179-
displayName: 'Create scoring image and set IMAGE_LOCATION variable'
180-
inputs:
181-
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
182-
scriptLocation: inlineScript
183-
inlineScript: |
184-
set -e # fail on error
185-
export SUBSCRIPTION_ID=$(az account show --query id -o tsv)
186-
python -m ml_service.util.create_scoring_image --output_image_location_file image_location.txt
187-
# Output image location to Azure DevOps job
188-
IMAGE_LOCATION="$(cat image_location.txt)"
189-
echo "##vso[task.setvariable variable=IMAGE_LOCATION]$IMAGE_LOCATION"
190-
- task: AzureWebAppContainer@1
191-
name: WebAppDeploy
192-
displayName: 'Azure Web App on Container Deploy'
193-
inputs:
194-
azureSubscription: '$(AZURE_RM_SVC_CONNECTION)'
195-
appName: '$(WEBAPP_DEPLOYMENT_NAME)'
196-
resourceGroupName: '$(RESOURCE_GROUP)'
197-
imageName: '$(IMAGE_LOCATION)'
198-
- task: AzureCLI@1
199-
displayName: 'Smoke test'
200-
inputs:
201-
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
202-
scriptLocation: inlineScript
203-
inlineScript: |
204-
set -e # fail on error
205-
export SUBSCRIPTION_ID=$(az account show --query id -o tsv)
206-
python -m ml_service.util.smoke_test_scoring_service --type Webapp --service "$(WebAppDeploy.AppServiceApplicationUrl)/score"
97+
- template: diabetes_regression-publish-model-artifact-template.yml

0 commit comments

Comments
 (0)