|
1 | | -name: 🅰️ Azure Devops pipeline trigger |
2 | | -description: 🅰️ Azure Devops pipeline trigger |
3 | | - |
| 1 | +# action.yml |
| 2 | +name: 'Azure DevOps Pipeline Trigger' |
| 3 | +description: 'Triggers an Azure DevOps pipeline with template parameters' |
4 | 4 | inputs: |
5 | 5 | enable_azure_devops_step: |
6 | | - description: Are azure devops triggers enabled? |
7 | | - default: "false" |
| 6 | + description: 'Enable or disable the Azure DevOps step' |
| 7 | + required: true |
| 8 | + default: 'true' |
8 | 9 | azure_devops_project_url: |
9 | | - description: Azure devops project url like (e.g. `https://dev.azure.com/pagopaspa/arc-projects``) |
| 10 | + description: 'Azure DevOps project URL' |
| 11 | + required: true |
10 | 12 | azure_devops_pipeline_name: |
11 | | - description: Pipeline name inside the project (e.g. `arc-cittadini-deploy-aks.deploy`) |
| 13 | + description: 'Name of the Azure DevOps pipeline to trigger' |
| 14 | + required: true |
12 | 15 | azure_devops_pat: |
13 | | - description: Personal secret azure devops PAT |
14 | | - default: '' |
| 16 | + description: 'Azure DevOps Personal Access Token' |
| 17 | + required: true |
15 | 18 | azure_template_parameters: |
16 | | - description: Json attribute with all the parameters that must be send to the pipeline. See README for example (⚠️ this parameters must exists) |
| 19 | + description: 'Template parameters in JSON format' |
| 20 | + required: false |
| 21 | + default: '{}' |
17 | 22 |
|
18 | 23 | runs: |
19 | | - using: "composite" |
| 24 | + using: 'composite' |
20 | 25 | steps: |
21 | | - |
22 | | - # |
23 | | - # AZDO |
24 | | - # |
25 | | - - name: 🤔 Check azure_devops_pat |
26 | | - if: ${{ inputs.enable_azure_devops_step == 'true' }} |
| 26 | + - name: Set up Python |
| 27 | + uses: actions/setup-python@v4 |
| 28 | + with: |
| 29 | + python-version: '3.10' |
| 30 | + |
| 31 | + - name: Install dependencies |
27 | 32 | shell: bash |
| 33 | + run: pip install requests |
| 34 | + |
| 35 | + - name: Run Pipeline Trigger |
| 36 | + shell: python |
| 37 | + env: |
| 38 | + INPUT_ENABLE_AZURE_DEVOPS_STEP: ${{ inputs.enable_azure_devops_step }} |
| 39 | + INPUT_AZURE_DEVOPS_PROJECT_URL: ${{ inputs.azure_devops_project_url }} |
| 40 | + INPUT_AZURE_DEVOPS_PIPELINE_NAME: ${{ inputs.azure_devops_pipeline_name }} |
| 41 | + INPUT_AZURE_DEVOPS_PAT: ${{ inputs.azure_devops_pat }} |
| 42 | + INPUT_AZURE_TEMPLATE_PARAMETERS: ${{ inputs.azure_template_parameters }} |
28 | 43 | run: | |
29 | | - if [ -z "${{ inputs.azure_devops_pat }}" ]; then |
30 | | - echo "Error: azure_devops_pat is empty. This is required for triggering the Azure DevOps pipeline." |
31 | | - exit 1 |
32 | | - fi |
| 44 | + import os |
| 45 | + import json |
| 46 | + import sys |
| 47 | + from urllib.parse import urlparse |
| 48 | + import requests |
| 49 | + import base64 |
| 50 | + |
| 51 | + def log_info(message): print(f"ℹ️ {message}") |
| 52 | + def log_success(message): print(f"✅ {message}") |
| 53 | + def log_warning(message): print(f"⚠️ {message}") |
| 54 | + def log_error(message): print(f"❌ {message}") |
| 55 | + def log_start(message): print(f"🚀 {message}") |
| 56 | + def log_config(message): print(f"⚙️ {message}") |
| 57 | + def log_api(message): print(f"🔌 {message}") |
33 | 58 |
|
34 | | - echo "🔨 Start launch trigger with Azure Devops" |
| 59 | + def get_project_info(project_url): |
| 60 | + """Extract organization and project from Azure DevOps URL""" |
| 61 | + log_info(f"Parsing project URL: {project_url}") |
| 62 | + parts = urlparse(project_url).path.strip('/').split('/') |
| 63 | + org, project = parts[0], parts[1] |
| 64 | + log_success(f"Found organization: {org} and project: {project}") |
| 65 | + return org, project |
35 | 66 |
|
36 | | - - name: 🚂 Trigger Azure DevOps pipeline |
37 | | - if: inputs.enable_azure_devops_step == 'true' |
38 | | - # https://github.com/pagopa/azure-pipelines/releases/tag/v2.0.0 |
39 | | - uses: pagopa/azure-pipelines@51d971651241601a348e4e2ed2431b8b7576d4f0 |
40 | | - with: |
41 | | - azure-devops-project-url: ${{ inputs.azure_devops_project_url }} |
42 | | - azure-pipeline-name: ${{ inputs.azure_devops_pipeline_name }} |
43 | | - azure-devops-token: ${{ inputs.azure_devops_pat }} |
44 | | - azure-pipeline-variables: '{"system.debug": "true"}' |
45 | | - azure-template-parameters: ${{ inputs.azure_template_parameters }} |
| 67 | + def get_pipeline_id(org, project, pipeline_name, auth_header): |
| 68 | + """Get pipeline ID from name""" |
| 69 | + log_api(f"Getting pipeline ID for: {pipeline_name}") |
| 70 | + url = f"https://dev.azure.com/{org}/{project}/_apis/pipelines?api-version=7.1" |
| 71 | + |
| 72 | + response = requests.get(url, headers=auth_header) |
| 73 | + if response.status_code != 200: |
| 74 | + log_error(f"Failed to get pipeline list: {response.text}") |
| 75 | + sys.exit(1) |
| 76 | + |
| 77 | + pipelines = response.json()['value'] |
| 78 | + for pipeline in pipelines: |
| 79 | + if pipeline['name'] == pipeline_name: |
| 80 | + log_success(f"Found pipeline ID: {pipeline['id']}") |
| 81 | + return pipeline['id'] |
| 82 | + |
| 83 | + log_error(f"Pipeline {pipeline_name} not found") |
| 84 | + sys.exit(1) |
| 85 | +
|
| 86 | + def trigger_pipeline(org, project, pipeline_id, template_params, auth_header): |
| 87 | + """Trigger the pipeline with template parameters""" |
| 88 | + log_start("Triggering pipeline...") |
| 89 | + url = f"https://dev.azure.com/{org}/{project}/_apis/pipelines/{pipeline_id}/runs?api-version=7.1" |
| 90 | + |
| 91 | + # Pretty print template parameters for logging |
| 92 | + log_config("Template parameters:") |
| 93 | + print(json.dumps(template_params, indent=2)) |
| 94 | + |
| 95 | + body = { |
| 96 | + "templateParameters": template_params, |
| 97 | + "resources": { |
| 98 | + "repositories": { |
| 99 | + "self": { |
| 100 | + "refName": "refs/heads/main" |
| 101 | + } |
| 102 | + } |
| 103 | + } |
| 104 | + } |
| 105 | + |
| 106 | + log_api("Making API request to Azure DevOps...") |
| 107 | + response = requests.post(url, headers=auth_header, json=body) |
| 108 | + return response |
| 109 | +
|
| 110 | + # Main execution |
| 111 | + log_start("Starting Azure DevOps Pipeline Trigger") |
| 112 | +
|
| 113 | + # Check if step is enabled |
| 114 | + if os.environ['INPUT_ENABLE_AZURE_DEVOPS_STEP'].lower() != 'true': |
| 115 | + log_warning("Step is disabled. Skipping...") |
| 116 | + sys.exit(0) |
| 117 | +
|
| 118 | + try: |
| 119 | + # Get inputs |
| 120 | + project_url = os.environ['INPUT_AZURE_DEVOPS_PROJECT_URL'] |
| 121 | + pipeline_name = os.environ['INPUT_AZURE_DEVOPS_PIPELINE_NAME'] |
| 122 | + pat = os.environ['INPUT_AZURE_DEVOPS_PAT'] |
| 123 | +
|
| 124 | + # Validate PAT token |
| 125 | + if not pat or pat.isspace(): |
| 126 | + log_error("Azure DevOps PAT token cannot be empty or null") |
| 127 | + sys.exit(1) |
| 128 | + |
| 129 | + template_params = json.loads(os.environ['INPUT_AZURE_TEMPLATE_PARAMETERS']) |
| 130 | +
|
| 131 | + # Create auth header |
| 132 | + auth_token = base64.b64encode(f":{pat}".encode()).decode() |
| 133 | + auth_header = { |
| 134 | + "Authorization": f"Basic {auth_token}", |
| 135 | + "Content-Type": "application/json" |
| 136 | + } |
| 137 | + log_config("Authentication configured") |
| 138 | +
|
| 139 | + # Get organization and project |
| 140 | + org, project = get_project_info(project_url) |
| 141 | +
|
| 142 | + # Get pipeline ID |
| 143 | + pipeline_id = get_pipeline_id(org, project, pipeline_name, auth_header) |
| 144 | +
|
| 145 | + # Trigger pipeline |
| 146 | + response = trigger_pipeline(org, project, pipeline_id, template_params, auth_header) |
| 147 | +
|
| 148 | + if response.status_code == 200: |
| 149 | + log_success("Pipeline triggered successfully! 🎉") |
| 150 | + print("\nPipeline details:") |
| 151 | + print(json.dumps(response.json(), indent=2)) |
| 152 | + else: |
| 153 | + log_error(f"Failed to trigger pipeline: {response.text}") |
| 154 | + sys.exit(1) |
| 155 | +
|
| 156 | + except Exception as e: |
| 157 | + log_error(f"An error occurred: {str(e)}") |
| 158 | + sys.exit(1) |
| 159 | +
|
| 160 | + log_success("Pipeline trigger completed successfully! 🏁") |
0 commit comments