Skip to content

Add AI Actions Report workflow using GitHub Models#165

Merged
igorpecovnik merged 10 commits intomainfrom
ai
Jan 15, 2026
Merged

Add AI Actions Report workflow using GitHub Models#165
igorpecovnik merged 10 commits intomainfrom
ai

Conversation

@igorpecovnik
Copy link
Member

@igorpecovnik igorpecovnik commented Jan 13, 2026

Summary

  • Adds a new GitHub Actions workflow (generate-actions-report.yml) that generates a comprehensive JSON report of all workflows and actions in the repository
  • Includes a Node.js script (generate-actions-report.mjs) that scans .github/workflows/ for workflow files and action definitions
  • Uses GitHub Models (GPT-4o-mini) to generate concise, accurate descriptions of each workflow/action's purpose
  • Reports include: name, AI-generated description, execution method, links, and timestamps

Features

  • Can be triggered manually via workflow_dispatch with configurable parameters (scan folder, default branch)
  • Can also run automatically on push
  • Generates actions-report.json artifact with structured data about all automation
  • Configurable scan root folder and default branch for generated links
  • Supports GitHub Models (default, free), Z.ai, and Anthropic Claude as AI providers
  • Uses the built-in GITHUB_TOKEN for free access to AI models
  • Automatic retry with exponential backoff when hitting rate limits (4s, 8s, 16s, 32s, 64s)
  • Timestamp tracking: edited (last file modification) and executed (last workflow run)
  • Report displayed in GitHub Actions summary for easy viewing

Output Fields

  • name: Workflow/action filename
  • description: AI-generated description of what the workflow does
  • execution_method: Triggers and entrypoints
  • status_link: Link to workflow status page (for workflows)
  • script_link: Link to the source file
  • edited: ISO 8601 timestamp of last file modification
  • executed: ISO 8601 timestamp of last workflow run (workflows only)

Configuration

The workflow uses GitHub Models by default with the GITHUB_TOKEN, which is automatically available in GitHub Actions and provides free access to GPT-4o-mini.

Test plan

  • Workflow runs successfully when triggered manually
  • Verify actions-report.json artifact is produced
  • Check that report includes all workflows with accurate descriptions
  • Confirm script and status links are correctly generated
  • Verify rate limit handling with exponential backoff

@github-actions github-actions bot added 02 Milestone: First quarter release size/large PR with 250 lines or more GitHub Actions GitHub Actions code GitHub GitHub-related changes like labels, templates, ... Needs review Seeking for review labels Jan 13, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 13, 2026

Warning

Rate limit exceeded

@igorpecovnik has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minutes and 23 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 51d5763 and e915ffc.

📒 Files selected for processing (1)
  • .github/workflows/generate-actions-report.yml

Walkthrough

This PR introduces infrastructure for automated AI-generated documentation of GitHub workflows and actions. It adds a new GitHub Actions workflow that runs nightly and on manual dispatch, scanning workflow YAML files and generating structured JSON reports. The workflow fetches workflow execution metrics via GitHub API, uses AI providers (z.ai, Anthropic Claude, OpenAI) to generate descriptions, implements caching and rate-limit retry logic, and merges reports into a data branch. The README is simplified to reference this new system with a single link to explore all action workflows.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

ready to merge

Suggested reviewers

  • armbianworker
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a GitHub Actions workflow for generating AI-powered action reports using GitHub Models.
Description check ✅ Passed The PR description comprehensively explains the changes, including the new workflow file, Node.js script, AI provider support, features, output fields, and test plan.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ai

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai bot requested a review from armbianworker January 13, 2026 13:34
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
scripts/claude-actions-report.mjs (2)

36-52: Consider edge case with nested JSON or multiple objects.

The fallback extraction using indexOf("{") and lastIndexOf("}") works for single-object responses but could misbehave if Claude returns text like "Here's your JSON: {...} and another {...}". For this specific use case where Claude is instructed to return strict JSON, this is likely fine.


145-158: Add request timeout to prevent indefinite hangs.

The fetch call lacks a timeout, which could cause the workflow to hang indefinitely if the API is unresponsive. Consider using AbortController to add a timeout.

♻️ Proposed fix
+  const controller = new AbortController();
+  const timeout = setTimeout(() => controller.abort(), 60000); // 60s timeout
+
   const res = await fetch(API_URL, {
     method: "POST",
     headers: {
       "content-type": "application/json",
       "x-api-key": apiKey,
       "anthropic-version": "2023-06-01",
     },
     body: JSON.stringify(body),
+    signal: controller.signal,
-  });
+  }).finally(() => clearTimeout(timeout));
.github/workflows/generate-actions-report.yml (3)

3-14: Consider limiting push trigger to specific branches.

The push trigger without branch filters will run on every push to any branch, which could consume unnecessary API credits and workflow minutes. Consider limiting to the default branch or specific branches.

♻️ Proposed fix
 on:
   push:
+    branches:
+      - main
   workflow_dispatch:

36-44: Input defaults not applied on push trigger.

When triggered by push, inputs.scan_root and inputs.default_branch will be empty strings (not the defaults defined in workflow_dispatch). This works because the script uses || which treats empty strings as falsy, but for clarity, you could use GitHub's expression syntax to provide defaults.

♻️ Proposed fix for explicit defaults
       - name: Generate report
         env:
           ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
           CLAUDE_MODEL: claude-sonnet-4-5
