-
Notifications
You must be signed in to change notification settings - Fork 26
feat: Integrate Arbiter discovery pipeline #117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
67cfa82
97caf8e
ceb4e29
5dd4899
740c735
4039d7b
c6c6bef
eaf7b81
11ca6ee
5dd93d7
0d5adbc
377eb9a
bf0cd13
9a99b8f
8e2e746
8974a67
6fc7c21
3aa682b
00231f6
809923d
0dd25a7
a4b4ba9
a9a90d4
8dacca0
2240187
809cebb
be041fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,175 @@ | ||
| name: Arazzo Workflow Validation | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main, feature/arbiter-discovery-pipeline] | ||
| paths: | ||
| - "workflows/**" | ||
| - "plex-api-spec.yaml" | ||
| - ".github/workflows/arazzo-validation.yml" | ||
| pull_request: | ||
| branches: [main] | ||
| paths: | ||
| - "workflows/**" | ||
| - "plex-api-spec.yaml" | ||
| - ".github/workflows/arazzo-validation.yml" | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| concurrency: | ||
| group: arazzo-validation-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| validate: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout plex-api-spec | ||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Clone Arbiter | ||
| run: | | ||
| git clone https://github.com/LukasParke/arbiter.git ../arbiter | ||
|
|
||
| - name: Set up Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '24' | ||
|
|
||
| - name: Setup pnpm | ||
| uses: pnpm/action-setup@v4 | ||
| with: | ||
| version: latest | ||
|
|
||
| - name: Build Arbiter | ||
| run: | | ||
| cd ../arbiter | ||
| pnpm install --frozen-lockfile | ||
| pnpm run build | ||
|
|
||
| - name: Set up Docker Compose | ||
| uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2320ee5c88db75466b73 # v3.10.0 | ||
|
|
||
| - name: Start Plex Media Server | ||
| run: | | ||
| docker compose up -d pms | ||
| for i in {1..60}; do | ||
| if curl -sf http://localhost:32400/identity > /dev/null 2>&1; then | ||
| echo "PMS is ready" | ||
| break | ||
| fi | ||
| echo "Waiting for PMS... ($i/60)" | ||
| sleep 5 | ||
| done | ||
| env: | ||
| PLEX_CLAIM_TOKEN: ${{ secrets.PLEX_CLAIM_TOKEN }} | ||
|
|
||
| - name: Extract Plex Token | ||
| id: plex-token | ||
| run: | | ||
| # Wait for Plex to finish initialization and generate token | ||
| for i in {1..30}; do | ||
| TOKEN=$(docker exec plex-api-test cat /config/Library/Application\ Support/Plex\ Media\ Server/Preferences.xml 2>/dev/null | grep -oP 'PlexOnlineToken="\K[^"]+' || true) | ||
| if [ -n "$TOKEN" ]; then | ||
| echo "token=$TOKEN" >> $GITHUB_OUTPUT | ||
| echo "Found Plex token" | ||
| break | ||
| fi | ||
| echo "Waiting for Plex token... ($i/30)" | ||
| sleep 5 | ||
| done | ||
|
|
||
| # Fallback: use a test token if available | ||
| if [ -z "${{ steps.plex-token.outputs.token }}" ]; then | ||
| echo "token=test-token" >> $GITHUB_OUTPUT | ||
| echo "Using fallback test token" | ||
| fi | ||
|
|
||
| - name: Start Arbiter Proxy with Validation | ||
| run: | | ||
| cd ../arbiter | ||
| node dist/src/cli.js start \ | ||
| --target http://localhost:32400 \ | ||
| --port 8080 \ | ||
| --docs-port 9000 \ | ||
| --db-path /tmp/arbiter.db \ | ||
| --validate \ | ||
| --spec "$GITHUB_WORKSPACE/plex-api-spec.yaml" \ | ||
| --verbose > /tmp/arbiter.log 2>&1 & | ||
| PROXY_PID=$! | ||
| echo "PROXY_PID=$PROXY_PID" >> $GITHUB_ENV | ||
|
|
||
| for i in {1..30}; do | ||
| if curl -sf http://localhost:8080/identity > /dev/null 2>&1; then | ||
| echo "Arbiter proxy is ready (with validation enabled)" | ||
| break | ||
| fi | ||
| echo "Waiting for arbiter proxy... ($i/30)" | ||
| sleep 1 | ||
| done | ||
|
|
||
| - name: Install Redocly Respect | ||
| run: | | ||
| npm install -g @redocly/cli@latest | ||
| npx @redocly/cli@latest --version | ||
|
|
||
| - name: Lint Arazzo Workflows | ||
| run: | | ||
| for wf in workflows/*.yaml; do | ||
| echo "=== Linting $(basename $wf) ===" | ||
| npx @redocly/cli@latest lint "$wf" || exit 1 | ||
| done | ||
|
|
||
| - name: Run Arazzo Tests via Arbiter Proxy | ||
| run: | | ||
| FAILED=0 | ||
| for wf in workflows/*.yaml; do | ||
| echo "" | ||
| echo "========================================" | ||
| echo "=== Running $(basename $wf) ===" | ||
| echo "========================================" | ||
| npx @redocly/cli@latest respect "$wf" \ | ||
| --input plexToken=${{ steps.plex-token.outputs.token }} \ | ||
| --input baseUrl=http://localhost:8080 \ | ||
| || FAILED=1 | ||
| done | ||
| exit $FAILED | ||
|
|
||
| - name: Collect Arbiter Validation Log | ||
| if: always() | ||
| run: | | ||
| echo "=== Arbiter Proxy Validation Log ===" > /tmp/validation-summary.log | ||
| if [ -f /tmp/arbiter.log ]; then | ||
| grep -E "\[VALIDATE\]|Proxy error|Diff Report|Missing endpoints|Query param gaps" /tmp/arbiter.log >> /tmp/validation-summary.log || true | ||
| cat /tmp/validation-summary.log | ||
| fi | ||
|
|
||
| - name: Stop Arbiter Proxy | ||
| if: always() | ||
| run: | | ||
| kill $PROXY_PID 2>/dev/null || true | ||
| sleep 2 | ||
|
|
||
| - name: Stop Plex Media Server | ||
| if: always() | ||
| run: docker compose down | ||
|
|
||
| - name: Upload Arbiter Log | ||
| if: always() | ||
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | ||
| with: | ||
| name: arbiter-validation-log | ||
| path: /tmp/arbiter.log | ||
| retention-days: 7 | ||
|
|
||
| - name: Upload Validation Summary | ||
| if: always() | ||
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | ||
| with: | ||
| name: validation-summary | ||
| path: /tmp/validation-summary.log | ||
| retention-days: 7 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| name: Nightly Discovery Pipeline | ||
|
|
||
| on: | ||
| schedule: | ||
| - cron: '0 6 * * *' | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
| actions: write | ||
|
|
||
| concurrency: | ||
| group: nightly-discovery | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| discover: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout plex-api-spec | ||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Clone Arbiter | ||
| run: | | ||
| git clone https://github.com/LukasParke/arbiter.git ../arbiter | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| - name: Set up Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '24' | ||
|
|
||
| - name: Setup pnpm | ||
| uses: pnpm/action-setup@v4 | ||
| with: | ||
| version: latest | ||
|
|
||
| - name: Build Arbiter | ||
| run: | | ||
| cd ../arbiter | ||
| pnpm install --frozen-lockfile | ||
| pnpm run build | ||
|
|
||
| - name: Set up Docker Compose | ||
| uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2320ee5c88db75466b73 # v3.10.0 | ||
|
|
||
| - name: Start Plex Media Server | ||
| run: | | ||
| docker compose up -d pms | ||
| # Wait for PMS to be healthy | ||
| for i in {1..60}; do | ||
| if curl -sf http://localhost:32400/identity > /dev/null 2>&1; then | ||
| echo "PMS is ready" | ||
| break | ||
| fi | ||
| echo "Waiting for PMS... ($i/60)" | ||
| sleep 5 | ||
| done | ||
|
Comment on lines
+48
to
+59
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fail fast when the readiness loops exhaust, sir. Both polls merely finish their retries and then carry on. If PMS or Arbiter never becomes reachable, the workflow stumbles into later steps and fails with a misleading symptom instead of stopping at the actual fault. 🎩 A modest remedy - name: Start Plex Media Server
run: |
docker compose up -d pms
# Wait for PMS to be healthy
for i in {1..60}; do
if curl -sf http://localhost:32400/identity > /dev/null 2>&1; then
echo "PMS is ready"
break
fi
echo "Waiting for PMS... ($i/60)"
sleep 5
done
+ curl -sf http://localhost:32400/identity > /dev/null 2>&1 || {
+ echo "PMS failed to become ready" >&2
+ docker compose logs pms || true
+ exit 1
+ }
@@
- name: Start Arbiter Proxy
run: |
cd ../arbiter
node dist/src/cli.js start \
--target http://localhost:32400 \
--port 8080 \
--docs-port 9000 \
--db-path /tmp/arbiter.db \
--verbose &
PROXY_PID=$!
echo "PROXY_PID=$PROXY_PID" >> $GITHUB_ENV
# Wait for proxy
for i in {1..30}; do
if curl -sf http://localhost:8080/identity > /dev/null 2>&1; then
echo "Proxy is ready"
break
fi
echo "Waiting for proxy... ($i/30)"
sleep 1
done
+ curl -sf http://localhost:8080/identity > /dev/null 2>&1 || {
+ echo "Arbiter failed to become ready" >&2
+ exit 1
+ }Also applies to: 63-82 🤖 Prompt for AI Agents |
||
| env: | ||
| PLEX_CLAIM_TOKEN: ${{ secrets.PLEX_CLAIM_TOKEN }} | ||
|
|
||
| - name: Start Arbiter Proxy | ||
| run: | | ||
| cd ../arbiter | ||
| node dist/src/cli.js start \ | ||
| --target http://localhost:32400 \ | ||
| --port 8080 \ | ||
| --docs-port 9000 \ | ||
| --db-path /tmp/arbiter.db \ | ||
| --verbose & | ||
| PROXY_PID=$! | ||
| echo "PROXY_PID=$PROXY_PID" >> $GITHUB_ENV | ||
| # Wait for proxy | ||
| for i in {1..30}; do | ||
| if curl -sf http://localhost:8080/identity > /dev/null 2>&1; then | ||
| echo "Proxy is ready" | ||
| break | ||
| fi | ||
| echo "Waiting for proxy... ($i/30)" | ||
| sleep 1 | ||
| done | ||
|
|
||
| - name: Generate Traffic | ||
| run: | | ||
| cd ../arbiter | ||
| node dist/src/cli.js generate-traffic \ | ||
| --target http://localhost:8080 \ | ||
| --output /tmp/traffic.jsonl | ||
|
|
||
| - name: Stop Arbiter Proxy | ||
| run: | | ||
| kill $PROXY_PID || true | ||
| sleep 2 | ||
|
|
||
| - name: Run Diff | ||
| run: | | ||
| cd ../arbiter | ||
| node dist/src/cli.js diff \ | ||
| --spec ./plex-api-spec/plex-api-spec.yaml \ | ||
| --traffic /tmp/traffic.jsonl \ | ||
| --output /tmp/diff_report.json | ||
|
Comment on lines
+96
to
+102
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The diff step points at the wrong spec path, sir. After 🎩 A steadier path - name: Run Diff
run: |
cd ../arbiter
node dist/src/cli.js diff \
- --spec ./plex-api-spec/plex-api-spec.yaml \
+ --spec "$GITHUB_WORKSPACE/plex-api-spec.yaml" \
--traffic /tmp/traffic.jsonl \
--output /tmp/diff_report.json🤖 Prompt for AI Agents |
||
|
|
||
| - name: Stop Plex Media Server | ||
| if: always() | ||
| run: docker compose down | ||
|
|
||
| - name: Upload diff report | ||
| if: always() | ||
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | ||
| with: | ||
| name: diff-report | ||
| path: /tmp/diff_report.json | ||
|
|
||
| - name: Upload traffic capture | ||
| if: always() | ||
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | ||
| with: | ||
| name: traffic-capture | ||
| path: /tmp/traffic.jsonl | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,71 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: Lint OpenAPI Spec | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pray add least-privilege token scope and disable checkout credential persistence. Your workflow in Suggested least-privilege patch name: Lint OpenAPI Spec
on:
@@
+permissions:
+ contents: read
+
jobs:
prettier:
@@
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: false
@@
speakeasy:
@@
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: false
@@
vacuum:
@@
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: false📝 Committable suggestion
Suggested change
🧰 Tools🪛 zizmor (1.25.2)[warning] 3-13: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting (concurrency-limits) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| push: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| branches: [main] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| paths: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - "plex-api-spec.yaml" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - ".github/workflows/lint.yml" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pull_request: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| branches: [main] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| paths: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - "plex-api-spec.yaml" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - ".github/workflows/lint.yml" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+3
to
+13
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win A modest concurrency guard would save wasted runner time. Adding workflow concurrency here prevents older in-flight runs from consuming CI minutes once superseded by newer commits. Suggested concurrency block on:
@@
+concurrency:
+ group: lint-openapi-${{ github.ref }}
+ cancel-in-progress: true📝 Committable suggestion
Suggested change
🧰 Tools🪛 zizmor (1.25.2)[warning] 3-13: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting (concurrency-limits) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| prettier: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - uses: actions/setup-node@v4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+19
to
+20
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
FILE=".github/workflows/lint.yml"
echo "== File: $FILE =="
wc -l "$FILE"
sed -n '1,200p' "$FILE" | nl -baRepository: LukasParke/plex-api-spec Length of output: 198 🏁 Script executed: #!/bin/bash
set -euo pipefail
FILE=".github/workflows/lint.yml"
echo "== File: $FILE =="
wc -l "$FILE"
sed -n '1,200p' "$FILE" | nl -baRepository: LukasParke/plex-api-spec Length of output: 198 🏁 Script executed: #!/bin/bash
set -euo pipefail
FILE=".github/workflows/lint.yml"
echo "== File: $FILE =="
wc -l "$FILE"
echo "== Contents (with line numbers) =="
cat -n "$FILE" | sed -n '1,120p'Repository: LukasParke/plex-api-spec Length of output: 1583 🌐 Web query:
💡 Result: The default value of actions/checkout v4 input persist-credentials is true (i.e., credentials/token or SSH key are configured in the local git config by default). [1][2] The README also states the behavior: “The auth token is persisted in the local git config… Set persist-credentials: false to opt-out.” [2] Citations:
🌐 Web query:
💡 Result: By default, GitHub Actions grants the GITHUB_TOKEN the repository/organization/enterprise “Workflow permissions” defaults set for the repo; you only override those defaults when you add a permissions: block to the workflow/job. GitHub’s docs also note that if a workflow uses the permissions key, any scopes you do not explicitly set are denied (with an exception for metadata, which always gets read access). [1][2] What this means when you do NOT set any permissions block: 1) The GITHUB_TOKEN permissions start as the default “Workflow permissions” configuration for your repository (which may be restricted or permissive depending on org/enterprise settings). [1] 2) For new repositories in a personal account, GitHub states the default is “only has read access for the contents and packages scopes.” [1] 3) If you set a permissions key at all (workflow/job), then unspecified permissions become “no access”, except metadata which is always read. [3] So, for the specific case “no permissions block is set”, the practical answer is: you get whatever the repo’s configured default workflow permissions are (often restricted to read-only contents and packages for personal repos); you don’t get automatic broad read/write just because the workflow omitted the block. [1][4] Citations:
🏁 Script executed: #!/bin/bash
set -euo pipefail
ls -la
find . -maxdepth 2 -type f \( -name "package.json" -o -name "package-lock.json" -o -name "pnpm-lock.yaml" -o -name "yarn.lock" \) -printRepository: LukasParke/plex-api-spec Length of output: 1167 🌐 Web query:
💡 Result: The default value for the persist-credentials input in actions/checkout v4 is true [1][2][3]. When set to true (the default), the action configures the authentication token or SSH key with the local git configuration [1][3]. This allows your subsequent workflow steps to perform authenticated git commands [3][4]. The token is automatically removed during the post-job cleanup process [3][5]. To prevent the action from persisting these credentials, you can explicitly set persist-credentials to false [3][4]. Citations:
🌐 Web query:
💡 Result: When no permissions block is defined in a GitHub Actions workflow, the GITHUB_TOKEN permissions default to the settings configured at the repository, organization, or enterprise level [1][2]. Repositories newly created on GitHub today typically have a restricted default setting where the GITHUB_TOKEN is granted read-only access to the contents and packages scopes [1][3]. However, this behavior depends on the specific settings chosen by repository or organization administrators [1][2]. Administrators can configure the default GITHUB_TOKEN permissions via the repository or organization settings under Actions > General > Workflow permissions [1][4]. There are generally two configurable options: 1. Permissive: Read and write access for all scopes [1][5]. 2. Restricted: Read-only access for repository contents and packages [1][5]. If a repository belongs to an organization, it will inherit the organization's default permission setting unless a more restrictive setting is enforced [1][2]. Furthermore, regardless of these default settings, the GITHUB_TOKEN is always downgraded to read-only access when a workflow is triggered by a pull request from a forked repository (unless the specific repository setting to send write tokens to workflows from pull requests is enabled) [5][2]. It is considered a security best practice to explicitly define the required permissions in the workflow file using the permissions key to follow the principle of least privilege [6][2]. Citations:
🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== Top-level files =="
ls -la
echo "== Lockfiles / package manifests (max depth 2) =="
find . -maxdepth 2 -type f \( -name "package.json" -o -name "package-lock.json" -o -name "pnpm-lock.yaml" -o -name "yarn.lock" \) -printRepository: LukasParke/plex-api-spec Length of output: 1239 Pin GitHub Actions to full commit SHAs (and harden mutable downloads) — most certainly, sir. In
Suggested hardening patch- - uses: actions/checkout@v4
+ - uses: actions/checkout@<FULL_COMMIT_SHA_FOR_V4>
...
- - uses: actions/setup-node@v4
+ - uses: actions/setup-node@<FULL_COMMIT_SHA_FOR_V4>
...
- - uses: speakeasy-api/sdk-generation-action@v15
+ - uses: speakeasy-api/sdk-generation-action@<FULL_COMMIT_SHA_FOR_V15>
...
- - uses: actions/checkout@v4
+ - uses: actions/checkout@<FULL_COMMIT_SHA_FOR_V4>🧰 Tools🪛 zizmor (1.25.2)[warning] 19-19: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false (artipacked) [error] 19-19: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) [error] 20-20: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| node-version: '20' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - run: npm install prettier prettier-plugin-openapi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
# Show lint workflow around the referenced line
echo "=== .github/workflows/lint.yml (lines 1-120) ==="
nl -ba .github/workflows/lint.yml | sed -n '1,120p'
# Confirm npm install usage in the workflow(s)
echo
echo "=== Search for 'npm install' in .github/workflows ==="
rg -n "npm (install|ci)" .github/workflows || true
# Check for package-lock presence (needed for npm ci)
echo
echo "=== Check for package-lock.json ==="
ls -la package-lock.json 2>/dev/null || trueRepository: LukasParke/plex-api-spec Length of output: 178 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== .github/workflows/lint.yml (lines 1-200) ==="
sed -n '1,200p' .github/workflows/lint.yml
echo
echo "=== Search for 'npm install' / 'npm ci' in .github/workflows ==="
rg -n "npm (install|ci)" .github/workflows || true
echo
echo "=== Check for package-lock.json / npm-shrinkwrap.json ==="
ls -la package-lock.json npm-shrinkwrap.json 2>/dev/null || true
echo
echo "=== Check if repo uses pnpm/yarn instead of npm ==="
ls -la yarn.lock pnpm-lock.yaml 2>/dev/null || trueRepository: LukasParke/plex-api-spec Length of output: 1560 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== Inspect package.json ==="
ls -la package.json || true
cat package.json
echo
echo "=== Check whether prettier-plugin-openapi is in package-lock.json ==="
rg -n "\"prettier-plugin-openapi\"" package-lock.json || true
echo
echo "=== Check whether prettier is in package-lock.json ==="
rg -n "\"prettier\"" package-lock.json | head -n 20 || trueRepository: LukasParke/plex-api-spec Length of output: 535 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== package-lock.json header ==="
head -n 40 package-lock.jsonRepository: LukasParke/plex-api-spec Length of output: 1441 🌐 Web query:
💡 Result: For Citations: Avoid a floating Suggested deterministic install- - run: npm install prettier prettier-plugin-openapi
+ - run: npm ci --include=dev📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - run: npx prettier --check plex-api-spec.yaml | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| speakeasy: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Install Speakeasy | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| curl -fsSL https://raw.githubusercontent.com/speakeasy-api/speakeasy/main/install.sh | sh | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| speakeasy --version | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - run: speakeasy lint openapi -s plex-api-spec.yaml | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| vacuum: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contents: read | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Install Vacuum | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| gh release download --repo daveshanley/vacuum --pattern '*linux_x86_64.tar.gz' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tar -xzf vacuum_*_linux_x86_64.tar.gz | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sudo mv vacuum /usr/local/bin/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+43
to
+47
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
# Inspect the workflow content around the referenced lines
FILE=".github/workflows/lint.yml"
echo "== File: $FILE =="
nl -ba "$FILE" | sed -n '1,120p'
nl -ba "$FILE" | sed -n '30,70p'
# Extract just the Install Vacuum step for precise comparison
echo "== Install Vacuum step (context) =="
rg -n "Install Vacuum|vacuum_linux_amd64|releases/latest" "$FILE" -n || trueRepository: LukasParke/plex-api-spec Length of output: 168 🏁 Script executed: #!/bin/bash
set -euo pipefail
FILE=".github/workflows/lint.yml"
echo "== File: $FILE =="
awk '{printf "%4d\t%s\n", NR, $0}' "$FILE" | sed -n '1,120p'
echo "== Around lines 39-42 =="
awk '{printf "%4d\t%s\n", NR, $0}' "$FILE" | sed -n '30,70p'
echo "== Matches for vacuum install =="
rg -n "Vacuum|vacuum_linux_amd64|releases/latest|vacuum/releases" "$FILE" || trueRepository: LukasParke/plex-api-spec Length of output: 2209 🌐 Web query:
💡 Result: Vacuum (daveshanley) GitHub release checksums location/lookup: For a given version X.Y.Z, the installer script fetches the checksum file from: https://github.com/daveshanley/vacuum/releases/download/v$1/checksums.txt [1] It then selects the expected SHA-256 by grepping for the asset name (which in the release assets is of the form vacuum__linux_x86_64.tar.gz; the script maps machine types so amd64/x86_64 become x86_64) [1]. Example for the latest releases around today (2026-06-03): - v0.27.2 release exists on GitHub [2] and includes checksums.txt as a release asset [2]. - v0.27.1 release exists on GitHub [3] and includes checksums.txt as a release asset [3]. Important: I could not retrieve the actual checksum line value for “vacuum_linux_amd64 checksums.txt sha256” from the GitHub release asset contents within the provided search results. However, the authoritative way to get the exact SHA-256 is to download the release’s checksums.txt and read the line for the linux amd64 artifact (which corresponds to linux_x86_64 in the installer’s naming) [1]. How to get the sha256 yourself (matches the project’s installer logic): 1) Pick the version tag (e.g., v0.27.2) [2]. 2) Download checksums.txt: curl -sSL "https://github.com/daveshanley/vacuum/releases/download/v0.27.2/checksums.txt" -o checksums.txt 3) Extract the sha256 for the linux amd64 artifact name used by the installer (linux_x86_64): grep "vacuum_0.27.2_linux_x86_64.tar.gz" checksums.txt | awk '{print $1}' If you tell me which exact version tag you mean (e.g., v0.27.2) I can re-run a targeted lookup specifically for that version’s linux amd64 checksum entry. Citations:
🌐 Web query:
💡 Result: The script located at https://raw.githubusercontent.com/daveshanley/vacuum/main/bin/install.sh is an automated installer for the vacuum OpenAPI linter [1][2]. It is designed to detect the user's operating system and architecture, download the appropriate release binary from GitHub, verify it against a checksums.txt file, and install it into a local directory [1]. Regarding your query about finding the SHA256 checksum for vacuum_linux_x86_64, the installation script itself does not contain hardcoded checksums. Instead, it dynamically downloads a checksums.txt file from the specific release version's assets on GitHub [1][3]. To obtain the current checksum for a specific version, you should: 1. Visit the official GitHub releases page for daveshanley/vacuum: https://github.com/daveshanley/vacuum/releases [4]. 2. Select the desired version (e.g., v0.27.2) [5][6]. 3. Locate and download the checksums.txt file under the "Assets" section of that release [7][8][9]. 4. Grep for the specific binary to see its corresponding hash, for example: grep vacuum_linux_x86_64 checksums.txt The vacuum project is an OpenAPI linter written in Go [4][5]. The primary installation method recommended by the author involves using the install script via curl (curl -fsSL https://quobix.com/scripts/install_vacuum.sh | sh) or using tools like Homebrew [10][4]. Citations:
Pin and checksum-verify Vacuum; avoid 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| vacuum version | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Lint with Vacuum | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| vacuum lint plex-api-spec.yaml \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --details \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --pipeline-output \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --no-banner \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --min-score 25 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Generate Vacuum Report | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if: always() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| vacuum report plex-api-spec.yaml report-prefix --no-pretty | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Upload Vacuum Report | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if: always() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uses: actions/upload-artifact@v4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: vacuum-report | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path: report-prefix*.json | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| retention-days: 30 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
actions: writegrant exceeds this errand's modest needs, sir.Neither
actions/checkoutnoractions/upload-artifact@v4calls upon theactionsAPI scope — artifact uploads ride upon the runtime token rather than this permission. In the spirit of least privilege (and to silence zizmor'sexcessive-permissionsreproach), I should counsel removing it. An explanatory comment would also appease theundocumented-permissionsadvisory.🎩 A more frugal allotment
🧰 Tools
🪛 zizmor (1.25.2)
[error] 10-10: overly broad permissions (excessive-permissions): actions: write is overly broad at the workflow level
(excessive-permissions)
[warning] 10-10: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment
(undocumented-permissions)
🤖 Prompt for AI Agents