# Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. name: Approve Test Queue on: schedule: - cron: '*/5 * * * *' # Runs every 5 minutes workflow_dispatch: # Allows manual triggering jobs: approve-queue: runs-on: ubuntu-latest environment: main steps: - name: Checkout repository uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v6 with: python-version: "3.12" - name: Install dependencies run: | python -m pip install --upgrade pip pip install requests - name: Approve waiting deployments env: GITHUB_TOKEN: ${{ secrets.PAT }} MAX_CONCURRENCY: ${{ vars.MAX_CONCURRENCY || 1 }} run: | python - <= MAX_CONCURRENCY: print("Maximum concurrency reached, no new approvals will be made") exit(0) # Get waiting CI workflows for test environment print("Fetching deployments...") pending_workflows = filter_cicd_runs(get_workflow_runs("waiting")) # Sort deployments by creation date (oldest first) print("Sorting workflows...") pending_workflows = sorted(pending_workflows, key=lambda x: x.get("created_at", "")) # Process each deployment print("Processing ...") for workflow in pending_workflows: if total_workflows >= MAX_CONCURRENCY: print("Maximum concurrency reached, stopping approvals") break workflow_id = workflow.get("id") workflow_name = workflow.get("display_title") or workflow.get("name") or "" if not workflow_id: print(f"Skipping workflow without a run id: {workflow_name}") continue print(f"Approving workflow {workflow_name} with Run Id: {workflow_id}") deployment_url = f"actions/runs/{workflow_id}/pending_deployments" pending_deployments = make_request(deployment_url) if not pending_deployments: print(f"No pending deployments found for workflow {workflow_name}; skipping") continue environment_ids = [] environment_names = [] for deployment in pending_deployments: environment = deployment.get("environment") or {} environment_id = environment.get("id") environment_name = environment.get("name") or "" if not environment_id: print(f"Skipping deployment without an environment id for workflow {workflow_name}") continue environment_ids.append(environment_id) environment_names.append(environment_name) if not environment_ids: print(f"No pending deployments with environment ids found for workflow {workflow_name}") exit(1) # Approve the deployment status_data = { "environment_ids": environment_ids, "state": "approved", "comment": "Automatically approved by queue manager" } result = make_request( deployment_url, method="POST", data=status_data, allow_no_pending_deployments=True, ) if result is None: print(f"Failed to approve environments {environment_names} for workflow {workflow_name}") exit(1) if isinstance(result, dict) and result.get("skipped"): continue total_workflows += 1 EOF notify: if: failure() runs-on: ubuntu-latest needs: [approve-queue] steps: - name: Notify env: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} SLACK_WEBHOOK_ADMIN: GITHUB_RUN_ID: ${{ github.run_id }} GITHUB_REPOSITORY: ${{ github.repository }} run: | curl -X POST \ -H 'Content-type: application/json' \ --data "{\"text\":\":robot_joy: failed. Please review manually.\n\ncc ${SLACK_WEBHOOK_ADMIN}\"}" \ $SLACK_WEBHOOK