Skip to content

Build VM Image workflow_run_id:0 download_ya_archive:false remove_old_images:true update_image_id:true #14

Build VM Image workflow_run_id:0 download_ya_archive:false remove_old_images:true update_image_id:true

Build VM Image workflow_run_id:0 download_ya_archive:false remove_old_images:true update_image_id:true #14

Workflow file for this run

name: Build VM Image
run-name: Build VM Image ${{ github.event.workflow_run.event }} workflow_run_id:${{ inputs.workflow_run_id }} download_ya_archive:${{ inputs.download_ya_archive }} remove_old_images:${{ inputs.remove_old_images }} update_image_id:${{ inputs.update_image_id }}
on:
# schedule:
# - cron: "0 5 * * *"
workflow_call:
inputs:
build:
description: "Build VM image"
required: false
default: true
type: boolean
download_ya_archive:
description: "Download .ya archive to resulting image"
required: false
default: true
type: boolean
workflow_run_id:
description: "Workflow run id (optional)"
required: false
default: 0
type: number
file:
description: "File to download"
required: false
default: "ya_web_url_file"
type: string
images_to_keep:
description: "Number of images to keep"
required: false
default: 3
type: number
remove_old_images:
description: "Delete old images"
required: false
default: false
type: boolean
update_image_id:
description: "Update image id"
required: false
default: false
type: boolean
image_prefix:
description: "Image prefix"
required: false
default: "gh-2204-auto"
type: string
check_vm_creation:
description: "Check VM creation"
required: false
default: false
type: boolean
nebius:
description: "Run on new nebius runners"
required: false
default: "no"
type: string
workflow_dispatch:
inputs:
build:
description: "Build VM image"
required: false
default: true
type: boolean
download_ya_archive:
description: "Download .ya archive to resulting image"
required: false
default: true
type: boolean
workflow_run_id:
description: "Workflow run id (optional)"
required: false
default: 0
type: number
file:
description: "File to download"
required: false
default: "ya_web_url_file"
type: string
images_to_keep:
description: "Number of images to keep"
required: false
default: 3
type: number
remove_old_images:
description: "Delete old images"
required: false
default: false
type: boolean
update_image_id:
description: "Update image id"
required: false
default: false
type: boolean
image_prefix:
description: "Image prefix"
required: false
default: "gh-2204-auto"
type: string
check_vm_creation:
description: "Check VM creation"
required: false
default: false
type: boolean
nebius:
description: "Run on new nebius runners"
required: false
default: "no"
type: choice
options:
- "yes"
- "no"
env:
build: ${{ github.event_name == 'schedule' && 'true' || inputs.build }}
defaults:
run:
shell: bash --noprofile --norc -eo pipefail -x {0}
jobs:
build:
runs-on: ubuntu-latest
outputs:
IMAGE_ID_2204: ${{ steps.build.outputs.IMAGE_ID_2204 }}
IMAGE_ALREADY_EXISTS: ${{ steps.check-image.outputs.image_already_exists }}
BUILD: ${{ env.build }}
steps:
- name: Checkout PR
uses: actions/checkout@v4
- name: Set up Packer
if: inputs.nebius == 'no'
uses: hashicorp/setup-packer@v3
with:
version: 1.10.2
- name: install dependencies
run: |
pip install https://github.com/librarian/python-sdk/releases/download/v0.1.1/nebiusai-0.1.1-py3-none-any.whl
pip install PyGithub==2.2.0 grpcio grpcio-tools yandexcloud==0.258.0
echo "PATH=$PATH:$HOME/nebius-cloud/bin:$HOME/.nebius/bin" >> $GITHUB_ENV
- name: Set up NCP
if: inputs.nebius == 'no'
run: |
curl -sSL https://storage.ai.nebius.cloud/ncp/install.sh | bash
cat <<EOF > sa.json
${sa_json}
EOF
ncp config profile create nbs-github-user-sa
ncp config set service-account-key sa.json
ncp config set endpoint api.ai.nebius.cloud:443
env:
sa_json: ${{ secrets.NEBIUS_SA_JSON_CREDENTIALS }}
- name: Set up Nebius CLI
if: inputs.nebius == 'yes'
run: |
curl -sSL https://storage.ai.nebius.cloud/nebius/install.sh | bash
cat <<EOF > sa.json
${sa_json}
EOF
cat sa.json | jq -r '."subject-credentials"."private-key"' > private.pem
echo "::add-mask::$(cat sa.json | jq -r '."subject-credentials"."kid"')"
public_key_id=$(cat sa.json | jq -r '."subject-credentials"."kid"')
echo "::add-mask::$(cat sa.json | jq -r '."subject-credentials"."iss"')"
service_account_id=$(cat sa.json | jq -r '."subject-credentials"."iss"')
echo "::add-mask::tenant-e00en3r863f7me6wtd"
nebius profile create --endpoint api.eu-north1.nebius.cloud \
--profile nbs-github-user-sa \
--parent-id tenant-e00en3r863f7me6wtd \
--public-key-id "${public_key_id}" \
--private-key-file private.pem \
--service-account-id "${service_account_id}"
env:
sa_json: ${{ secrets.NEW_NEBIUS_SA_JSON_CREDENTIALS }}
- name: Get IAM token
if: inputs.nebius == 'no'
id: get-iam-token
run: |
YC_TOKEN=$(ncp --profile=nbs-github-user-sa iam create-token --format=json | jq -r .iam_token)
echo "::add-mask::$YC_TOKEN"
echo "YC_TOKEN=$YC_TOKEN" >> $GITHUB_ENV
- name: Get .ya archive url
if: inputs.download_ya_archive == true && inputs.nebius == 'no'
id: get-ya-archive-url
run: |
python .github/scripts/workflow-artifact-download.py \
--artifact "${ARTIFACT_NAME}" \
--workflow-run-id "${WORKFLOW_RUN_ID}"
env:
GITHUB_TOKEN: ${{ github.token }}
ARTIFACT_NAME: ${{ inputs.file }}
WORKFLOW_RUN_ID: ${{ inputs.workflow_run_id }}
- name: Check whether we have image with this workflow_run_id
if: inputs.download_ya_archive == true && inputs.nebius == 'no'
id: check-image
run: |
ncp --profile=nbs-github-user-sa compute images list --folder-id "${FOLDER_ID}" --format=json | tee -a images.txt
exit_code=0
jq -r 'first(
.[].name |
if .== "${{ inputs.image_prefix }}-${{ steps.get-ya-archive-url.outputs.run_id }}"
then
halt_error(1)
else
empty
end
)' < images.txt || {
exit_code=$?
}
if [ "$exit_code" -eq 1 ]; then
echo "Image with this run_id already exists, if you want to overwrite it, rename old one"
echo "image_already_exists=true" >> $GITHUB_OUTPUT
else
echo "Image with this run_id doesn't exist"
echo "image_already_exists=false" >> $GITHUB_OUTPUT
fi
env:
FOLDER_ID: bjeuq5o166dq4ukv3eec
- name: Run `packer init` and create variables file
if: steps.check-image.outputs.image_already_exists != 'true' && inputs.nebius == 'no'
id: init
run: |
VARIABLES_FILE=$(mktemp XXXXXXX.hcl)
IMAGE_FAMILY_NAME=${GITHUB_REPOSITORY//\//-}
echo "VARIABLES_FILE=$VARIABLES_FILE" >> $GITHUB_ENV
packer init .github/packer/config.pkr.hcl
cat << EOF > $VARIABLES_FILE
RUNNER_VERSION="${RUNNER_VERSION}"
USER_TO_CREATE="${USER_NAME}"
PASSWORD_HASH="${PASSWORD_HASH}"
${YA_ARCHIVE_PARAMETER}
FOLDER_ID="${FOLDER_ID}"
ZONE="${ZONE}"
SUBNET_ID="${SUBNET_ID}"
ORG="${ORG}"
TEAM="${TEAM}"
GITHUB_TOKEN="${GITHUB_TOKEN}"
AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID}"
AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY}"
REPOSITORY="${GITHUB_REPOSITORY}"
IMAGE_FAMILY_NAME="${IMAGE_FAMILY_NAME}"
IMAGE_PREFIX="${IMAGE_PREFIX}"
BUILD_RUN_ID="${BUILD_RUN_ID}"
EOF
cat $VARIABLES_FILE
env:
PACKER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RUNNER_VERSION: ${{ vars.RUNNER_VERSION || '2.308.0' }}
FOLDER_ID: bjeuq5o166dq4ukv3eec
ZONE: eu-north1-c
SUBNET_ID: f8uh0ml4rhb45nde9p75
USER_NAME: github
GITHUB_TOKEN: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
PASSWORD_HASH: ${{ secrets.VM_USER_PASSWD }}
ORG: "ydb-platform"
TEAM: "nbs"
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
IMAGE_PREFIX: ${{ inputs.image_prefix }}
BUILD_RUN_ID: ${{ github.run_id }}
YA_ARCHIVE_PARAMETER: |
${{ (inputs.download_ya_archive && steps.get-ya-archive-url.outputs.latest_url != '')
&& format(
'YA_ARCHIVE_URL="{0}"
NIGHTLY_RUN_ID="{1}"',
steps.get-ya-archive-url.outputs.latest_url, steps.get-ya-archive-url.outputs.run_id
) || ''
}}
- name: Run `packer validate`
if: steps.check-image.outputs.image_already_exists != 'true' && inputs.nebius == 'no'
id: validate
run: |
packer validate -var-file=$VARIABLES_FILE .github/packer/github-runner.pkr.hcl
env:
PACKER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run `packer build`
id: build
if: env.build == 'true' && steps.check-image.outputs.image_already_exists != 'true' && inputs.nebius == 'no'
timeout-minutes: 120
run: |
packer build -timestamp-ui -var-file=$VARIABLES_FILE .github/packer/github-runner.pkr.hcl
echo "IMAGE_ID_2204=$(jq -r '.builds[0].artifact_id' manifest.json)" >> $GITHUB_OUTPUT
env:
PACKER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Print IMAGE_ID_2204
if: env.build == 'true' && steps.check-image.outputs.image_already_exists != 'true' && inputs.nebius == 'no'
run: echo ${{ steps.build.outputs.IMAGE_ID_2204 }}
- name: Start runner
id: start-runner
if: env.build == 'true' && steps.check-image.outputs.image_already_exists != 'true' && inputs.nebius == 'no'
uses: ./.github/actions/runner_create
timeout-minutes: 60
with:
repo_owner: ${{ github.repository_owner }}
repo: ${{ github.event.repository.name }}
service_account_key: ${{ secrets.NEBIUS_SA_JSON_CREDENTIALS }}
token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
vm_folder: bjeuq5o166dq4ukv3eec
vm_name: ${{ format('packer-run-{0}-{1}', github.run_id, github.run_attempt) }}
vm_zone: eu-north1-c
vm_cpu: 60
vm_memory: 420
vm_disk_type: 'network-ssd-nonreplicated'
vm_disk_size: 1023
vm_subnet: f8uh0ml4rhb45nde9p75
vm_image: ${{ steps.build.outputs.IMAGE_ID_2204 }}
vm_labels: ${{ format('run={0}-{1},repo={2},owner={3}', github.run_id, github.run_attempt, github.event.repository.name, github.repository_owner) }}
vm_user_passwd: ${{ secrets.VM_USER_PASSWD }}
- name: Stop runner
uses: ./.github/actions/runner_remove
if: always() && env.build == 'true' && steps.check-image.outputs.image_already_exists != 'true' && inputs.nebius == 'no'
timeout-minutes: 60
with:
service_account_key: ${{ secrets.NEBIUS_SA_JSON_CREDENTIALS }}
token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
repo_owner: ${{ github.repository_owner }}
repo: ${{ github.event.repository.name }}
vm_id: ${{ steps.start-runner.outputs.instance-id }}
- name: Set new image id
if: env.build == 'true' && steps.check-image.outputs.image_already_exists != 'true' && inputs.nebius == 'no'
run: |
python ./.github/scripts/manage-images.py \
--service-account-key sa.json \
--new-image-id ${NEW_IMAGE_ID} \
--image-variable-name ${IMAGE_VARIABLE_NAME} \
--images-to-keep ${IMAGES_TO_KEEP} ${UPDATE_IMAGE_ID} ${REMOVE_OLD_IMAGES}
env:
GITHUB_TOKEN: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
IMAGE_VARIABLE_NAME: IMAGE_ID_2204
NEW_IMAGE_ID: ${{ steps.build.outputs.IMAGE_ID_2204 }}
IMAGES_TO_KEEP: ${{ inputs.images_to_keep }}
UPDATE_IMAGE_ID: ${{ inputs.update_image_id && '--update-image-id' || '' }}
REMOVE_OLD_IMAGES: ${{ inputs.remove_old_images && '--remove-old-images' || '' }}
- name: Get latest image ID from Nebius
if: inputs.nebius == 'yes' && env.build == 'true'
id: get-image-id-nebius
run: |
image_id=$(nebius compute image get-latest-by-family --image-family ubuntu22.04-nbs-github-ci --parent-id ${{ vars.NEBIUS_PARENT_ID }} --format json | jq -r .metadata.id)
echo "IMAGE_ID_2204=$image_id" >> $GITHUB_OUTPUT
- name: Start runner (nebius)
id: start-runner-nebius
if: inputs.nebius == 'yes' && env.build == 'true' && steps.get-image-id-nebius.outputs.IMAGE_ID_2204 != vars.NEBIUS_IMAGE_ID_2204
uses: ./.github/actions/nebius_runner_create
timeout-minutes: 60
with:
org: ydb-platform
team: nbs
repo_owner: ${{ github.repository_owner }}
repo: ${{ github.event.repository.name }}
service_account_key: ${{ secrets.NEW_NEBIUS_SA_JSON_CREDENTIALS }}
token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
vm_parent_id: ${{ vars.NEBIUS_PARENT_ID }}
vm_name: ${{ format('packer-run-{0}-{1}', github.run_id, github.run_attempt) }}
vm_preset: "2vcpu-8gb"
vm_disk_type: 'network-ssd-nonreplicated'
vm_disk_size: 93
vm_subnet: ${{ vars.NEBIUS_SUBNET_ID }}
vm_image: ${{ steps.get-image-id-nebius.outputs.IMAGE_ID_2204 }}
vm_labels: ${{ format('run={0}-{1},repo={2},owner={3}', github.run_id, github.run_attempt, github.event.repository.name, github.repository_owner) }}
vm_user_passwd: ${{ secrets.VM_USER_PASSWD }}
- name: Stop runner (nebius)
uses: ./.github/actions/nebius_runner_remove
if: always() && inputs.nebius == 'yes' && env.build == 'true' && steps.get-image-id-nebius.outputs.IMAGE_ID_2204 != vars.NEBIUS_IMAGE_ID_2204
timeout-minutes: 60
with:
service_account_key: ${{ secrets.NEW_NEBIUS_SA_JSON_CREDENTIALS }}
token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
repo_owner: ${{ github.repository_owner }}
repo: ${{ github.event.repository.name }}
vm_parent_id: ${{ vars.NEBIUS_PARENT_ID }}
vm_id: ${{ steps.start-runner-nebius.outputs.instance-id }}
- name: Set new image id (nebius)
if: env.build == 'true' && steps.check-image.outputs.image_already_exists != 'true' && inputs.nebius == 'yes'
run: |
python ./.github/scripts/nebius-manage-images.py \
--service-account-key sa.json \
--new-image-id ${NEW_IMAGE_ID} \
--image-variable-name ${IMAGE_VARIABLE_NAME} ${UPDATE_IMAGE_ID}
env:
GITHUB_TOKEN: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
IMAGE_VARIABLE_NAME: NEBIUS_IMAGE_ID_2204
NEW_IMAGE_ID: ${{ steps.get-image-id-nebius.outputs.IMAGE_ID_2204 }}
UPDATE_IMAGE_ID: ${{ inputs.update_image_id && '--update-image-id' || '' }}