-          SCAN_ROOT: ${{ inputs.scan_root }}
-          REPO_DEFAULT_BRANCH: ${{ inputs.default_branch }}
+          SCAN_ROOT: ${{ inputs.scan_root || '.github' }}
+          REPO_DEFAULT_BRANCH: ${{ inputs.default_branch || 'main' }}
         run: |
           node scripts/claude-actions-report.mjs

31-34: Consider pinning dependency versions for reproducibility.

Installing dependencies without version specifiers (npm i fast-glob js-yaml) could lead to non-reproducible builds if packages introduce breaking changes.

♻️ Proposed fix
       - name: Install deps
         run: |
           npm init -y
-          npm i fast-glob js-yaml
+          npm i fast-glob@3 js-yaml@4
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 08883e8 and ded6daf.

📒 Files selected for processing (2)
  • .github/workflows/generate-actions-report.yml
  • scripts/claude-actions-report.mjs
🔇 Additional comments (10)
scripts/claude-actions-report.mjs (8)

1-26: LGTM on imports and module setup.

The shebang, documentation header, and imports are well-structured. The JSDoc-style header clearly documents the expected environment variables and output format.


27-34: LGTM!

The requiredEnv function correctly validates required environment variables and exits with an appropriate error code.


54-62: LGTM!

Both file classification functions are correctly implemented with proper cross-platform path handling and case-insensitive checks where appropriate.


64-85: LGTM!

The link generation correctly uses GitHub Actions environment variables with appropriate fallbacks for local execution.


87-109: LGTM!

The execution method summarization covers the various formats for workflow triggers (string, array, object) and action run configurations.


162-176: LGTM on response parsing.

The response parsing correctly handles Anthropic's content block format and provides useful error messages with truncated raw text for debugging.


178-244: LGTM on main function implementation.

The main function has good error resilience:

  • YAML parse failures gracefully fallback to null
  • Claude API errors are caught and produce a descriptive fallback
  • Content is truncated to avoid oversized payloads
  • Sequential processing naturally avoids rate limiting

246-249: LGTM!

Standard error handling pattern for CLI scripts with appropriate exit code.

.github/workflows/generate-actions-report.yml (2)

16-21: LGTM on job configuration.

Good security practice with minimal contents: read permissions.


45-49: LGTM on artifact upload.

The artifact upload step is correctly configured. Consider adding retention-days if you want to limit storage costs, but the default is reasonable.

@igorpecovnik igorpecovnik changed the title Add Claude Actions Report workflow and script Add Z.ai Actions Report workflow and script Jan 13, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @scripts/claude-actions-report.mjs:
- Line 265: The chosen default Anthropic model identifier is invalid; update the
default in the model assignment so that when provider === "zai" is false the
Claude model uses a valid dated identifier (i.e., replace "claude-sonnet-4-5"
with a dated tag such as "claude-sonnet-4-5-20250929" or the latest valid
version), keeping the ability to override via process.env.AI_MODEL and
preserving the provider === "zai" branch logic that yields "glm-4.7".
🧹 Nitpick comments (1)
scripts/claude-actions-report.mjs (1)

162-174: Consider adding a request timeout.

The fetch call has no timeout, which could cause the script to hang indefinitely if the API is slow or unresponsive. This is especially relevant in CI environments where job timeouts may be longer than desired.

♻️ Suggested improvement using AbortController
+  const controller = new AbortController();
+  const timeout = setTimeout(() => controller.abort(), 60000); // 60s timeout
+
   const res = await fetch(ZAI_API_URL, {
     method: "POST",
     headers: {
       "content-type": "application/json",
       "authorization": `Bearer ${apiKey}`,
     },
     body: JSON.stringify(body),
+    signal: controller.signal,
-  });
+  }).finally(() => clearTimeout(timeout));
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ded6daf and b6fbdf2.

📒 Files selected for processing (2)
  • .github/workflows/generate-actions-report.yml
  • scripts/claude-actions-report.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/generate-actions-report.yml
🔇 Additional comments (10)
scripts/claude-actions-report.mjs (10)

1-27: LGTM!

Clear documentation of the script's purpose, output schema, and environment variables. Imports are appropriate for the file scanning and YAML parsing tasks.


28-38: LGTM!

Good use of distinct exit codes (2 for config errors vs 1 for runtime errors) and clear error messaging.


40-47: LGTM!

Provider validation is correct with a sensible default and clear error messaging.


49-65: LGTM!

The fallback JSON extraction handles common LLM output patterns where JSON is wrapped in extra text. The simple brace-matching approach is sufficient for the expected flat JSON schema.


67-75: LGTM!

Correct file type detection with proper path normalization for cross-platform compatibility.


77-98: LGTM!

Proper handling of GitHub context with graceful fallback for local execution. Link construction follows correct GitHub URL patterns.


100-122: LGTM!

Comprehensive parsing of workflow triggers and action run configurations. Handles all common on block formats (string, array, object).


192-257: LGTM!

Correct Anthropic Messages API integration with proper headers and response parsing. The same timeout recommendation from the z.ai call applies here as well.


276-325: LGTM!

Robust per-file error handling ensures the report is generated even if some AI calls fail. The fallback to parsedExecution preserves useful information when AI fails.


332-335: LGTM!

Standard error handling pattern with appropriate exit code for runtime errors.

@igorpecovnik igorpecovnik changed the title Add Z.ai Actions Report workflow and script Add AI Actions Report workflow using GitHub Models Jan 13, 2026
@igorpecovnik igorpecovnik force-pushed the ai branch 8 times, most recently from 430a8ad to 39ac92c Compare January 13, 2026 17:57
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
scripts/claude-actions-report.mjs (2)

