mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
The existing concurrency configuration causes workflow runs for one Pull Request to cancel in-progress runs for another Pull Request. When the workflow is triggered by the `pull_request_target event`, `github.ref` is always set to the base branch, regardless of which branch raised the PR. This causes every new pull request to share the same concurrency key and thus cancel the running CI of any other open pull request. This commit updates the `concurrency.group` to use `github.event.pull_request.number` for unique isolation when running on PR, falling back to `github.ref` for non-PR push (e.g., merge group). Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
237 lines
8.4 KiB
YAML
237 lines
8.4 KiB
YAML
name: MSHV Infra Setup
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
ARCH:
|
|
description: 'Architecture for the VM'
|
|
required: true
|
|
type: string
|
|
KEY:
|
|
description: 'SSH Key Name'
|
|
required: true
|
|
type: string
|
|
OS_DISK_SIZE:
|
|
description: 'OS Disk Size in GB'
|
|
required: true
|
|
type: string
|
|
RG:
|
|
description: 'Resource Group Name'
|
|
required: true
|
|
type: string
|
|
VM_SKU:
|
|
description: 'VM SKU'
|
|
required: true
|
|
type: string
|
|
secrets:
|
|
MI_CLIENT_ID:
|
|
required: true
|
|
RUNNER_RG:
|
|
required: true
|
|
STORAGE_ACCOUNT_PATHS:
|
|
required: true
|
|
ARCH_SOURCE_PATH:
|
|
required: true
|
|
USERNAME:
|
|
required: true
|
|
outputs:
|
|
PRIVATE_IP:
|
|
description: 'Private IP of the VM'
|
|
value: ${{ jobs.infra-setup.outputs.PRIVATE_IP }}
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
cancel-in-progress: true
|
|
jobs:
|
|
infra-setup:
|
|
name: ${{ inputs.ARCH }} VM Provision
|
|
runs-on: mshv
|
|
continue-on-error: true
|
|
outputs:
|
|
PRIVATE_IP: ${{ steps.get-vm-ip.outputs.PRIVATE_IP }}
|
|
steps:
|
|
- name: Install & login to AZ CLI
|
|
env:
|
|
MI_CLIENT_ID: ${{ secrets.MI_CLIENT_ID }}
|
|
run: |
|
|
set -e
|
|
echo "Installing Azure CLI if not already installed"
|
|
if ! command -v az &>/dev/null; then
|
|
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
|
|
else
|
|
echo "Azure CLI already installed"
|
|
fi
|
|
az --version
|
|
echo "Logging into Azure CLI using Managed Identity"
|
|
az login --identity --client-id ${MI_CLIENT_ID}
|
|
|
|
- name: Get Location
|
|
id: get-location
|
|
env:
|
|
SKU: ${{ inputs.VM_SKU }}
|
|
STORAGE_ACCOUNT_PATHS: ${{ secrets.STORAGE_ACCOUNT_PATHS }}
|
|
run: |
|
|
set -e
|
|
# Extract vCPU count from SKU (e.g., "Standard_D2s_v3" => 2)
|
|
vcpu=$(echo "$SKU" | sed -n 's/^Standard_[A-Za-z]\+\([0-9]\+\).*/\1/p')
|
|
if [[ -z "$vcpu" ]]; then
|
|
echo "Cannot extract vCPU count from SKU: $SKU"
|
|
exit 1
|
|
fi
|
|
|
|
SUPPORTED_LOCATIONS=$(echo "$STORAGE_ACCOUNT_PATHS" | jq -r 'to_entries[] | .key')
|
|
|
|
for location in $SUPPORTED_LOCATIONS; do
|
|
family=$(az vm list-skus --size "$SKU" --location "$location" --resource-type "virtualMachines" --query '[0].family' -o tsv)
|
|
if [[ -z "$family" ]]; then
|
|
echo "Cannot determine VM family for SKU: $SKU in $location"
|
|
continue
|
|
fi
|
|
|
|
usage=$(az vm list-usage --location "$location" --query "[?name.value=='$family'] | [0]" -o json)
|
|
current=$(echo "$usage" | jq -r '.currentValue')
|
|
limit=$(echo "$usage" | jq -r '.limit')
|
|
|
|
if [[ $((limit - current)) -ge $vcpu ]]; then
|
|
echo "Sufficient quota found in $location"
|
|
echo "location=$location" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
done
|
|
|
|
echo "No location found with sufficient vCPU quota for SKU: $SKU"
|
|
exit 1
|
|
|
|
- name: Create Resource Group
|
|
id: rg-setup
|
|
env:
|
|
LOCATION: ${{ steps.get-location.outputs.location }}
|
|
RG: ${{ inputs.RG }}
|
|
STORAGE_ACCOUNT_PATHS: ${{ secrets.STORAGE_ACCOUNT_PATHS }}
|
|
run: |
|
|
set -e
|
|
echo "Creating Resource Group: $RG"
|
|
# Create the resource group
|
|
echo "Creating resource group in location: ${LOCATION}"
|
|
az group create --name ${RG} --location ${LOCATION}
|
|
echo "Resource group created successfully."
|
|
|
|
- name: Generate SSH Key
|
|
id: generate-ssh-key
|
|
env:
|
|
KEY: ${{ inputs.KEY }}
|
|
run: |
|
|
set -e
|
|
echo "Generating SSH key: $KEY"
|
|
mkdir -p ~/.ssh
|
|
ssh-keygen -t rsa -b 4096 -f ~/.ssh/${KEY} -N ""
|
|
|
|
- name: Create VM
|
|
id: vm-setup
|
|
env:
|
|
KEY: ${{ inputs.KEY }}
|
|
LOCATION: ${{ steps.get-location.outputs.location }}
|
|
OS_DISK_SIZE: ${{ inputs.OS_DISK_SIZE }}
|
|
RG: ${{ inputs.RG }}
|
|
RUNNER_RG: ${{ secrets.RUNNER_RG }}
|
|
USERNAME: ${{ secrets.USERNAME }}
|
|
VM_SKU: ${{ inputs.VM_SKU }}
|
|
VM_IMAGE_NAME: ${{ inputs.ARCH }}_${{ steps.get-location.outputs.location }}_image
|
|
VM_NAME: ${{ inputs.ARCH }}_${{ steps.get-location.outputs.location }}_${{ github.run_id }}
|
|
run: |
|
|
set -e
|
|
echo "Creating $VM_SKU VM: $VM_NAME"
|
|
|
|
# Extract subnet ID from the runner VM
|
|
echo "Retrieving subnet ID..."
|
|
SUBNET_ID=$(az network vnet list --resource-group ${RUNNER_RG} --query "[?contains(location, '${LOCATION}')].{SUBNETS:subnets}" | jq -r ".[0].SUBNETS[0].id")
|
|
if [[ -z "${SUBNET_ID}" ]]; then
|
|
echo "ERROR: Failed to retrieve Subnet ID."
|
|
exit 1
|
|
fi
|
|
|
|
# Extract image ID from the runner VM
|
|
echo "Retrieving image ID..."
|
|
IMAGE_ID=$(az image show --resource-group ${RUNNER_RG} --name ${VM_IMAGE_NAME} --query "id" -o tsv)
|
|
if [[ -z "${IMAGE_ID}" ]]; then
|
|
echo "ERROR: Failed to retrieve Image ID."
|
|
exit 1
|
|
fi
|
|
|
|
# Create VM
|
|
az vm create \
|
|
--resource-group ${RG} \
|
|
--name ${VM_NAME} \
|
|
--subnet ${SUBNET_ID} \
|
|
--size ${VM_SKU} \
|
|
--location ${LOCATION} \
|
|
--image ${IMAGE_ID} \
|
|
--os-disk-size-gb ${OS_DISK_SIZE} \
|
|
--public-ip-sku Standard \
|
|
--storage-sku Premium_LRS \
|
|
--public-ip-address "" \
|
|
--admin-username ${USERNAME} \
|
|
--ssh-key-value ~/.ssh/${KEY}.pub \
|
|
--security-type Standard \
|
|
--output json
|
|
|
|
echo "VM creation process completed successfully."
|
|
|
|
- name: Get VM Private IP
|
|
id: get-vm-ip
|
|
env:
|
|
RG: ${{ inputs.RG }}
|
|
VM_NAME: ${{ inputs.ARCH }}_${{ steps.get-location.outputs.location }}_${{ github.run_id }}
|
|
run: |
|
|
set -e
|
|
echo "Retrieving VM Private IP address..."
|
|
# Retrieve VM Private IP address
|
|
PRIVATE_IP=$(az vm show -g ${RG} -n ${VM_NAME} -d --query privateIps -o tsv)
|
|
if [[ -z "$PRIVATE_IP" ]]; then
|
|
echo "ERROR: Failed to retrieve private IP address."
|
|
exit 1
|
|
fi
|
|
echo "PRIVATE_IP=$PRIVATE_IP" >> $GITHUB_OUTPUT
|
|
|
|
- name: Wait for SSH availability
|
|
env:
|
|
KEY: ${{ inputs.KEY }}
|
|
PRIVATE_IP: ${{ steps.get-vm-ip.outputs.PRIVATE_IP }}
|
|
USERNAME: ${{ secrets.USERNAME }}
|
|
run: |
|
|
echo "Waiting for SSH to be accessible..."
|
|
timeout 120 bash -c 'until ssh -o StrictHostKeyChecking=no -i ~/.ssh/${KEY} ${USERNAME}@${PRIVATE_IP} "exit" 2>/dev/null; do sleep 5; done'
|
|
echo "VM is accessible!"
|
|
|
|
- name: Remove Old Host Key
|
|
env:
|
|
PRIVATE_IP: ${{ steps.get-vm-ip.outputs.PRIVATE_IP }}
|
|
run: |
|
|
set -e
|
|
echo "Removing the old host key"
|
|
ssh-keygen -R $PRIVATE_IP
|
|
|
|
- name: SSH into VM and Install Dependencies
|
|
env:
|
|
KEY: ${{ inputs.KEY }}
|
|
PRIVATE_IP: ${{ steps.get-vm-ip.outputs.PRIVATE_IP }}
|
|
USERNAME: ${{ secrets.USERNAME }}
|
|
run: |
|
|
set -e
|
|
ssh -i ~/.ssh/${KEY} -o StrictHostKeyChecking=no ${USERNAME}@${PRIVATE_IP} << EOF
|
|
set -e
|
|
echo "Logged in successfully."
|
|
echo "Installing dependencies..."
|
|
sudo tdnf install -y git moby-engine moby-cli clang llvm pkg-config make gcc glibc-devel
|
|
echo "Installing Rust..."
|
|
curl -sSf https://sh.rustup.rs | sh -s -- --default-toolchain stable --profile default -y
|
|
export PATH="\$HOME/.cargo/bin:\$PATH"
|
|
cargo --version
|
|
sudo mkdir -p /etc/docker/
|
|
echo '{"default-ulimits":{"nofile":{"Hard":65535,"Name":"nofile","Soft":65535}}}' | sudo tee /etc/docker/daemon.json
|
|
sudo systemctl stop docker
|
|
sudo systemctl enable docker.service
|
|
sudo systemctl enable containerd.service
|
|
sudo systemctl start docker
|
|
sudo groupadd -f docker
|
|
sudo usermod -a -G docker ${USERNAME}
|
|
sudo systemctl restart docker
|
|
EOF |