Skip to content

feat(orca): v0.6.4 — quickstart command + --version flag #520

feat(orca): v0.6.4 — quickstart command + --version flag

feat(orca): v0.6.4 — quickstart command + --version flag #520

Workflow file for this run

# Phase 2: Build Verification
#
# When a plugin has a `build` section, this workflow:
# 1. Clones the developer's source repo at the pinned commit SHA
# 2. Fetches dependencies + runs security audit
# 3. Compiles the project
# 4. Validates the artifact
# 5. Posts a build report to the PR
#
# Source code is EXTERNAL (Homebrew model):
# - plugin.yaml has: build.source_repo + build.source_commit
# - We clone at exact SHA → compile → publish our artifact
# - Community repo stays small (no source code stored)
#
# SECURITY: Split into isolated jobs to prevent Pwn Request attacks.
# - gate: blocks fork PRs that modify .github/
# - collect: zero permissions, checkouts fork code, collects data as artifact
# - build jobs: have write perms, only checkout main, process artifact data
name: "Phase 2: Build Verification"
on:
pull_request_target:
paths:
- 'skills/**'
types: [opened, synchronize, reopened]
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
# ═══════════════════════════════════════════════════════════════
# Security Gate — block fork PRs that modify .github/
# ═══════════════════════════════════════════════════════════════
gate:
name: Security gate
runs-on: ubuntu-latest
permissions:
pull-requests: read
outputs:
safe: ${{ steps.check.outputs.safe }}
steps:
- uses: actions/checkout@v4
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
fetch-depth: 0
- name: Block .github modifications from forks
id: check
run: |
echo "Checking PR for .github/ modifications..."
CHANGES=$(git diff --name-only origin/main...${{ github.event.pull_request.head.sha }} | grep "^\.github/" || true)
if [ -n "$CHANGES" ]; then
echo "::error::Fork PRs cannot modify .github/ files:"
echo "$CHANGES"
echo "safe=false" >> "$GITHUB_OUTPUT"
exit 1
fi
echo "No .github/ modifications detected"
echo "safe=true" >> "$GITHUB_OUTPUT"
# ═══════════════════════════════════════════════════════════════
# Collect — zero permissions sandbox, checkout fork code
# ═══════════════════════════════════════════════════════════════
collect:
name: Collect plugin data
needs: gate
runs-on: ubuntu-latest
permissions: {}
outputs:
plugin_dir: ${{ steps.find.outputs.plugin_dir }}
plugin_name: ${{ steps.find.outputs.plugin_name }}
has_build: ${{ steps.find.outputs.has_build }}
build_lang: ${{ steps.find.outputs.build_lang }}
source_repo: ${{ steps.find.outputs.source_repo }}
source_commit: ${{ steps.find.outputs.source_commit }}
source_dir: ${{ steps.find.outputs.source_dir }}
source_mode: ${{ steps.find.outputs.source_mode }}
local_source_dir: ${{ steps.find.outputs.local_source_dir }}
binary_name: ${{ steps.find.outputs.binary_name }}
build_main: ${{ steps.find.outputs.build_main }}
steps:
- uses: actions/checkout@v4
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
fetch-depth: 0
- name: Find plugin and parse build config
id: find
run: |
CHANGED=$(git diff --name-only origin/main...${{ github.event.pull_request.head.sha }} -- 'skills/' | head -100)
PLUGIN_NAME=$(echo "$CHANGED" | head -1 | cut -d'/' -f2)
# Validate plugin name (prevent injection via malicious folder names)
if ! echo "$PLUGIN_NAME" | grep -qE '^[a-zA-Z0-9_-]+$'; then
echo "::error::Invalid plugin name: contains special characters"
exit 1
fi
PLUGIN_DIR="skills/${PLUGIN_NAME}"
echo "plugin_dir=${PLUGIN_DIR}" >> "$GITHUB_OUTPUT"
echo "plugin_name=${PLUGIN_NAME}" >> "$GITHUB_OUTPUT"
YAML_FILE="${PLUGIN_DIR}/plugin.yaml"
if [ ! -f "$YAML_FILE" ]; then
echo "has_build=false" >> "$GITHUB_OUTPUT"
exit 0
fi
# Parse all build fields at once
YAML_FILE="$YAML_FILE" PLUGIN_DIR="$PLUGIN_DIR" python3 << 'PYEOF'
import yaml, os
yaml_file = os.environ["YAML_FILE"]
plugin_dir = os.environ["PLUGIN_DIR"]
with open(yaml_file) as f:
data = yaml.safe_load(f)
build = data.get("build")
out = os.environ.get("GITHUB_OUTPUT", "/dev/null")
with open(out, "a") as gh:
if not build:
gh.write("has_build=false\n")
else:
gh.write("has_build=true\n")
gh.write(f"build_lang={build.get('lang', '')}\n")
repo = build.get('source_repo', '')
commit = build.get('source_commit', '')
gh.write(f"source_repo={repo}\n")
gh.write(f"source_commit={commit}\n")
sd = build.get('source_dir', '.')
gh.write(f"source_dir={'' if sd == '.' else sd}\n")
gh.write(f"binary_name={build.get('binary_name', '')}\n")
gh.write(f"build_main={build.get('main', '')}\n")
# source_mode: "local" if no external repo, "external" if repo specified
if repo:
gh.write("source_mode=external\n")
else:
gh.write("source_mode=local\n")
gh.write(f"local_source_dir={plugin_dir}\n")
PYEOF
# ── Collect plugin files as artifact (for local-source builds) ──
- name: Collect plugin files
run: |
mkdir -p /tmp/plugin-data
PLUGIN_DIR="skills/${{ steps.find.outputs.plugin_name }}"
if [ -d "$PLUGIN_DIR" ]; then
cp -r "$PLUGIN_DIR" /tmp/plugin-data/
fi
- uses: actions/upload-artifact@v4
with:
name: plugin-data
path: /tmp/plugin-data/
# ═══ Clone source repo (shared step) ════════════════════════
# Each build job clones the external repo at the pinned commit SHA.
# This is a YAML anchor pattern — each job repeats the clone step.
# ═══════════════════════════════════════════════════════════════
# Rust Build
# ═══════════════════════════════════════════════════════════════
build-rust:
name: Build (Rust)
needs: collect
if: needs.collect.outputs.has_build == 'true' && needs.collect.outputs.build_lang == 'rust'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
# No repository/ref override = checkouts main (trusted code)
- uses: actions/download-artifact@v4
if: needs.collect.outputs.source_mode != 'external'
with:
name: plugin-data
path: /tmp/plugin-data/
- name: Prepare source
run: |
if [ "${{ needs.collect.outputs.source_mode }}" = "external" ] && [ -n "${{ needs.collect.outputs.source_repo }}" ]; then
git clone "https://github.com/${{ needs.collect.outputs.source_repo }}.git" /tmp/source
cd /tmp/source && git checkout "${{ needs.collect.outputs.source_commit }}"
echo "Checked out $(git rev-parse HEAD)"
else
PLUGIN_NAME="${{ needs.collect.outputs.plugin_name }}"
LOCAL_DIR="${{ needs.collect.outputs.local_source_dir }}"
[ -z "$LOCAL_DIR" ] && LOCAL_DIR="${{ needs.collect.outputs.plugin_dir }}"
ARTIFACT_DIR="/tmp/plugin-data/${PLUGIN_NAME}"
if [ -d "$ARTIFACT_DIR" ]; then
cp -r "$ARTIFACT_DIR" /tmp/source
else
cp -r "$LOCAL_DIR" /tmp/source
fi
echo "Using local source from artifact"
fi
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Fetch dependencies
working-directory: /tmp/source/${{ needs.collect.outputs.source_dir }}
run: cargo fetch
- name: Security audit
working-directory: /tmp/source/${{ needs.collect.outputs.source_dir }}
run: |
cargo install cargo-audit 2>/dev/null || true
cargo audit 2>&1 || true
- name: Build
working-directory: /tmp/source/${{ needs.collect.outputs.source_dir }}
run: cargo build --release 2>&1 | tail -20
- name: Verify artifact
id: verify
run: |
BIN="/tmp/source/${{ needs.collect.outputs.source_dir }}/target/release/${{ needs.collect.outputs.binary_name }}"
if [ -f "$BIN" ]; then
chmod +x "$BIN"
SIZE=$(stat -c%s "$BIN" 2>/dev/null || stat -f%z "$BIN")
echo "size=$((SIZE / 1024 / 1024))MB" >> "$GITHUB_OUTPUT"
echo "status=pass" >> "$GITHUB_OUTPUT"
sha256sum "$BIN"
else
echo "::error::Binary not found at $BIN"
echo "status=fail" >> "$GITHUB_OUTPUT"
fi
- name: Upload artifact
if: steps.verify.outputs.status == 'pass'
uses: actions/upload-artifact@v4
with:
name: build-rust-${{ needs.collect.outputs.plugin_name }}
path: /tmp/source/${{ needs.collect.outputs.source_dir }}/target/release/${{ needs.collect.outputs.binary_name }}
# ═══════════════════════════════════════════════════════════════
# Go Build
# ═══════════════════════════════════════════════════════════════
build-go:
name: Build (Go)
needs: collect
if: needs.collect.outputs.has_build == 'true' && needs.collect.outputs.build_lang == 'go'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
# No repository/ref override = checkouts main (trusted code)
- uses: actions/download-artifact@v4
if: needs.collect.outputs.source_mode != 'external'
with:
name: plugin-data
path: /tmp/plugin-data/
- name: Prepare source
run: |
if [ "${{ needs.collect.outputs.source_mode }}" = "external" ] && [ -n "${{ needs.collect.outputs.source_repo }}" ]; then
git clone "https://github.com/${{ needs.collect.outputs.source_repo }}.git" /tmp/source
cd /tmp/source && git checkout "${{ needs.collect.outputs.source_commit }}"
echo "Checked out $(git rev-parse HEAD)"
else
PLUGIN_NAME="${{ needs.collect.outputs.plugin_name }}"
LOCAL_DIR="${{ needs.collect.outputs.local_source_dir }}"
[ -z "$LOCAL_DIR" ] && LOCAL_DIR="${{ needs.collect.outputs.plugin_dir }}"
ARTIFACT_DIR="/tmp/plugin-data/${PLUGIN_NAME}"
if [ -d "$ARTIFACT_DIR" ]; then
cp -r "$ARTIFACT_DIR" /tmp/source
else
cp -r "$LOCAL_DIR" /tmp/source
fi
echo "Using local source from artifact"
fi
- uses: actions/setup-go@v5
with:
go-version: '1.22'
- name: Fetch dependencies
working-directory: /tmp/source/${{ needs.collect.outputs.source_dir }}
run: go mod download
- name: Security check
working-directory: /tmp/source/${{ needs.collect.outputs.source_dir }}
run: |
go install golang.org/x/vuln/cmd/govulncheck@latest 2>/dev/null || true
govulncheck ./... 2>&1 || true
- name: Build
working-directory: /tmp/source/${{ needs.collect.outputs.source_dir }}
env:
CGO_ENABLED: 0
run: go build -o "${{ needs.collect.outputs.binary_name }}" -ldflags="-s -w" .
- name: Verify artifact
id: verify
run: |
BIN="/tmp/source/${{ needs.collect.outputs.source_dir }}/${{ needs.collect.outputs.binary_name }}"
if [ -f "$BIN" ]; then
SIZE=$(stat -c%s "$BIN")
echo "size=$((SIZE / 1024 / 1024))MB" >> "$GITHUB_OUTPUT"
echo "status=pass" >> "$GITHUB_OUTPUT"
sha256sum "$BIN"
else
echo "status=fail" >> "$GITHUB_OUTPUT"
fi
- name: Upload artifact
if: steps.verify.outputs.status == 'pass'
uses: actions/upload-artifact@v4
with:
name: build-go-${{ needs.collect.outputs.plugin_name }}
path: /tmp/source/${{ needs.collect.outputs.source_dir }}/${{ needs.collect.outputs.binary_name }}
# ═══════════════════════════════════════════════════════════════
# TypeScript Build (Bun compile)
# ═══════════════════════════════════════════════════════════════
build-typescript:
name: Build (TypeScript)
needs: collect
if: needs.collect.outputs.has_build == 'true' && needs.collect.outputs.build_lang == 'typescript'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
# No repository/ref override = checkouts main (trusted code)
- uses: actions/download-artifact@v4
if: needs.collect.outputs.source_mode != 'external'
with:
name: plugin-data
path: /tmp/plugin-data/
- name: Prepare source
run: |
if [ "${{ needs.collect.outputs.source_mode }}" = "external" ] && [ -n "${{ needs.collect.outputs.source_repo }}" ]; then
git clone "https://github.com/${{ needs.collect.outputs.source_repo }}.git" /tmp/source
cd /tmp/source && git checkout "${{ needs.collect.outputs.source_commit }}"
echo "Checked out $(git rev-parse HEAD)"
else
PLUGIN_NAME="${{ needs.collect.outputs.plugin_name }}"
LOCAL_DIR="${{ needs.collect.outputs.local_source_dir }}"
[ -z "$LOCAL_DIR" ] && LOCAL_DIR="${{ needs.collect.outputs.plugin_dir }}"
ARTIFACT_DIR="/tmp/plugin-data/${PLUGIN_NAME}"
if [ -d "$ARTIFACT_DIR" ]; then
cp -r "$ARTIFACT_DIR" /tmp/source
else
cp -r "$LOCAL_DIR" /tmp/source
fi
echo "Using local source from artifact"
fi
- uses: oven-sh/setup-bun@v2
- name: Install dependencies
working-directory: /tmp/source/${{ needs.collect.outputs.source_dir }}
run: bun install
- name: Compile to binary
working-directory: /tmp/source/${{ needs.collect.outputs.source_dir }}
run: bun build --compile "${{ needs.collect.outputs.build_main }}" --outfile "${{ needs.collect.outputs.binary_name }}"
- name: Verify artifact
id: verify
run: |
BIN="/tmp/source/${{ needs.collect.outputs.source_dir }}/${{ needs.collect.outputs.binary_name }}"
if [ -f "$BIN" ]; then
SIZE=$(stat -c%s "$BIN")
echo "size=$((SIZE / 1024 / 1024))MB" >> "$GITHUB_OUTPUT"
echo "status=pass" >> "$GITHUB_OUTPUT"
sha256sum "$BIN"
else
echo "status=fail" >> "$GITHUB_OUTPUT"
fi
- name: Upload artifact
if: steps.verify.outputs.status == 'pass'
uses: actions/upload-artifact@v4
with:
name: build-ts-${{ needs.collect.outputs.plugin_name }}
path: /tmp/source/${{ needs.collect.outputs.source_dir }}/${{ needs.collect.outputs.binary_name }}
# ═══════════════════════════════════════════════════════════════
# Node.js (npm pack)
# ═══════════════════════════════════════════════════════════════
build-node:
name: Build (Node.js)
needs: collect
if: needs.collect.outputs.has_build == 'true' && needs.collect.outputs.build_lang == 'node'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
# No repository/ref override = checkouts main (trusted code)
- uses: actions/download-artifact@v4
if: needs.collect.outputs.source_mode != 'external'
with:
name: plugin-data
path: /tmp/plugin-data/
- name: Prepare source
run: |
if [ "${{ needs.collect.outputs.source_mode }}" = "external" ] && [ -n "${{ needs.collect.outputs.source_repo }}" ]; then
git clone "https://github.com/${{ needs.collect.outputs.source_repo }}.git" /tmp/source
cd /tmp/source && git checkout "${{ needs.collect.outputs.source_commit }}"
echo "Checked out $(git rev-parse HEAD)"
else
PLUGIN_NAME="${{ needs.collect.outputs.plugin_name }}"
LOCAL_DIR="${{ needs.collect.outputs.local_source_dir }}"
[ -z "$LOCAL_DIR" ] && LOCAL_DIR="${{ needs.collect.outputs.plugin_dir }}"
ARTIFACT_DIR="/tmp/plugin-data/${PLUGIN_NAME}"
if [ -d "$ARTIFACT_DIR" ]; then
cp -r "$ARTIFACT_DIR" /tmp/source
else
cp -r "$LOCAL_DIR" /tmp/source
fi
echo "Using local source from artifact"
fi
- uses: oven-sh/setup-bun@v2
- name: Install dependencies
working-directory: /tmp/source/${{ needs.collect.outputs.source_dir }}
run: bun install
- name: Compile to binary
working-directory: /tmp/source/${{ needs.collect.outputs.source_dir }}
run: bun build --compile "${{ needs.collect.outputs.build_main }}" --outfile "${{ needs.collect.outputs.binary_name }}"
- name: Verify artifact
id: verify
run: |
BIN="/tmp/source/${{ needs.collect.outputs.source_dir }}/${{ needs.collect.outputs.binary_name }}"
if [ -f "$BIN" ]; then
SIZE=$(stat -c%s "$BIN")
echo "size=$((SIZE / 1024 / 1024))MB" >> "$GITHUB_OUTPUT"
echo "status=pass" >> "$GITHUB_OUTPUT"
sha256sum "$BIN"
else
echo "status=fail" >> "$GITHUB_OUTPUT"
fi
- name: Upload artifact
if: steps.verify.outputs.status == 'pass'
uses: actions/upload-artifact@v4
with:
name: build-node-${{ needs.collect.outputs.plugin_name }}
path: /tmp/source/${{ needs.collect.outputs.source_dir }}/${{ needs.collect.outputs.binary_name }}
# ═══════════════════════════════════════════════════════════════
# Python Validation (pip install — no binary packaging)
# Python plugins are distributed as pip packages, not binaries.
# Users install via pip/pipx at runtime.
# ═══════════════════════════════════════════════════════════════
build-python:
name: Build (Python)
needs: collect
if: needs.collect.outputs.has_build == 'true' && needs.collect.outputs.build_lang == 'python'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
# No repository/ref override = checkouts main (trusted code)
- uses: actions/download-artifact@v4
if: needs.collect.outputs.source_mode != 'external'
with:
name: plugin-data
path: /tmp/plugin-data/
- name: Prepare source
run: |
if [ "${{ needs.collect.outputs.source_mode }}" = "external" ] && [ -n "${{ needs.collect.outputs.source_repo }}" ]; then
git clone "https://github.com/${{ needs.collect.outputs.source_repo }}.git" /tmp/source
cd /tmp/source && git checkout "${{ needs.collect.outputs.source_commit }}"
echo "Checked out $(git rev-parse HEAD)"
else
PLUGIN_NAME="${{ needs.collect.outputs.plugin_name }}"
LOCAL_DIR="${{ needs.collect.outputs.local_source_dir }}"
[ -z "$LOCAL_DIR" ] && LOCAL_DIR="${{ needs.collect.outputs.plugin_dir }}"
ARTIFACT_DIR="/tmp/plugin-data/${PLUGIN_NAME}"
if [ -d "$ARTIFACT_DIR" ]; then
cp -r "$ARTIFACT_DIR" /tmp/source
else
cp -r "$LOCAL_DIR" /tmp/source
fi
echo "Using local source from artifact"
fi
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Check Python version requirements
working-directory: /tmp/source/${{ needs.collect.outputs.source_dir }}
run: |
# Extract requires-python from pyproject.toml if present
if [ -f pyproject.toml ]; then
REQUIRES=$(python3 -c "
import tomllib
with open('pyproject.toml', 'rb') as f:
data = tomllib.load(f)
print(data.get('project', {}).get('requires-python', 'not specified'))
" 2>/dev/null || echo "not specified")
echo "requires-python: $REQUIRES"
fi
- name: Install package
working-directory: /tmp/source/${{ needs.collect.outputs.source_dir }}
run: |
pip install pip-audit
pip install -e . 2>/dev/null || pip install -r requirements.txt 2>/dev/null || pip install . || {
echo "::error::pip install failed — this package cannot be installed"
exit 1
}
echo "pip install succeeded"
- name: Security audit
run: pip-audit 2>&1 || true
- name: Verify entry point works
id: verify
working-directory: /tmp/source/${{ needs.collect.outputs.source_dir }}
run: |
MAIN="${{ needs.collect.outputs.build_main }}"
BIN="${{ needs.collect.outputs.binary_name }}"
# Check if the entry point script runs
if [ -n "$MAIN" ] && python3 "$MAIN" --help > /dev/null 2>&1; then
echo "Entry point $MAIN responds to --help"
echo "status=pass" >> "$GITHUB_OUTPUT"
elif command -v "$BIN" > /dev/null 2>&1; then
echo "Installed command $BIN found in PATH"
echo "status=pass" >> "$GITHUB_OUTPUT"
else
echo "status=pass" >> "$GITHUB_OUTPUT"
echo "::warning::Could not verify entry point, but pip install succeeded"
fi
# Report package info
pip show "$(python3 -c "
import tomllib
with open('pyproject.toml', 'rb') as f:
print(tomllib.load(f).get('project', {}).get('name', ''))
" 2>/dev/null || echo '')" 2>/dev/null || true
# ═══════════════════════════════════════════════════════════════
# Build Report
# ═══════════════════════════════════════════════════════════════
report:
name: Build report
needs: [collect, build-rust, build-go, build-typescript, build-node, build-python]
if: always() && needs.collect.outputs.has_build == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: Post build report
uses: actions/github-script@v7
env:
BUILD_LANG: ${{ needs.collect.outputs.build_lang }}
PLUGIN_NAME: ${{ needs.collect.outputs.plugin_name }}
SOURCE_REPO: ${{ needs.collect.outputs.source_repo }}
SOURCE_COMMIT: ${{ needs.collect.outputs.source_commit }}
with:
script: |
const lang = process.env.BUILD_LANG;
const pluginName = process.env.PLUGIN_NAME;
const sourceRepo = process.env.SOURCE_REPO;
const sourceCommit = process.env.SOURCE_COMMIT;
const results = {
rust: '${{ needs.build-rust.result }}',
go: '${{ needs.build-go.result }}',
typescript: '${{ needs.build-typescript.result }}',
node: '${{ needs.build-node.result }}',
python: '${{ needs.build-python.result }}',
};
const result = results[lang] || 'skipped';
const passed = result === 'success';
const icon = passed ? '✅' : (result === 'skipped' ? '⏭️' : '❌');
const status = passed ? 'PASSED' : (result === 'skipped' ? 'SKIPPED' : 'FAILED');
const shortSha = sourceCommit.substring(0, 8);
const body = [
`## 🔨 Phase 2: Build Verification — ${icon} ${status}`,
'',
`> **Plugin**: \`${pluginName}\` | **Language**: \`${lang}\``,
`> **Source**: [\`${sourceRepo}@${shortSha}\`](https://github.com/${sourceRepo}/tree/${sourceCommit})`,
`> `,
`> *Compiled from developer source code by our CI. Users install our build artifacts.*`,
'',
passed
? 'Build succeeded. Compiled artifact uploaded as workflow artifact.'
: result === 'skipped'
? 'No build configuration — Skill-only plugin.'
: `Build failed. Check the [workflow logs](${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}).`,
'',
'---',
`*Source integrity: commit SHA \`${sourceCommit}\` is the content fingerprint.*`
].join('\n');
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: ${{ github.event.pull_request.number }},
});
const botComment = comments.find(c =>
c.user.type === 'Bot' && c.body.includes('Phase 2: Build Verification')
);
const params = { owner: context.repo.owner, repo: context.repo.repo, body };
if (botComment) {
await github.rest.issues.updateComment({ ...params, comment_id: botComment.id });
} else {
await github.rest.issues.createComment({ ...params, issue_number: ${{ github.event.pull_request.number }} });
}