156-163: Note on timestamp accuracy in CI environments.

The mtime from fs.stat reflects the filesystem modification time, which in CI environments typically equals the checkout time rather than the actual last commit time. For accurate "last edited" timestamps, consider using Git log:

// Alternative using git log for accurate commit time
async function getFileEditTime(filePath) {
  try {
    const { execSync } = await import('node:child_process');
    const timestamp = execSync(`git log -1 --format=%aI -- "${filePath}"`, { encoding: 'utf8' }).trim();
    return timestamp || null;
  } catch {
    // Fallback to mtime if git is unavailable
    const stats = await fs.stat(filePath);
    return stats.mtime.toISOString();
  }
}

This may be acceptable if the current behavior is intentional.


262-331: Consider extracting shared prompt logic.

The callZai and callOpenAI functions share identical prompt construction (lines 263-288 duplicate lines 191-216). Consider extracting the shared logic to reduce maintenance burden.

♻️ Suggested refactor
function buildPrompt(fileKind, relPath, content, parsedExecution) {
  const systemContent = [
    "You are a senior DevOps engineer.",
    // ... rest of system prompt
  ].join("\n");

  const userContent = [
    `File kind: ${fileKind}`,
    `Path: ${relPath}`,
    `Parsed execution hint: ${parsedExecution}`,
    "",
    "File content:",
    content,
  ].join("\n");

  return { systemContent, userContent };
}
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b6fbdf2 and 39ac92c.

📒 Files selected for processing (2)
  • .github/workflows/generate-actions-report.yml
  • scripts/claude-actions-report.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/generate-actions-report.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-report
🔇 Additional comments (12)
scripts/claude-actions-report.mjs (12)

1-34: LGTM!

Clear documentation header with env vars, output schema, and appropriate imports for the task.


35-57: LGTM!

Exponential backoff implementation is correct. The retry logic properly distinguishes rate-limit errors from other failures and escalates wait times appropriately (4s → 8s → 16s → 32s → 64s).


59-70: LGTM!

The OPENAI_API_URL points to GitHub Models (Azure-hosted inference), which aligns with the PR description mentioning "GitHub Models (default: GPT-4o-mini via GITHUB_TOKEN)". The exit code 2 for missing env vars is appropriate for distinguishing configuration errors from runtime failures.


72-79: LGTM!

Provider validation is correct with a sensible default.


81-97: LGTM!

Robust JSON extraction that handles AI responses with extraneous text around JSON. The fallback strategy using first/last brace matching is practical given the strict JSON instruction in prompts.


99-107: LGTM!

File type detection is correct for standard GitHub Actions layouts, with proper Windows path normalization.


109-130: LGTM!

Link generation logic correctly handles both GitHub.com and GitHub Enterprise Server via GITHUB_SERVER_URL, with appropriate fallbacks when repository context is unavailable.


132-154: LGTM!

The execution method extraction handles the various forms of workflow triggers (string, array, object) and action runner configurations defensively.


190-260: LGTM!

The Z.ai integration is well-structured with clear prompts, appropriate error handling, and correct use of the retry mechanism.


333-402: LGTM with minor note.

The Anthropic API integration correctly uses the Messages API format with proper headers. The anthropic-version: 2023-06-01 is the stable version and should continue working.


404-488: Main function is well-structured.

The flow is logical: glob files → parse YAML → call AI → collect metadata → write report. Good defensive handling with the try/catch around AI calls (lines 446-461) ensuring one file's failure doesn't break the entire report.

Note: The authentication issue at line 471 (passing AI provider key instead of GITHUB_TOKEN to getLastWorkflowRunTime) was flagged in an earlier comment.


490-493: LGTM!

Standard error handling pattern with appropriate exit code (1 for runtime errors, distinguishing from exit code 2 used for configuration errors).

@igorpecovnik igorpecovnik force-pushed the ai branch 2 times, most recently from 60773a8 to adb8b8b Compare January 13, 2026 20:14
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @scripts/claude-actions-report.mjs:
- Around line 174-197: getLastWorkflowRunTime is being called with provider API
keys (ZAI_API_KEY/ANTHROPIC_API_KEY) so GitHub auth fails; update the call site
that invokes getLastWorkflowRunTime to pass process.env.GITHUB_TOKEN (not the
provider apiKey) and ensure the workflow identifier you pass is the workflow
filename (e.g., "build.yml") instead of the YAML `name`; you can also rename the
parameter in getLastWorkflowRunTime to githubToken for clarity and use that
token in the Authorization header when calling the GitHub Actions API.
🧹 Nitpick comments (1)
scripts/claude-actions-report.mjs (1)

271-411: LGTM!

Both API client functions correctly implement their respective provider formats. The Anthropic function properly uses x-api-key header and handles the content array response format.

Optional: The system/user prompt construction is duplicated across all three call* functions. Consider extracting a buildPrompt(fileKind, relPath, content, parsedExecution) helper to reduce duplication.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 60773a8 and adb8b8b.

📒 Files selected for processing (2)
  • .github/workflows/generate-actions-report.yml
  • scripts/claude-actions-report.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/generate-actions-report.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-report
🔇 Additional comments (12)
scripts/claude-actions-report.mjs (12)

1-43: LGTM!

The header documentation is comprehensive and clearly documents the expected environment variables, output structure, and supported providers.


44-66: LGTM!

The exponential backoff implementation is correct. The retry logic properly distinguishes rate-limit errors from other failures and re-throws non-rate-limit errors immediately.


