-
Notifications
You must be signed in to change notification settings - Fork 252
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for Jenkins declarative pipelines (#127)
--------- Co-authored-by: mohanajuhi166 <mohanab@microsoft.com> Co-authored-by: mohanajuhi166 <mohanajuhi166@gmail.com> Co-authored-by: Hayward van Biljon <hvanbiljon@microsoft.com>
- Loading branch information
1 parent
8e48fa2
commit b97f867
Showing
29 changed files
with
1,587 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
@Library('shared-library') _ | ||
pipeline { | ||
agent any | ||
|
||
parameters { | ||
string(name: 'env_name', defaultValue: "dev", description: 'env stage e.g. dev, test, prod') | ||
string(name: 'flow_type', defaultValue: 'named_entity_recognition', description: 'flow type to be registered and deployed') | ||
string(name: 'model_version', description: 'flow version in registry to be deployed') | ||
string(name: 'run_id', description: 'run id of the flow to be deployed') | ||
} | ||
|
||
// Install requirements and provision AML Managed Online Endpoint | ||
stages { | ||
stage('Provision AML Online Endpoint') { | ||
steps { | ||
installRequirements('execute_job_requirements') | ||
withCredentials([azureServicePrincipal('AZURE_CREDENTIALS')]) { | ||
withPythonEnv('/usr/bin/python3.9') { | ||
sh """ | ||
python -m llmops.common.deployment.provision_endpoint \ | ||
--subscription_id $AZURE_SUBSCRIPTION_ID \ | ||
--build_id $run_id \ | ||
--output_file "endpoint_principal.txt" \ | ||
--env_name $env_name \ | ||
--flow_to_execute $flow_type | ||
""" | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Assign Azure resource permissions to endpoint principal | ||
stage('Assign Azure resource permissions') { | ||
steps { | ||
azureLogin() | ||
withCredentials([azureServicePrincipal('AZURE_CREDENTIALS')]) { | ||
sh ''' | ||
endpoint_principal=$(cat endpoint_principal.txt) | ||
echo $endpoint_principal | ||
file_path="./$flow_type/llmops_config.json" | ||
echo $file_path | ||
env_type="$env_name" | ||
|
||
selected_object=\$(jq ".envs[] | select(.ENV_NAME == \"$env_type\")" "\$file_path") | ||
echo $selected_object | ||
|
||
key_vault_name=$(echo "$selected_object" | jq -r ".KEYVAULT_NAME") | ||
resource_group_name=$(echo "$selected_object" | jq -r ".RESOURCE_GROUP_NAME") | ||
workspace_name=$(echo "$selected_object" | jq -r ".WORKSPACE_NAME") | ||
|
||
az role assignment create --assignee $endpoint_principal --role "AzureML Data Scientist" --scope "/subscriptions/$AZURE_SUBSCRIPTION_ID/resourcegroups/$resource_group_name/providers/Microsoft.MachineLearningServices/workspaces/$workspace_name" | ||
|
||
auth_type=$(az keyvault show -n $key_vault_name -g $resource_group_name --query "properties.enableRbacAuthorization") | ||
if [[ -z "$auth_type" ]]; then | ||
echo "assigning RBAC permission" | ||
az role assignment create --assignee $endpoint_principal --role "Key Vault Reader" --scope "/subscriptions/$AZURE_SUBSCRIPTION_ID/resourcegroups/$resource_group_name/providers/Microsoft.KeyVault/vaults/$key_vault_name" | ||
else | ||
echo "assigning policy permission" | ||
az keyvault set-policy --name $key_vault_name --resource-group $resource_group_name --object-id $endpoint_principal --secret-permissions get list | ||
fi | ||
''' | ||
} | ||
} | ||
} | ||
|
||
// Provision AML Online Deployment for given model version and run id | ||
stage('Provision AML Online Deployment') { | ||
steps { | ||
withCredentials([azureServicePrincipal('AZURE_CREDENTIALS')]) { | ||
withPythonEnv('/usr/bin/python3.9') { | ||
sh """ | ||
python -m llmops.common.deployment.provision_deployment \ | ||
--subscription_id $AZURE_SUBSCRIPTION_ID \ | ||
--model_version $model_version \ | ||
--build_id $run_id \ | ||
--env_name $env_name \ | ||
--flow_to_execute $flow_type | ||
""" | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Test Online AML Deployment | ||
stage('Test AML Deployment') { | ||
steps { | ||
withCredentials([azureServicePrincipal('AZURE_CREDENTIALS')]) { | ||
withPythonEnv('/usr/bin/python3.9') { | ||
sh """ | ||
python -m llmops.common.deployment.test_model_on_aml \ | ||
--subscription_id $AZURE_SUBSCRIPTION_ID \ | ||
--env_name $env_name \ | ||
--flow_to_execute $flow_type | ||
""" | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
@Library('shared-library') _ | ||
pipeline { | ||
agent any | ||
|
||
options { | ||
// This is required if you want to clean before build | ||
skipDefaultCheckout(true) | ||
} | ||
|
||
parameters { | ||
string(name: 'flow_type', defaultValue: 'named_entity_recognition', description: 'The flow use-case to validate') | ||
} | ||
|
||
stages { | ||
stage('Checkout') { | ||
steps { | ||
cleanWs() | ||
checkout scm | ||
} | ||
} | ||
|
||
// Load dependencies, login to Azure and load subscription details | ||
stage('Load Dependencies') { | ||
steps { | ||
installRequirements('build_validation_requirements') | ||
sh 'az version' | ||
} | ||
} | ||
|
||
stage('Azure Login') { | ||
steps { | ||
azureLogin() | ||
} | ||
} | ||
|
||
stage('Load Azure Subscription Details') { | ||
steps { | ||
withCredentials([azureServicePrincipal('AZURE_CREDENTIALS')]) { | ||
sh ''' | ||
export subscriptionId=$(az account show --query id -o tsv) | ||
echo "SUBSCRIPTION_ID=$AZURE_SUBSCRIPTION_ID" | ||
''' | ||
} | ||
} | ||
} | ||
|
||
// Execute unit tests and publish results | ||
stage('Execute Unit Tests') { | ||
steps { | ||
withPythonEnv('/usr/bin/python3.9') { | ||
sh "pytest ${params.flow_type}/tests --junitxml=junit/test-results.xml --cov=. --cov-report=xml" | ||
} | ||
} | ||
} | ||
|
||
stage('Publish Unit Test Results') { | ||
steps { | ||
archiveArtifacts artifacts: '**/test-*.xml', fingerprint: true | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
@Library('shared-library') _ | ||
pipeline { | ||
agent any | ||
|
||
parameters { | ||
string(name: 'env_name', defaultValue: "dev", description: 'env stage e.g. dev, test, prod') | ||
string(name: 'flow_type', defaultValue: 'named_entity_recognition', description: 'flow type to be registered and deployed') | ||
string(name: 'model_version', description: 'flow version in registry to be deployed') | ||
string(name: 'run_id', description: 'run id of the flow to be deployed') | ||
} | ||
|
||
// Install requirements and provision Kubernetes Online Endpoint | ||
stages { | ||
stage('Provision Kubernetes Online Endpoint') { | ||
steps { | ||
installRequirements('execute_job_requirements') | ||
withCredentials([azureServicePrincipal('AZURE_CREDENTIALS')]) { | ||
withPythonEnv('/usr/bin/python3.9') { | ||
sh """ | ||
python -m llmops.common.deployment.kubernetes_endpoint \ | ||
--subscription_id $AZURE_SUBSCRIPTION_ID \ | ||
--build_id $run_id \ | ||
--output_file "endpoint_principal.txt" \ | ||
--env_name $env_name \ | ||
--flow_to_execute $flow_type | ||
""" | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Assign Azure resource permissions to endpoint principal | ||
stage('Assign Azure resource permissions') { | ||
steps { | ||
withCredentials([azureServicePrincipal('AZURE_CREDENTIALS')]) { | ||
sh ''' | ||
endpoint_principal=$(cat endpoint_principal.txt) | ||
echo $endpoint_principal | ||
file_path="./$flow_type/llmops_config.json" | ||
echo $file_path | ||
env_type="$env_name" | ||
|
||
selected_object=\$(jq ".envs[] | select(.ENV_NAME == \"$env_type\")" "\$file_path") | ||
echo $selected_object | ||
|
||
key_vault_name=$(echo "$selected_object" | jq -r ".KEYVAULT_NAME") | ||
resource_group_name=$(echo "$selected_object" | jq -r ".RESOURCE_GROUP_NAME") | ||
workspace_name=$(echo "$selected_object" | jq -r ".WORKSPACE_NAME") | ||
|
||
az role assignment create --assignee $endpoint_principal --role "AzureML Data Scientist" --scope "/subscriptions/$AZURE_SUBSCRIPTION_ID/resourcegroups/$resource_group_name/providers/Microsoft.MachineLearningServices/workspaces/$workspace_name" | ||
|
||
auth_type=$(az keyvault show -n $key_vault_name -g $resource_group_name --query "properties.enableRbacAuthorization") | ||
if [[ -z "$auth_type" ]]; then | ||
echo "assigning RBAC permission" | ||
az role assignment create --assignee $endpoint_principal --role "Key Vault Reader" --scope "/subscriptions/$AZURE_SUBSCRIPTION_ID/resourcegroups/$resource_group_name/providers/Microsoft.KeyVault/vaults/$key_vault_name" | ||
else | ||
echo "assigning policy permission" | ||
az keyvault set-policy --name $key_vault_name --resource-group $resource_group_name --object-id $endpoint_principal --secret-permissions get list | ||
fi | ||
''' | ||
} | ||
} | ||
} | ||
|
||
// Provision Kubernetes Online Deployment | ||
stage('Provision Kubernetes Online Deployment') { | ||
steps { | ||
withCredentials([azureServicePrincipal('AZURE_CREDENTIALS')]) { | ||
withPythonEnv('/usr/bin/python3.9') { | ||
sh """ | ||
python -m llmops.common.deployment.kubernetes_deployment \ | ||
--subscription_id $AZURE_SUBSCRIPTION_ID \ | ||
--model_version $model_version \ | ||
--build_id $run_id \ | ||
--env_name $env_name \ | ||
--flow_to_execute $flow_type | ||
""" | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Test Kubernetes Deployment | ||
stage('Test Kubernetes Deployment') { | ||
steps { | ||
withCredentials([azureServicePrincipal('AZURE_CREDENTIALS')]) { | ||
withPythonEnv('/usr/bin/python3.9') { | ||
sh """ | ||
python -m llmops.common.deployment.test_model_on_kubernetes \ | ||
--subscription_id $AZURE_SUBSCRIPTION_ID \ | ||
--env_name $env_name \ | ||
--flow_to_execute $flow_type | ||
""" | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
@Library('shared-library') _ | ||
pipeline { | ||
agent any | ||
parameters { | ||
string(name: 'flow_to_execute', defaultValue: 'named_entity_recognition', description: 'The flow use-case to execute') | ||
string(name: 'deploy_environment', defaultValue: 'dev', description: 'Execution Environment') | ||
} | ||
|
||
environment { | ||
dev_connections = credentials('COMMON_DEV_CONNECTIONS') | ||
registry_details = credentials('DOCKER_IMAGE_REGISTRY') | ||
} | ||
|
||
// Install requirements for job execution and build validation and create local promptflow connections | ||
stages { | ||
stage('Create local promptflow connections') { | ||
steps { | ||
installRequirements('execute_job_requirements') | ||
installRequirements('build_validation_requirements') | ||
withCredentials([azureServicePrincipal('AZURE_CREDENTIALS')]) { | ||
withPythonEnv('/usr/bin/python3.9') { | ||
sh ''' | ||
python -m llmops.common.prompt_local_connections \\ | ||
--flow_to_execute ${flow_to_execute} \\ | ||
--env_name ${deploy_environment} \\ | ||
--connection_details "$dev_connections" | ||
''' | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Create Docker image and push to Azure Container Registry | ||
stage('Create Docker Image') { | ||
steps { | ||
installRequirements('build_validation_requirements') | ||
withCredentials([string(credentialsId: 'DOCKER_IMAGE_REGISTRY', variable: 'registry_details'), | ||
string(credentialsId: 'COMMON_DEV_CONNECTIONS', variable: 'connection_details')]) { | ||
withPythonEnv('/usr/bin/python3.9') { | ||
sh """ | ||
# Your Docker image creation command here | ||
echo "build no script:" | ||
echo ${BUILD_NUMBER} | ||
#!/bin/bash | ||
./llmops/common/scripts/gen_docker_image.sh --flow_to_execute $flow_to_execute --deploy_environment $deploy_environment --build_id ${BUILD_NUMBER} --REGISTRY_DETAILS '${registry_details}' --CONNECTION_DETAILS '${connection_details}' | ||
""" | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Deploy Docker image to Azure Webapp | ||
stage('Create Webapp') { | ||
steps { | ||
withCredentials([string(credentialsId: 'COMMON_DEV_CONNECTIONS', variable: 'connection_details')]) { | ||
sh """ | ||
/bin/bash ./llmops/common/scripts/az_webapp_deploy.sh --flow_to_execute $flow_to_execute --deploy_environment $deploy_environment --build_id ${BUILD_NUMBER} --CONNECTION_DETAILS '${connection_details}' | ||
""" | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.