From b74a34a94603736124ab223d56e5f901f22ba671 Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Sat, 19 Aug 2023 19:04:33 +0400 Subject: [PATCH] ci(label): trigger workflows on labelling (#3070) --- .github/actions/label/build.js | 179 ++++++++++++++++++++++++++++++ .github/workflows/build-macos.yml | 56 ++++++++++ .github/workflows/build.yml | 46 +------- .github/workflows/label.yml | 30 +++++ 4 files changed, 268 insertions(+), 43 deletions(-) create mode 100644 .github/actions/label/build.js create mode 100644 .github/workflows/build-macos.yml create mode 100644 .github/workflows/label.yml diff --git a/.github/actions/label/build.js b/.github/actions/label/build.js new file mode 100644 index 00000000000..39503e28172 --- /dev/null +++ b/.github/actions/label/build.js @@ -0,0 +1,179 @@ +/** + * Javascript module for the label action. + */ + +const [owner, repo] = ["gear-tech", "gear"]; +const { LABEL, REF, HEAD_SHA } = process.env; +const linux = LABEL === "A0-pleasereview"; +const checks = linux ? ["linux", "win-cross"] : ["x86"]; +const workflow_id = linux + ? ".github/workflows/build.yml" + : ".github/workflows/build-macos.yml"; + +/** + * Sleep for ms milliseconds. + **/ +const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); + +/** + * If skipping this action. + **/ +const skip = async ({ github }) => { + const { + data: { check_runs }, + } = await github.rest.checks.listForRef({ + owner, + repo, + ref: REF, + }); + + const runs = linux + ? check_runs.filter((run) => run.name === "build" || run.name === "build / linux") + : check_runs.filter((run) => run.name === "build / macox-x86"); + + if (runs.length === 0) return false; + for (run of runs) { + if (run.conclusion !== "skipped") return true; + } + + return false; +}; + +/** + * Create build checks. + * + * TODO: + * * Queue the new created checks to check suite PR (#3087). + * * Support re-runing the checks. (#3088) + **/ +const createChecks = async ({ core, github }) => { + let status = {}; + for (check of checks) { + const { data: res } = await github.rest.checks.create({ + owner, + repo, + name: `build / ${check}`, + head_sha: HEAD_SHA, + }); + + core.info(`Created check ${check}`); + status[check] = res; + } + + return status; +}; + +/** + * Dispatch the target workflow. + */ +const dispatchWorkflow = async ({ core, github }) => { + await github.rest.actions.createWorkflowDispatch({ + owner, + repo, + workflow_id, + ref: REF, + }); + + await sleep(10000); + + // Get the target workflow run + const { + data: { workflow_runs }, + } = await github.rest.actions.listWorkflowRuns({ + owner, + repo, + workflow_id, + head_sha: HEAD_SHA, + }); + + if (workflow_runs.length != 1) { + core.setFailed(`Incorrect workflow runs`); + return; + } + + return workflow_runs[0]; +}; + +/// List jobs of workflow run. +const listJobs = async ({ github, core, run_id }) => { + const { + data: { jobs }, + } = await github.rest.actions.listJobsForWorkflowRun({ + owner, + repo, + run_id, + }); + + if (jobs.length === 0) { + core.setFailed(`Empty jobs from dispatched workflow`); + return; + } + + const requiredJobs = jobs.filter((job) => checks.includes(job.name)); + if (requiredJobs.length !== checks.length) { + core.setFailed(`Incorrect count for disptached jobs`); + return; + } + + return requiredJobs; +}; + +/** + * The main function. + **/ +module.exports = async ({ github, core }) => { + if (await skip({ github })) { + core.info("Build has already been processed."); + return; + } + + const run = await dispatchWorkflow({ core, github }); + let labelChecks = await createChecks({ core, github }); + + while (true) { + const jobs = await listJobs({ github, core, run_id: run.id }); + completed = jobs.filter((job) => job.status === "completed").length; + + for (job of jobs) { + let checkJob = labelChecks[job.name]; + if ( + checkJob.status !== job.status || + checkJob.conclusion !== job.conclusion + ) { + core.info( + `Updating check ${job.name}, status: ${job.status}, conclusion: ${job.conclusion}` + ); + + let { status, conclusion } = job; + + let data = { + owner, + repo, + check_run_id: checkJob.id, + status, + output: { + title: `Build ${job.name}`, + summary: `ref ${job.html_url}`, + }, + }; + + labelChecks[job.name].status = status; + if (conclusion) { + data.conclusion = conclusion; + labelChecks[job.name].conclusion = conclusion; + } + + await github.rest.checks.update(data); + } else { + continue; + } + } + + if (completed === checks.length) { + core.info("All jobs completed."); + break; + } else { + await sleep(10000); + } + } +}; diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml new file mode 100644 index 00000000000..8ab63dd12da --- /dev/null +++ b/.github/workflows/build-macos.yml @@ -0,0 +1,56 @@ +name: Build MacOS + +on: + workflow_call: + workflow_dispatch: + +env: + CARGO_INCREMENTAL: 0 + CARGO_TERM_COLOR: always + RUST_BACKTRACE: short + TERM: xterm-256color + BINARYEN_VERSION: version_111 + +jobs: + x86: + runs-on: macos-latest + env: + RUSTUP_HOME: /tmp/rustup_home + steps: + - name: "ACTIONS: Checkout" + uses: actions/checkout@v3 + + - name: "ACTIONS: Setup caching" + uses: actions/cache@v3 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo- + + - name: "Install: protobuf" + run: brew install protobuf + + - name: "Install: Rust toolchain" + uses: dsherret/rust-toolchain-file@v1 + + - name: "Install: cargo-nextest" + run: curl -LsSf https://get.nexte.st/latest/mac | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin + + - name: "Build: Node" + run: >- + cargo build + -p gear-cli --features=lazy-pages + + - name: "Test: Lazy pages" + run: >- + cargo nextest run + -p "pallet-*" + -p gear-lazy-pages + -p gear-runtime-interface + --features=lazy-pages diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 56712d14826..0aaf814d993 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -247,47 +247,7 @@ jobs: env: CARGO_BUILD_TARGET: x86_64-pc-windows-msvc - macos-x86: - if: ${{ always() && inputs.macos }} + macos: needs: linux - runs-on: macos-latest - env: - RUSTUP_HOME: /tmp/rustup_home - steps: - - name: "ACTIONS: Checkout" - uses: actions/checkout@v3 - - - name: "ACTIONS: Setup caching" - uses: actions/cache@v3 - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-cargo- - - - name: "Install: protobuf" - run: brew install protobuf - - - name: "Install: Rust toolchain" - uses: dsherret/rust-toolchain-file@v1 - - - name: "Install: cargo-nextest" - run: curl -LsSf https://get.nexte.st/latest/mac | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin - - - name: "Build: Node" - run: >- - cargo build - -p gear-cli --features=lazy-pages - - - name: "Test: Lazy pages" - run: >- - cargo nextest run - -p "pallet-*" - -p gear-lazy-pages - -p gear-runtime-interface - --features=lazy-pages + if: ${{ always() && inputs.macos }} + uses: ./.github/workflows/build-macos.yml diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml new file mode 100644 index 00000000000..187032b8adc --- /dev/null +++ b/.github/workflows/label.yml @@ -0,0 +1,30 @@ +name: Label + +on: + pull_request: + branches: [master, vara-stage-1, vara-stage-2, vara-stage-3] + types: [labeled] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + dispatch: + runs-on: ubuntu-latest + if: >- + github.event.label.name == 'A0-pleasereview' + || github.event.label.name == 'E2-forcemacos' + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - uses: actions/github-script@v6 + env: + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + LABEL: ${{ github.event.label.name }} + REF: ${{ github.head_ref || github.ref_name }} + with: + script: | + const script = require('./.github/actions/label/build.js'); + await script({ github, core });