68-79: LGTM!

The API endpoints are correctly defined for each provider, and requiredEnv provides appropriate validation with clear error messages.


81-88: LGTM!

Provider validation is straightforward and provides a helpful error message listing valid options.


90-106: LGTM!

Robust JSON parsing with fallback extraction handles LLM responses that may include markdown wrapping or extra text.


108-116: LGTM!

File classification logic correctly identifies workflow and action files with proper handling for Windows paths.


118-139: LGTM!

Link construction is correct with appropriate fallbacks when repository information is unavailable.


141-163: LGTM!

Comprehensive parsing of workflow triggers and action execution methods with appropriate fallbacks for all edge cases.


165-172: LGTM!

Simple and correct implementation for retrieving file modification timestamps.


199-269: LGTM!

Well-structured AI prompt with clear JSON schema and appropriate error handling. The stream: false setting is correct for this use case.


413-513: LGTM overall with one note.

The main function is well-structured with proper error handling. Content truncation at 20,000 characters is a sensible safeguard against oversized payloads.

Note: The fix suggested for getLastWorkflowRunTime also addresses the issue at line 488 where name (the workflow display name from YAML) should be filename for the GitHub API call.


515-518: LGTM!

Standard CLI error handling pattern with proper exit code.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @.github/workflows/generate-actions-report.yml:
- Around line 46-47: The workflow sets SCAN_ROOT and REPO_DEFAULT_BRANCH from
inputs that are only populated for workflow_dispatch, so on push they become
empty; update the assignment to use expression fallbacks so SCAN_ROOT and
REPO_DEFAULT_BRANCH default to the intended values when inputs.scan_root or
inputs.default_branch are empty (use the GitHub Actions expression fallback for
inputs.scan_root and inputs.default_branch), keeping the same variable names
SCAN_ROOT and REPO_DEFAULT_BRANCH so downstream steps continue to read the same
env vars.
- Around line 73-77: The REPOS assignment directly interpolates ${{
inputs.repositories }} into the shell, enabling command injection; instead read
the input into an environment variable and reference it safely (e.g., assign to
REPOS from a vetted env var), ensure you quote the variable when used (use
"$REPOS"), and validate/sanitize the value (allow only expected characters like
alphanumerics, commas, hyphens, underscores) before appending to GITHUB_OUTPUT;
update the lines that set and check REPOS (the REPOS variable and the echo
"list=..." write) to use the safe env var, quoting, and validation.
🧹 Nitpick comments (4)
.github/workflows/generate-actions-report.yml (4)

3-4: Consider adding branch or path filters to the push trigger.

The push: trigger without filters will run this workflow on every push to any branch. Since this workflow makes AI API calls and generates reports, this could be expensive and wasteful for feature branches.

Suggested improvement
 on:
   push:
+    branches:
+      - main
+    paths:
+      - '.github/workflows/**'
+      - 'scripts/claude-actions-report.mjs'

51-55: Wrap JSON output in a code block for proper rendering.

Raw JSON piped to $GITHUB_STEP_SUMMARY will not render correctly. Wrap it in a fenced code block for readability.

Suggested fix
       - name: Display report
         run: |
           echo '# Actions Report' >> $GITHUB_STEP_SUMMARY
           echo '' >> $GITHUB_STEP_SUMMARY
+          echo '```json' >> $GITHUB_STEP_SUMMARY
           jq '.' actions-report.json >> $GITHUB_STEP_SUMMARY
+          echo '```' >> $GITHUB_STEP_SUMMARY

