From fe69f909ae126c094f9e384474c05bf0f1248380 Mon Sep 17 00:00:00 2001 From: KirillKurdyukov Date: Tue, 16 Jun 2026 16:50:18 +0300 Subject: [PATCH 1/4] Update SLO workflow paths Point the Java SDK SLO image build at the relocated query workload and pass checkout paths relative to the workspace. --- .github/scripts/build-slo-image.sh | 9 +++++---- .github/workflows/slo.yml | 8 ++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/scripts/build-slo-image.sh b/.github/scripts/build-slo-image.sh index cd2972b0e..cf12a92a4 100755 --- a/.github/scripts/build-slo-image.sh +++ b/.github/scripts/build-slo-image.sh @@ -5,7 +5,7 @@ # The script assembles a temporary build context containing two checkouts # side by side — the SDK source tree and the ydb-java-examples checkout — # and feeds that context to `docker build` using the Dockerfile shipped -# inside `ydb-java-examples/slo/`. +# inside `ydb-java-examples/slo-workload/query/`. # # The Dockerfile takes care of building the SDK from source, installing it # into an in-image local Maven repository, and then building the workload @@ -32,7 +32,8 @@ Usage: Options: --sdk Path to the ydb-java-sdk checkout to build against. --examples Path to the ydb-java-examples checkout that owns the - SLO workload sources (must contain slo/Dockerfile). + SLO workload sources (must contain + slo-workload/query/Dockerfile). --tag Docker tag to assign to the built image (e.g. ydb-app-current). --fallback-image If the initial Docker build fails, tag this image as @@ -91,7 +92,7 @@ fi sdk_dir="$(cd "$sdk_dir" && pwd)" examples_dir="$(cd "$examples_dir" && pwd)" -dockerfile="${examples_dir}/slo/Dockerfile" +dockerfile="${examples_dir}/slo-workload/query/Dockerfile" [[ -f "$dockerfile" ]] || die "Dockerfile not found: $dockerfile" # Assemble a build context that contains the two checkouts side by side. @@ -131,7 +132,7 @@ rm -rf "$context_dir/ydb-java-sdk/.git" "$context_dir/ydb-java-examples/.git" # silent copy failure on the runner). for required in \ "$context_dir/ydb-java-sdk/pom.xml" \ - "$context_dir/ydb-java-examples/slo/Dockerfile" + "$context_dir/ydb-java-examples/slo-workload/query/Dockerfile" do [[ -f "$required" ]] || die "Build context missing required file: $required" done diff --git a/.github/workflows/slo.yml b/.github/workflows/slo.yml index e5bdf1eae..94e372968 100644 --- a/.github/workflows/slo.yml +++ b/.github/workflows/slo.yml @@ -98,8 +98,8 @@ jobs: set -euxo pipefail chmod +x sdk-current/.github/scripts/build-slo-image.sh sdk-current/.github/scripts/build-slo-image.sh \ - --sdk "${GITHUB_WORKSPACE}/sdk-current" \ - --examples "${GITHUB_WORKSPACE}/examples" \ + --sdk sdk-current \ + --examples examples \ --tag ydb-app-current - name: Build baseline workload image @@ -108,8 +108,8 @@ jobs: # Reuse the build script from the current checkout — it doesn't # depend on SDK contents, only on the layout it produces. sdk-current/.github/scripts/build-slo-image.sh \ - --sdk "${GITHUB_WORKSPACE}/sdk-baseline" \ - --examples "${GITHUB_WORKSPACE}/examples" \ + --sdk sdk-baseline \ + --examples examples \ --tag ydb-app-baseline \ --fallback-image ydb-app-current From 1c55bbfe2715a633d9225ca0b3a3f814cbb0f53e Mon Sep 17 00:00:00 2001 From: KirillKurdyukov Date: Wed, 17 Jun 2026 17:21:07 +0300 Subject: [PATCH 2/4] Run all four SLO workloads in SDK workflow matrix. Extend build-slo-image.sh with --workload and optional --jdbc checkout; JDBC tanks rebuild the driver against the SDK under test before packaging the workload jar. Co-authored-by: Cursor --- .github/scripts/build-slo-image.sh | 99 ++++++++++++++++-------------- .github/workflows/slo.yml | 92 +++++++++++++-------------- 2 files changed, 97 insertions(+), 94 deletions(-) diff --git a/.github/scripts/build-slo-image.sh b/.github/scripts/build-slo-image.sh index cf12a92a4..c34be43b5 100755 --- a/.github/scripts/build-slo-image.sh +++ b/.github/scripts/build-slo-image.sh @@ -1,22 +1,4 @@ #!/usr/bin/env bash -# -# Builds the Docker image for the YDB Java SDK SLO workload. -# -# The script assembles a temporary build context containing two checkouts -# side by side — the SDK source tree and the ydb-java-examples checkout — -# and feeds that context to `docker build` using the Dockerfile shipped -# inside `ydb-java-examples/slo-workload/query/`. -# -# The Dockerfile takes care of building the SDK from source, installing it -# into an in-image local Maven repository, and then building the workload -# against that exact SDK version. So the script does not need any Maven / -# JDK setup on the host; only `docker` and standard POSIX tools. -# -# If the initial build fails and `--fallback-image` is provided, the script -# tags the fallback image as `--tag` and exits successfully. This mirrors -# the behaviour of the equivalent script in `ydb-go-sdk` and is used by the -# baseline build, where we want to keep going even if the historical commit -# can't be built any more. set -euo pipefail @@ -26,20 +8,19 @@ Usage: build-slo-image.sh \ --sdk \ --examples \ + --workload \ --tag \ + [--jdbc ] \ [--fallback-image ] Options: --sdk Path to the ydb-java-sdk checkout to build against. - --examples Path to the ydb-java-examples checkout that owns the - SLO workload sources (must contain - slo-workload/query/Dockerfile). - --tag Docker tag to assign to the built image - (e.g. ydb-app-current). + --examples Path to the ydb-java-examples checkout. + --workload SLO workload module to build. + --tag Docker tag to assign to the built image. + --jdbc Path to ydb-jdbc-driver (required for JDBC workloads). --fallback-image If the initial Docker build fails, tag this image as - --tag and exit successfully. Useful for the baseline - build, which may be unable to compile a historical - SDK commit. + --tag and exit successfully. EOF } @@ -50,7 +31,9 @@ die() { sdk_dir="" examples_dir="" +workload="" tag="" +jdbc_dir="" fallback_image="" while [[ $# -gt 0 ]]; do @@ -63,10 +46,18 @@ while [[ $# -gt 0 ]]; do examples_dir="${2:-}" shift 2 ;; + --workload) + workload="${2:-}" + shift 2 + ;; --tag) tag="${2:-}" shift 2 ;; + --jdbc) + jdbc_dir="${2:-}" + shift 2 + ;; --fallback-image) fallback_image="${2:-}" shift 2 @@ -81,40 +72,54 @@ while [[ $# -gt 0 ]]; do esac done -if [[ -z "$sdk_dir" || -z "$examples_dir" || -z "$tag" ]]; then +if [[ -z "$sdk_dir" || -z "$examples_dir" || -z "$workload" || -z "$tag" ]]; then usage die "Incomplete argument set" fi +case "$workload" in + query|jdbc|spring-data-jdbc|spring-data-jpa) + ;; + *) + die "Unsupported workload: $workload" + ;; +esac + +if [[ "$workload" != "query" && -z "$jdbc_dir" ]]; then + die "--jdbc is required for workload ${workload}" +fi + [[ -d "$sdk_dir" ]] || die "--sdk does not exist: $sdk_dir" [[ -d "$examples_dir" ]] || die "--examples does not exist: $examples_dir" +if [[ -n "$jdbc_dir" ]]; then + [[ -d "$jdbc_dir" ]] || die "--jdbc does not exist: $jdbc_dir" +fi sdk_dir="$(cd "$sdk_dir" && pwd)" examples_dir="$(cd "$examples_dir" && pwd)" +if [[ -n "$jdbc_dir" ]]; then + jdbc_dir="$(cd "$jdbc_dir" && pwd)" +fi -dockerfile="${examples_dir}/slo-workload/query/Dockerfile" +dockerfile="${examples_dir}/slo-workload/${workload}/Dockerfile" [[ -f "$dockerfile" ]] || die "Dockerfile not found: $dockerfile" -# Assemble a build context that contains the two checkouts side by side. -# We use hard links where possible to avoid copying large amounts of data; -# `cp -al` falls back to a regular copy when hard links aren't supported -# (e.g. across filesystems on the GitHub runner cache). context_dir="$(mktemp -d)" trap 'rm -rf "$context_dir"' EXIT echo "Assembling build context in $context_dir" echo " ydb-java-sdk: $sdk_dir" echo " ydb-java-examples: $examples_dir" +echo " workload: $workload" echo " tag: $tag" +if [[ -n "$jdbc_dir" ]]; then + echo " ydb-jdbc-driver: $jdbc_dir" +fi copy_tree() { local src="$1" local dst="$2" mkdir -p "$dst" - # The "/." suffix on src and "/" on dst asks cp to copy CONTENTS of src - # into dst, regardless of whether dst pre-existed. Without this, partial - # hardlink failures can leave dst partially populated and the fallback - # then nests src inside dst (dst/src/...) instead of overwriting. if cp -al "$src"/. "$dst"/ 2>/dev/null; then return 0 fi @@ -123,23 +128,27 @@ copy_tree() { copy_tree "$sdk_dir" "$context_dir/ydb-java-sdk" copy_tree "$examples_dir" "$context_dir/ydb-java-examples" +if [[ -n "$jdbc_dir" ]]; then + copy_tree "$jdbc_dir" "$context_dir/ydb-jdbc-driver" +else + mkdir -p "$context_dir/ydb-jdbc-driver" +fi -# Drop .git from each copied tree so it doesn't ship into image layers or -# confuse Maven plugins that probe for git metadata. -rm -rf "$context_dir/ydb-java-sdk/.git" "$context_dir/ydb-java-examples/.git" +rm -rf "$context_dir/ydb-java-sdk/.git" \ + "$context_dir/ydb-java-examples/.git" \ + "$context_dir/ydb-jdbc-driver/.git" -# Fail fast with a clear message if the layout is wrong (e.g. because of a -# silent copy failure on the runner). for required in \ "$context_dir/ydb-java-sdk/pom.xml" \ - "$context_dir/ydb-java-examples/slo-workload/query/Dockerfile" + "$context_dir/ydb-java-examples/slo-workload/${workload}/Dockerfile" do [[ -f "$required" ]] || die "Build context missing required file: $required" done -echo "Build context layout:" -ls -la "$context_dir" -echo " ydb-java-sdk: $(ls -1 "$context_dir/ydb-java-sdk" | wc -l) entries" +if [[ "$workload" != "query" ]]; then + [[ -f "$context_dir/ydb-jdbc-driver/pom.xml" ]] \ + || die "Build context missing required file: $context_dir/ydb-jdbc-driver/pom.xml" +fi set +e docker build \ diff --git a/.github/workflows/slo.yml b/.github/workflows/slo.yml index 94e372968..4867b4736 100644 --- a/.github/workflows/slo.yml +++ b/.github/workflows/slo.yml @@ -17,12 +17,18 @@ jobs: strategy: fail-fast: false matrix: - sdk: + workload: - name: java-query-kv - command: "" + module: query + - name: java-jdbc-kv + module: jdbc + - name: java-spring-data-jdbc-kv + module: spring-data-jdbc + - name: java-spring-data-jpa-kv + module: spring-data-jpa concurrency: - group: slo-${{ github.ref }}-${{ matrix.sdk.name }} + group: slo-${{ github.ref }}-${{ matrix.workload.name }} cancel-in-progress: true steps: @@ -93,25 +99,43 @@ jobs: ref: master path: examples + - name: Checkout ydb-jdbc-driver + if: matrix.workload.module != 'query' + uses: actions/checkout@v5 + with: + repository: ydb-platform/ydb-jdbc-driver + ref: master + path: jdbc-driver + - name: Build current workload image run: | set -euxo pipefail chmod +x sdk-current/.github/scripts/build-slo-image.sh - sdk-current/.github/scripts/build-slo-image.sh \ - --sdk sdk-current \ - --examples examples \ - --tag ydb-app-current + args=( + --sdk sdk-current + --examples examples + --workload ${{ matrix.workload.module }} + --tag "ydb-app-current-${{ matrix.workload.module }}" + ) + if [ "${{ matrix.workload.module }}" != "query" ]; then + args+=(--jdbc jdbc-driver) + fi + sdk-current/.github/scripts/build-slo-image.sh "${args[@]}" - name: Build baseline workload image run: | set -euxo pipefail - # Reuse the build script from the current checkout — it doesn't - # depend on SDK contents, only on the layout it produces. - sdk-current/.github/scripts/build-slo-image.sh \ - --sdk sdk-baseline \ - --examples examples \ - --tag ydb-app-baseline \ - --fallback-image ydb-app-current + args=( + --sdk sdk-baseline + --examples examples + --workload ${{ matrix.workload.module }} + --tag "ydb-app-baseline-${{ matrix.workload.module }}" + --fallback-image "ydb-app-current-${{ matrix.workload.module }}" + ) + if [ "${{ matrix.workload.module }}" != "query" ]; then + args+=(--jdbc jdbc-driver) + fi + sdk-current/.github/scripts/build-slo-image.sh "${args[@]}" - name: Run SLO Tests uses: ydb-platform/ydb-slo-action/init@v2 @@ -119,41 +143,11 @@ jobs: with: github_issue: ${{ github.event.pull_request.number }} github_token: ${{ secrets.GITHUB_TOKEN }} - workload_name: ${{ matrix.sdk.name }} + workload_name: ${{ matrix.workload.name }} workload_duration: "600" workload_current_ref: ${{ github.head_ref || github.ref_name }} - workload_current_image: ydb-app-current - workload_current_command: ${{ matrix.sdk.command }} --read-rps 1000 --write-rps 100 + workload_current_image: ydb-app-current-${{ matrix.workload.module }} + workload_current_command: --read-rps 1000 --write-rps 100 workload_baseline_ref: ${{ steps.baseline.outputs.ref }} - workload_baseline_image: ydb-app-baseline - workload_baseline_command: ${{ matrix.sdk.command }} --read-rps 1000 --write-rps 100 - -# publish-slo-report: -# needs: ydb-slo-action -# runs-on: ubuntu-latest -# name: Publish YDB SLO Report -# permissions: -# issues: write -# checks: write -# contents: read -# pull-requests: write -# steps: -# - name: Checkout current SDK version -# uses: actions/checkout@v5 -# -# - name: Publish YDB SLO Report -# uses: ydb-platform/ydb-slo-action/report@v2 -# with: -# github_token: ${{ secrets.GITHUB_TOKEN }} -# github_run_id: ${{ github.event.workflow_run.id }} -# -# - name: Remove SLO label from PR -# env: -# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} -# PRS: ${{ toJSON(github.event.workflow_run.pull_requests) }} -# REPO: ${{ github.event.workflow_run.repository.full_name }} -# run: | -# set -euo pipefail -# PR=$(jq -r '.[0].number' <<<"$PRS") -# gh pr edit "$PR" --repo "$REPO" --remove-label SLO -# + workload_baseline_image: ydb-app-baseline-${{ matrix.workload.module }} + workload_baseline_command: --read-rps 1000 --write-rps 100 From 081e011700c3089813f7142856fd256da34b7c72 Mon Sep 17 00:00:00 2001 From: KirillKurdyukov Date: Thu, 18 Jun 2026 09:44:38 +0300 Subject: [PATCH 3/4] Fix SDK SLO matrix: build all workloads like query. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use shared examples Dockerfile.sdk (SDK install + ydb.sdk.version pin). Drop jdbc-driver checkout from java-sdk workflow — JDBC driver SLO stays in ydb-jdbc-driver. Co-authored-by: Cursor --- .github/scripts/build-slo-image.sh | 63 +++++++++++++----------------- .github/workflows/slo.yml | 36 +++++------------ 2 files changed, 36 insertions(+), 63 deletions(-) diff --git a/.github/scripts/build-slo-image.sh b/.github/scripts/build-slo-image.sh index c34be43b5..7aee21c0d 100755 --- a/.github/scripts/build-slo-image.sh +++ b/.github/scripts/build-slo-image.sh @@ -10,7 +10,6 @@ Usage: --examples \ --workload \ --tag \ - [--jdbc ] \ [--fallback-image ] Options: @@ -18,7 +17,6 @@ Options: --examples Path to the ydb-java-examples checkout. --workload SLO workload module to build. --tag Docker tag to assign to the built image. - --jdbc Path to ydb-jdbc-driver (required for JDBC workloads). --fallback-image If the initial Docker build fails, tag this image as --tag and exit successfully. EOF @@ -33,7 +31,6 @@ sdk_dir="" examples_dir="" workload="" tag="" -jdbc_dir="" fallback_image="" while [[ $# -gt 0 ]]; do @@ -54,10 +51,6 @@ while [[ $# -gt 0 ]]; do tag="${2:-}" shift 2 ;; - --jdbc) - jdbc_dir="${2:-}" - shift 2 - ;; --fallback-image) fallback_image="${2:-}" shift 2 @@ -77,31 +70,41 @@ if [[ -z "$sdk_dir" || -z "$examples_dir" || -z "$workload" || -z "$tag" ]]; the die "Incomplete argument set" fi +workload_module="" +workload_jar="" +copy_libs="false" + case "$workload" in - query|jdbc|spring-data-jdbc|spring-data-jpa) + query) + workload_module="slo-workload/query" + workload_jar="ydb-slo-query-workload.jar" + copy_libs="true" + ;; + jdbc) + workload_module="slo-workload/jdbc" + workload_jar="ydb-slo-jdbc-workload.jar" + copy_libs="true" + ;; + spring-data-jdbc) + workload_module="slo-workload/spring-data-jdbc" + workload_jar="ydb-slo-spring-data-jdbc-workload.jar" + ;; + spring-data-jpa) + workload_module="slo-workload/spring-data-jpa" + workload_jar="ydb-slo-spring-data-jpa-workload.jar" ;; *) die "Unsupported workload: $workload" ;; esac -if [[ "$workload" != "query" && -z "$jdbc_dir" ]]; then - die "--jdbc is required for workload ${workload}" -fi - [[ -d "$sdk_dir" ]] || die "--sdk does not exist: $sdk_dir" [[ -d "$examples_dir" ]] || die "--examples does not exist: $examples_dir" -if [[ -n "$jdbc_dir" ]]; then - [[ -d "$jdbc_dir" ]] || die "--jdbc does not exist: $jdbc_dir" -fi sdk_dir="$(cd "$sdk_dir" && pwd)" examples_dir="$(cd "$examples_dir" && pwd)" -if [[ -n "$jdbc_dir" ]]; then - jdbc_dir="$(cd "$jdbc_dir" && pwd)" -fi -dockerfile="${examples_dir}/slo-workload/${workload}/Dockerfile" +dockerfile="${examples_dir}/slo-workload/docker/Dockerfile.sdk" [[ -f "$dockerfile" ]] || die "Dockerfile not found: $dockerfile" context_dir="$(mktemp -d)" @@ -112,9 +115,6 @@ echo " ydb-java-sdk: $sdk_dir" echo " ydb-java-examples: $examples_dir" echo " workload: $workload" echo " tag: $tag" -if [[ -n "$jdbc_dir" ]]; then - echo " ydb-jdbc-driver: $jdbc_dir" -fi copy_tree() { local src="$1" @@ -128,31 +128,22 @@ copy_tree() { copy_tree "$sdk_dir" "$context_dir/ydb-java-sdk" copy_tree "$examples_dir" "$context_dir/ydb-java-examples" -if [[ -n "$jdbc_dir" ]]; then - copy_tree "$jdbc_dir" "$context_dir/ydb-jdbc-driver" -else - mkdir -p "$context_dir/ydb-jdbc-driver" -fi -rm -rf "$context_dir/ydb-java-sdk/.git" \ - "$context_dir/ydb-java-examples/.git" \ - "$context_dir/ydb-jdbc-driver/.git" +rm -rf "$context_dir/ydb-java-sdk/.git" "$context_dir/ydb-java-examples/.git" for required in \ "$context_dir/ydb-java-sdk/pom.xml" \ - "$context_dir/ydb-java-examples/slo-workload/${workload}/Dockerfile" + "$context_dir/ydb-java-examples/slo-workload/docker/Dockerfile.sdk" do [[ -f "$required" ]] || die "Build context missing required file: $required" done -if [[ "$workload" != "query" ]]; then - [[ -f "$context_dir/ydb-jdbc-driver/pom.xml" ]] \ - || die "Build context missing required file: $context_dir/ydb-jdbc-driver/pom.xml" -fi - set +e docker build \ --platform linux/amd64 \ + --build-arg "WORKLOAD_MODULE=${workload_module}" \ + --build-arg "WORKLOAD_JAR=${workload_jar}" \ + --build-arg "COPY_LIBS=${copy_libs}" \ -t "$tag" \ -f "$dockerfile" \ "$context_dir" diff --git a/.github/workflows/slo.yml b/.github/workflows/slo.yml index 4867b4736..50c8b6584 100644 --- a/.github/workflows/slo.yml +++ b/.github/workflows/slo.yml @@ -99,43 +99,25 @@ jobs: ref: master path: examples - - name: Checkout ydb-jdbc-driver - if: matrix.workload.module != 'query' - uses: actions/checkout@v5 - with: - repository: ydb-platform/ydb-jdbc-driver - ref: master - path: jdbc-driver - - name: Build current workload image run: | set -euxo pipefail chmod +x sdk-current/.github/scripts/build-slo-image.sh - args=( - --sdk sdk-current - --examples examples - --workload ${{ matrix.workload.module }} + sdk-current/.github/scripts/build-slo-image.sh \ + --sdk sdk-current \ + --examples examples \ + --workload ${{ matrix.workload.module }} \ --tag "ydb-app-current-${{ matrix.workload.module }}" - ) - if [ "${{ matrix.workload.module }}" != "query" ]; then - args+=(--jdbc jdbc-driver) - fi - sdk-current/.github/scripts/build-slo-image.sh "${args[@]}" - name: Build baseline workload image run: | set -euxo pipefail - args=( - --sdk sdk-baseline - --examples examples - --workload ${{ matrix.workload.module }} - --tag "ydb-app-baseline-${{ matrix.workload.module }}" + sdk-current/.github/scripts/build-slo-image.sh \ + --sdk sdk-baseline \ + --examples examples \ + --workload ${{ matrix.workload.module }} \ + --tag "ydb-app-baseline-${{ matrix.workload.module }}" \ --fallback-image "ydb-app-current-${{ matrix.workload.module }}" - ) - if [ "${{ matrix.workload.module }}" != "query" ]; then - args+=(--jdbc jdbc-driver) - fi - sdk-current/.github/scripts/build-slo-image.sh "${args[@]}" - name: Run SLO Tests uses: ydb-platform/ydb-slo-action/init@v2 From f2f78442796a070be9a7a885b6013bbd4ad565d6 Mon Sep 17 00:00:00 2001 From: KirillKurdyukov Date: Thu, 18 Jun 2026 10:43:16 +0300 Subject: [PATCH 4/4] Add SLO report job after matrix workloads complete. Publish a combined PR comment via ydb-slo-action/report once all init jobs finish, then remove the SLO label to avoid accidental re-runs. Co-authored-by: Cursor --- .github/workflows/slo.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/.github/workflows/slo.yml b/.github/workflows/slo.yml index 50c8b6584..cacc939fb 100644 --- a/.github/workflows/slo.yml +++ b/.github/workflows/slo.yml @@ -133,3 +133,33 @@ jobs: workload_baseline_ref: ${{ steps.baseline.outputs.ref }} workload_baseline_image: ydb-app-baseline-${{ matrix.workload.module }} workload_baseline_command: --read-rps 1000 --write-rps 100 + + publish-slo-report: + needs: ydb-slo-action + if: ${{ always() && !cancelled() }} + + name: Publish YDB SLO Report + runs-on: ubuntu-latest + + permissions: + contents: read + pull-requests: write + checks: write + + steps: + - name: Publish YDB SLO Report + uses: ydb-platform/ydb-slo-action/report@v2 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + github_run_id: ${{ github.run_id }} + github_issue: ${{ github.event.pull_request.number }} + + - name: Remove SLO label from PR + if: github.event_name == 'pull_request' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + gh pr edit "${{ github.event.pull_request.number }}" \ + --repo "${{ github.repository }}" \ + --remove-label SLO