92-104: Missing error handling and hardcoded organization.

  1. If git clone fails (e.g., repo doesn't exist or is private), the workflow will fail without a clear message.
  2. The organization armbian is hardcoded in the clone URL, limiting reusability.
  3. inputs.default_branch will be empty on push events (same issue as build-report job).
Suggested improvements
       - name: Generate reports
+        env:
+          GITHUB_TOKEN: ${{ github.token }}
+          AI_PROVIDER: openai
+          AI_MODEL: gpt-4o-mini
+          REPO_DEFAULT_BRANCH: ${{ inputs.default_branch || 'main' }}
+          ORG_NAME: ${{ github.repository_owner }}
         run: |
           REPOS="${{ steps.repos.outputs.list }}"
           IFS=',' read -ra REPO_ARRAY <<< "$REPOS"
           for repo in "${REPO_ARRAY[@]}"; do
             echo "Processing $repo..."
-            git clone --depth 1 https://github.com/armbian/$repo.git temp-$repo
+            if ! git clone --depth 1 "https://github.com/${ORG_NAME}/${repo}.git" "temp-${repo}"; then
+              echo "::warning::Failed to clone $repo, skipping..."
+              continue
+            fi
             cd temp-$repo
-            GITHUB_REPOSITORY=armbian/$repo SCAN_ROOT=.github node ../scripts/claude-actions-report.mjs
+            GITHUB_REPOSITORY="${ORG_NAME}/${repo}" SCAN_ROOT=.github node ../scripts/claude-actions-report.mjs
             mv actions-report.json ../actions-report-$repo.json
             cd ..
             rm -rf temp-$repo
           done
-        env:
-          GITHUB_TOKEN: ${{ github.token }}
-          AI_PROVIDER: openai
-          AI_MODEL: gpt-4o-mini
-          REPO_DEFAULT_BRANCH: ${{ inputs.default_branch }}

20-21: Both jobs run in parallel, potentially duplicating work.

On every trigger, build-report scans the current repository while scan-organization scans a list that may include the current repository (default includes armbian.github.io). This could result in duplicate AI API calls and wasted compute.

Consider either:

  1. Adding a condition to skip scan-organization on push events, or
  2. Making scan-organization depend on build-report and excluding the current repo from its list.
Option: Run scan-organization only on workflow_dispatch
   scan-organization:
     runs-on: ubuntu-latest
+    if: github.event_name == 'workflow_dispatch' && inputs.repositories != ''
     permissions:
       contents: read
       models: read

Also applies to: 63-64

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between adb8b8b and 330a9a9.

📒 Files selected for processing (2)
  • .github/workflows/generate-actions-report.yml
  • scripts/claude-actions-report.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/claude-actions-report.mjs
🔇 Additional comments (1)
.github/workflows/generate-actions-report.yml (1)

23-25: LGTM on permissions.

The permissions are appropriately scoped to read-only for contents and models, following the principle of least privilege.

Also applies to: 65-67

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@igorpecovnik igorpecovnik force-pushed the ai branch 3 times, most recently from 6f517be to b524909 Compare January 14, 2026 06:35
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @.github/workflows/generate-actions-report.yml:
- Around line 60-65: The workflow currently hardcodes the checkout ref to the
temporary branch "feature/ai-cache-optimization" in the Checkout step of
generate-actions-report.yml, which will fail once that branch is deleted; update
the Checkout step (the actions/checkout@v4 usage) to use a stable ref—e.g.,
replace the hardcoded ref with a workflow input or use a repository default like
github.ref_name or github.head_ref (or simply remove the ref to default to the
repository's default branch) so the action checks out a valid, non-temporary
branch at runtime.
♻️ Duplicate comments (2)
.github/workflows/generate-actions-report.yml (2)

27-37: Command injection vulnerability persists.

The inputs.repositories value is directly interpolated into shell (line 30) and then into Python code (line 35). This allows arbitrary command execution via crafted input.

This was flagged in a previous review and remains unaddressed.

🛡️ Recommended fix using environment variables
       - name: Set repository matrix
         id: set_repos
+        env:
+          INPUT_REPOS: ${{ inputs.repositories }}
         run: |
-          REPOS="${{ inputs.repositories }}"
+          REPOS="${INPUT_REPOS:-}"
           if [ -z "$REPOS" ]; then
             REPOS="armbian.github.io,build,imager,os,sdk,documentation,shallow,docker-armbian-build,configng"
           fi
           # Convert comma-separated to JSON array using python for simpler parsing
-          MATRIX=$(python3 -c "import json,sys; repos=[r.strip() for r in '$REPOS'.split(',') if r.strip()]; print(json.dumps(repos))")
+          MATRIX=$(python3 -c "import json,os; repos=[r.strip() for r in os.environ.get('INPUT_REPOS','').split(',') if r.strip()]; print(json.dumps(repos) if repos else json.dumps(['armbian.github.io','build','imager','os','sdk','documentation','shallow','docker-armbian-build','configng']))")
           echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
           echo "Repositories to scan: $REPOS"

86-95: Command injection and empty input issues in report generation.

Two issues in this step:

  1. Command injection (line 89): SCAN_ROOT=${{ inputs.scan_root }} directly interpolates user input into the shell command.

  2. Empty inputs on push (lines 89, 95): inputs.scan_root and inputs.default_branch are empty on push events since they're only populated during workflow_dispatch. This was flagged in a previous review.

Suggested fix with env vars and fallbacks
       - name: Generate report for ${{ matrix.repo }}
+        env:
+          GITHUB_TOKEN: ${{ github.token }}
+          AI_PROVIDER: openai
+          AI_MODEL: gpt-4o-mini
+          REPO_DEFAULT_BRANCH: ${{ inputs.default_branch || 'main' }}
+          INPUT_SCAN_ROOT: ${{ inputs.scan_root || '.github' }}
         run: |
           cd repo-source
-          GITHUB_REPOSITORY=armbian/${{ matrix.repo }} SCAN_ROOT=${{ inputs.scan_root }} node ../script-repo/scripts/claude-actions-report.mjs
+          GITHUB_REPOSITORY=armbian/${{ matrix.repo }} SCAN_ROOT="${INPUT_SCAN_ROOT}" node ../script-repo/scripts/claude-actions-report.mjs
           mv actions-report.json ../actions-report-${{ matrix.repo }}.json
-        env:
-          GITHUB_TOKEN: ${{ github.token }}
-          AI_PROVIDER: openai
-          AI_MODEL: gpt-4o-mini
-          REPO_DEFAULT_BRANCH: ${{ inputs.default_branch }}
🧹 Nitpick comments (5)
.github/workflows/generate-actions-report.yml (5)

3-5: Consider limiting push trigger scope.

The workflow triggers on every push to any branch. This may cause excessive workflow runs and API usage. Consider restricting to specific branches or paths.

on:
  push:
    branches: [main]
    paths:
      - '.github/workflows/**'
      - 'scripts/claude-actions-report.mjs'

97-101: Duplicate cache save is unnecessary.

The actions/cache@v4 action automatically saves the cache at the end of the job when using restore-keys. The explicit "Save AI description cache" step with the same key as the restore step is redundant.

Suggested fix: Remove duplicate cache step
-      - name: Save AI description cache
-        uses: actions/cache@v4
-        with:
-          path: repo-source/.ai-cache
-          key: ai-descriptions-${{ matrix.repo }}-${{ hashFiles('repo-source/.github/**/*.yml', 'repo-source/.github/**/*.yaml') }}
-
       - name: Upload artifact

133-150: Shell-based JSON generation is fragile.

Building JSON by concatenating strings with echo is error-prone. If a filename contains special characters (quotes, backslashes), the output will be invalid JSON. Consider using jq which is pre-installed on GitHub runners.

Suggested fix using jq
       - name: Generate index
         run: |
           cd data-branch/data/actions
-          # Create list of all JSON files
-          files=$(ls actions-report-*.json 2>/dev/null | sort)
-          # Generate index.json
-          echo "{\"generated\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"files\":[" > index.json
-          first=true
-          for f in $files; do
-            if [ "$first" = true ]; then
-              first=false
-            else
-              echo "," >> index.json
-            fi
-            echo -n "\"$f\"" >> index.json
-          done
-          echo "]}" >> index.json
+          # Generate index.json using jq for proper JSON handling
+          jq -n --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
+            '{generated: $ts, files: $ARGS.positional}' \
+            --args $(ls actions-report-*.json 2>/dev/null | sort) > index.json
           cat index.json

152-163: Git push may fail on concurrent runs.

If multiple workflow runs execute simultaneously (e.g., rapid pushes), git push can fail due to divergent histories. Consider using --force-with-lease or adding retry logic, or use a concurrency group to prevent parallel runs.

Option 1: Add concurrency group at workflow level

Add at the top of the file after on::

concurrency:
  group: actions-report-${{ github.ref }}
  cancel-in-progress: true
Option 2: Add retry logic for git push
       - name: Commit to data branch
         run: |
           cd data-branch
           git config user.name "GitHub Actions"
           git config user.email "actions@github.com"
           git add data/actions/
           if git diff --staged --quiet; then
             echo "No changes to commit"
           else
             git commit -m "Update actions reports [skip ci]"
-            git push
+            # Retry push with pull-rebase on failure
+            git push || (git pull --rebase && git push)
           fi

39-51: Consider adding job timeout.

The job lacks a timeout-minutes setting. If the AI API becomes unresponsive, the job could hang indefinitely. Given the sequential processing (max-parallel: 1) and multiple repositories, consider adding a reasonable timeout.

   scan-repositories:
     name: "Scan"
     needs: setup
     runs-on: ubuntu-latest
+    timeout-minutes: 30
     permissions:
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 74a3cb0 and e515065.

📒 Files selected for processing (2)
  • .github/workflows/generate-actions-report.yml
  • scripts/claude-actions-report.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/claude-actions-report.mjs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Scan (imager)

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

igorpecovnik and others added 4 commits January 15, 2026 21:37
This adds a GitHub Actions workflow and Node.js script that generates a JSON report of workflows/actions from multiple repositories in the Armbian organization using AI for descriptions.

Features:
- Matrix-based parallel scanning of multiple repositories
- Defaults to armbian.github.io and build repositories
- Supports GitHub Models (free GPT-4o-mini), Z.ai, and Anthropic Claude as AI providers
- Uses GitHub's built-in GITHUB_TOKEN for free access to AI models
- Generates hierarchical JSON with organization, repository, and actions data
- Workflow names extracted from YAML (not filenames)
- Automatic commit of reports to data branch at data/actions/
- Configurable via workflow_dispatch inputs (repositories, scan folder, default branch)

JSON structure includes:
- organization: GitHub organization name
- repository: Repository name
- actions: Array of workflow/action entries with name, filename, description (AI), execution_method, links, and timestamps
Enhance the GitHub Actions report script to track detailed workflow execution statistics:

- Add retry_count: Number of re-run attempts for the last workflow run
- Add total_run_time_seconds: Total execution time including all retries
- Add last_run_duration_seconds: Duration of the last run attempt only
- Add last_run_status: Status of the most recent run (success/failure/etc)
- Add total_runs: Total number of runs in the sample (up to 10)

The script now fetches up to 10 recent workflow runs to calculate these metrics by analyzing GitHub's run_number and run_attempt fields, where run_attempt > 1 indicates a manual retry.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @.github/workflows/generate-actions-report.yml:
- Around line 165-171: The inline comment "Run websire generation" contains a
typo; update that comment to "Run website generation" (refer to the workflow
step name "Generate website actions.armbian.com" and the surrounding step block
using peter-evans/repository-dispatch@v4) so the comment reads correctly.
♻️ Duplicate comments (3)
.github/workflows/generate-actions-report.yml (3)

27-37: Command injection vulnerability remains unaddressed.

The inputs.repositories value is directly interpolated into the shell (line 30) and into a Python string literal (line 35). This allows arbitrary command execution by anyone who can trigger the workflow_dispatch.

🛡️ Recommended fix using environment variables
       - name: Set repository matrix
         id: set_repos
+        env:
+          INPUT_REPOS: ${{ inputs.repositories }}
         run: |
-          REPOS="${{ inputs.repositories }}"
+          REPOS="${INPUT_REPOS:-}"
           if [ -z "$REPOS" ]; then
             REPOS="armbian.github.io,build,imager,os,sdk,documentation,shallow,docker-armbian-build,configng"
           fi
           # Convert comma-separated to JSON array using python for simpler parsing
-          MATRIX=$(python3 -c "import json,sys; repos=[r.strip() for r in '$REPOS'.split(',') if r.strip()]; print(json.dumps(repos))")
+          MATRIX=$(python3 -c "import json,os; repos=[r.strip() for r in os.environ.get('INPUT_REPOS','').split(',') if r.strip()]; print(json.dumps(repos) if repos else json.dumps(['armbian.github.io','build','imager','os','sdk','documentation','shallow','docker-armbian-build','configng']))")
           echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
           echo "Repositories to scan: $REPOS"

86-95: Inputs are empty on push events.

inputs.scan_root and inputs.default_branch are only populated during workflow_dispatch. On push events, these will be empty strings, causing the script to receive empty environment variables instead of the intended defaults.

Suggested fix using fallback syntax
       - name: Generate report for ${{ matrix.repo }}
         run: |
           cd repo-source
-          GITHUB_REPOSITORY=armbian/${{ matrix.repo }} SCAN_ROOT=${{ inputs.scan_root }} node ../script-repo/scripts/claude-actions-report.mjs
+          GITHUB_REPOSITORY=armbian/${{ matrix.repo }} SCAN_ROOT=${{ inputs.scan_root || '.github' }} node ../script-repo/scripts/claude-actions-report.mjs
           mv actions-report.json ../actions-report-${{ matrix.repo }}.json
         env:
           GITHUB_TOKEN: ${{ github.token }}
           AI_PROVIDER: openai
           AI_MODEL: gpt-4o-mini
-          REPO_DEFAULT_BRANCH: ${{ inputs.default_branch }}
+          REPO_DEFAULT_BRANCH: ${{ inputs.default_branch || 'main' }}

60-65: Hardcoded branch ai will break after merge.

The checkout references the ai branch, which appears to be the source branch of this PR. Once merged, this branch will likely be deleted, causing the workflow to fail.

Suggested fix to use default branch
       - name: Checkout script repo
         uses: actions/checkout@v4
         with:
           repository: armbian/armbian.github.io
           path: script-repo
-          ref: ai
+          ref: main
🧹 Nitpick comments (2)
.github/workflows/generate-actions-report.yml (2)

3-5: Consider limiting push trigger to specific branches.

The push trigger without branch filters will run this workflow on every push to any branch, which may consume unnecessary compute resources and API quota for the AI descriptions.

Suggested fix to limit to main branch
 on:
   push:
+    branches:
+      - main
   workflow_dispatch:

133-150: Consider using jq for safer JSON generation.

Building JSON manually with echo statements is fragile. While the filenames are controlled in this case, using jq would be more robust and handle edge cases better.

Suggested fix using jq
       - name: Generate index
         run: |
           cd data-branch/data/actions
-          # Create list of all JSON files
-          files=$(ls actions-report-*.json 2>/dev/null | sort)
-          # Generate index.json
-          echo "{\"generated\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"files\":[" > index.json
-          first=true
-          for f in $files; do
-            if [ "$first" = true ]; then
-              first=false
-            else
-              echo "," >> index.json
-            fi
-            echo -n "\"$f\"" >> index.json
-          done
-          echo "]}" >> index.json
+          # Generate index.json using jq for safe JSON handling
+          jq -n --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
+            --argjson files "$(ls -1 actions-report-*.json 2>/dev/null | jq -R -s 'split("\n") | map(select(length > 0))')" \
+            '{generated: $ts, files: $files}' > index.json
           cat index.json
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 994ec26 and 627d096.

📒 Files selected for processing (1)
  • .github/workflows/generate-actions-report.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Scan (os)
🔇 Additional comments (1)
.github/workflows/generate-actions-report.yml (1)

152-163: LGTM!

Good practice to check for staged changes before committing and using [skip ci] to prevent workflow loops.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@scripts/generate-actions-report.mjs`:
- Around line 271-275: The API URL construction in getWorkflowRunDetails is
fragile (server -> apiUrl) for GitHub Enterprise; replace the string replace
with proper URL parsing: create a URL object from server (const serverUrl = new
URL(server)), then set apiUrl to "https://api.github.com" when
serverUrl.hostname endsWith("github.com"), otherwise set apiUrl to
`${serverUrl.origin}/api/v3`; update any uses of apiUrl accordingly (refer to
function getWorkflowRunDetails and variables server and apiUrl).
♻️ Duplicate comments (4)
.github/workflows/generate-actions-report.yml (4)

28-38: Command injection vulnerability persists.

The inputs.repositories value is directly interpolated into shell (line 31) and Python code (line 36), allowing command injection by users with workflow dispatch access.

Recommended fix using environment variable
       - name: Set repository matrix
         id: set_repos
+        env:
+          INPUT_REPOS: ${{ inputs.repositories }}
         run: |
-          REPOS="${{ inputs.repositories }}"
+          REPOS="$INPUT_REPOS"
           if [ -z "$REPOS" ]; then
             REPOS="armbian.github.io,build,imager,os,sdk,documentation,shallow,docker-armbian-build,configng"
           fi
           # Convert comma-separated to JSON array using python for simpler parsing
-          MATRIX=$(python3 -c "import json,sys; repos=[r.strip() for r in '$REPOS'.split(',') if r.strip()]; print(json.dumps(repos))")
+          MATRIX=$(python3 -c "import json,sys,os; repos=[r.strip() for r in os.environ.get('INPUT_REPOS', '').split(',') if r.strip()]; print(json.dumps(repos) if repos else json.dumps(['armbian.github.io','build','imager','os','sdk','documentation','shallow','docker-armbian-build','configng']))")
           echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
           echo "Repositories to scan: $REPOS"

61-66: Hardcoded feature branch reference will break after merge.

The checkout references ref: ai which is the PR's source branch. Once merged and deleted, this workflow will fail. Update to use the default branch or remove the ref line entirely.

Suggested fix
       - name: Checkout script repo
         uses: actions/checkout@v4
         with:
           repository: armbian/armbian.github.io
           path: script-repo
-          ref: ai

87-96: Inputs are empty on scheduled runs.

On schedule triggers, inputs.scan_root and inputs.default_branch are undefined (not the defaults from workflow_dispatch). The script will receive empty values instead of .github and main.

Suggested fix using fallback syntax
       - name: Generate report for ${{ matrix.repo }}
         run: |
           cd repo-source
-          GITHUB_REPOSITORY=armbian/${{ matrix.repo }} SCAN_ROOT=${{ inputs.scan_root }} node ../script-repo/scripts/generate-actions-report.mjs
+          GITHUB_REPOSITORY=armbian/${{ matrix.repo }} SCAN_ROOT=${{ inputs.scan_root || '.github' }} node ../script-repo/scripts/generate-actions-report.mjs
           mv actions-report.json ../actions-report-${{ matrix.repo }}.json
         env:
           GITHUB_TOKEN: ${{ github.token }}
           AI_PROVIDER: openai
           AI_MODEL: gpt-4o-mini
-          REPO_DEFAULT_BRANCH: ${{ inputs.default_branch }}
+          REPO_DEFAULT_BRANCH: ${{ inputs.default_branch || 'main' }}

166-167: Typo: "websire" → "website".

-      # Run websire generation
+      # Run website generation
🧹 Nitpick comments (4)
scripts/generate-actions-report.mjs (4)

318-320: Consider renaming total_runs for clarity.

The field name total_runs suggests an all-time count, but it only reflects the fetched sample size (up to 10). Consider renaming to sampled_runs or recent_runs_count to avoid confusion.


336-554: Consider extracting shared prompt logic to reduce duplication.

The three AI provider functions (callZai, callOpenAI, callAnthropic) contain nearly identical system prompts and user content construction (~20 lines each). Extracting these to shared helper functions would improve maintainability.

Refactor suggestion
function buildSystemPrompt() {
  return [
    "You are a senior DevOps engineer.",
    "You will analyze a GitHub Actions workflow or action definition file.",
    // ... rest of shared prompt
  ].join("\n");
}

function buildUserContent({ fileKind, relPath, content, parsedExecution }) {
  return [
    `File kind: ${fileKind}`,
    `Path: ${relPath}`,
    `Parsed execution hint: ${parsedExecution}`,
    "",
    "File content:",
    content,
  ].join("\n");
}

639-649: Caching AI failures may persist transient errors.

When AI calls fail (lines 639-644), the failure message is cached (line 648). This prevents repeated API calls but also means transient errors (e.g., network issues, temporary outages) will persist until the source file changes.

Consider either:

  • Not caching failed descriptions
  • Using a shorter TTL for cached failures
  • Marking failures differently in the cache to allow retry on next run

630-638: Consider logging when content is truncated.

Large files are silently truncated at 20KB (line 636). Adding a log message when truncation occurs would help diagnose cases where important content at the end of a file is missed.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 627d096 and 51d5763.

📒 Files selected for processing (3)
  • .github/workflows/generate-actions-report.yml
  • README.md
  • scripts/generate-actions-report.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • README.md
🔇 Additional comments (7)
scripts/generate-actions-report.mjs (3)

58-80: LGTM! Well-implemented exponential backoff.

The retry mechanism with exponential backoff starting at 4s is appropriate for rate-limited APIs. The logic correctly distinguishes rate-limit errors from other failures.


86-167: Solid caching implementation with appropriate invalidation strategies.

The cache correctly invalidates on version changes, content changes, and AI model changes. Graceful error handling ensures caching failures don't break the main workflow.


556-570: Clean provider and model configuration.

The provider selection logic with sensible defaults for each AI provider is well-structured. The automatic extraction of organization/repository from GITHUB_REPOSITORY is appropriate.

.github/workflows/generate-actions-report.yml (4)

3-19: Well-configured triggers with sensible defaults.

The schedule runs every 2 days and manual dispatch provides flexibility with optional inputs that have reasonable defaults.


78-102: Good cache configuration with repository-specific keys.

The cache strategy uses repo-specific keys with YAML file hashing for invalidation, and includes fallback restore keys for partial cache hits.


110-165: Well-structured merge and commit job.

The job properly handles artifact merging with graceful error handling, generates a machine-readable index, and commits with [skip ci] to prevent recursive triggers.


167-172: Cross-repository dispatch requires proper secret configuration.

Ensure secrets.DISPATCH is a PAT with appropriate permissions for the armbian/actions repository. The dispatch will silently fail if the token lacks access.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@igorpecovnik igorpecovnik added Ready to merge Reviewed, tested and ready for merge and removed Needs review Seeking for review labels Jan 15, 2026
@github-actions github-actions bot added Needs review Seeking for review Ready to merge Reviewed, tested and ready for merge and removed Ready to merge Reviewed, tested and ready for merge labels Jan 15, 2026
@igorpecovnik igorpecovnik merged commit f45d4d1 into main Jan 15, 2026
1 check passed
@igorpecovnik igorpecovnik deleted the ai branch January 15, 2026 21:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

02 Milestone: First quarter release Documentation Documentation changes or additions GitHub Actions GitHub Actions code GitHub GitHub-related changes like labels, templates, ... Needs review Seeking for review Ready to merge Reviewed, tested and ready for merge size/large PR with 250 lines or more

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant