SkillAgentSearch skills...

n-ga

Правила форматів для .github/workflows

Install / Use

npx skills add nitra/actions-runner

Installs into whichever agent you are using.

About this skill
📐

Cursor Rules

Cursor IDE rules (v2)

Quality Score

64/100

Category

Automation

Supported Platforms

Cursor

description: Правила форматів для .github/workflows version: '1.12' globs: ".github/workflows/*.yml" alwaysApply: false

Правило ga перевіряє структуру .github/workflows/, наявність обов'язкових workflow-файлів і їх відповідність канонам, а також налаштування VS Code та zizmor для роботи з GitHub Actions.

  • settings.json:
{ "[github-actions-workflow]": { "editor.defaultFormatter": "oxc.oxc-vscode" } }
  • git-ai.yml:
name: Git AI

on:
  pull_request:
    types: [closed]

concurrency:
  group: ${{ github.ref }}-${{ github.workflow }}
  cancel-in-progress: true

jobs:
  git-ai:
    if: github.event.pull_request.merged == true
    runs-on: ubuntu-latest
    permissions:
      contents: write

    steps:
      - name: Install git-ai
        run: |
          curl -fsSL https://usegitai.com/install.sh | bash
          echo "$HOME/.git-ai/bin" >> $GITHUB_PATH
      - name: Run git-ai
        id: run-git-ai
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          git config --global user.name "github-actions[bot]"
          git config --global user.email "github-actions[bot]@users.noreply.github.com"
          git-ai ci github run
  • clean-ga-workflows.yml:
name: Clean action for removing completed workflow runs

on:
  schedule:
    - cron: '0 1 16 * *'

  # Allow workflow to be manually run from the GitHub UI
  workflow_dispatch: {}

concurrency:
  group: ${{ github.ref }}-${{ github.workflow }}
  cancel-in-progress: true

jobs:
  cleanup_old_workflows:
    runs-on: ubuntu-latest
    permissions:
      actions: write
      contents: read
    steps:
      - name: Delete workflow runs
        uses: dmvict/clean-workflow-runs@v1
        with:
          token: ${{ github.token }}
          save_period: 31
          save_min_runs_number: 0
  • lint-ga.yml:
name: Lint GA

on:
  push:
    branches:
      - dev
      - main
    paths:
      - '.github/actions/**'
      - '.github/workflows/**'
  pull_request:
    branches:
      - dev
      - main

concurrency:
  group: ${{ github.ref }}-${{ github.workflow }}
  cancel-in-progress: true

jobs:
  lint-ga:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v6
        with:
          persist-credentials: false

      - uses: ./.github/actions/setup-bun-deps

      - uses: astral-sh/setup-uv@v8.0.0

      - name: Install conftest
        run: >-
          curl -fsSL
          https://github.com/open-policy-agent/conftest/releases/download/v0.62.0/conftest_0.62.0_Linux_x86_64.tar.gz
          | sudo tar -xz -C /usr/local/bin conftest

      - name: Lint GA
        run: bunx n-rules lint ga --no-fix
  • zizmor.yml:
rules:
  unpinned-uses:
    config:
      policies:
        '*': ref-pin
  • clean-merged-branch.yml:
name: Clean abandoned branches

on:
  # Run daily at midnight
  schedule:
    - cron: '0 1 15 * *'

  # Allow workflow to be manually run from the GitHub UI
  workflow_dispatch: {}

concurrency:
  group: ${{ github.ref }}-${{ github.workflow }}
  cancel-in-progress: true

jobs:
  cleanup_old_branches:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: read
    steps:
      - id: delete_stuff
        name: Delete those pesky dead branches
        uses: phpdocker-io/github-actions-delete-abandoned-branches@v2.0.3
        with:
          github_token: ${{ github.token }}
          last_commit_age_days: 90
          ignore_branches: main,dev
          # Action CLI accepts only yes/no. Go-yaml in conftest parses `no` as
          # boolean false, so the Rego policy normalizes both forms.
          dry_run: no

      - name: Get output
        env:
          DELETED_BRANCHES: ${{ steps.delete_stuff.outputs.deleted_branches }}
        run: |
          echo "Deleted branches: ${DELETED_BRANCHES}"
  • extensions.json:
{ "recommendations": ["github.vscode-github-actions"] }
  • uses-min-versions:
{
  "actions/checkout": "6",
  "Infisical/secrets-action": "1.0.16"
}
  • lint-repo.yml:
name: Lint repo-wide

on:
  push:
    branches:
      - dev
      - main

  pull_request:
    branches:
      - dev
      - main

concurrency:
  group: ${{ github.ref }}-${{ github.workflow }}
  cancel-in-progress: true

jobs:
  lint-repo:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v6
        with:
          persist-credentials: false

      - uses: ./.github/actions/setup-bun-deps

      - name: Repo-wide lint
        run: bunx n-rules lint --repo-wide --no-fix

Repo-wide лінти (lint-repo.yml, обовʼязковий)

Перевірки без path-підтримки (scope: full без glob: knip, jscpd, dep-policy тощо) живуть в окремому обовʼязковому workflow .github/workflows/lint-repo.yml із кроком bunx n-rules lint --repo-wide --no-fix. Він не гейтить деплой — жоден deploy-workflow не має на нього needs. Деталі: lint_repo_yml.mdc.

Сервіс-орієнтовані deploy-workflow (опційно)

Монорепо з деплой-сервісами (каталог сервісу, напр. run/nexus) оформлює деплой per-service workflow: тригер paths по каталогу (dir-scoped glob run/<service>/** — саме він, а не імʼя файлу, робить workflow сервісним; імʼя довільне — npm-publish.yml, deploy-<service>.yml, і не перейменовуй наявні — OIDC trusted publishing привʼязаний до імені) → джоба plan (bunx n-rules ci plan --path <svc> --github) → паралельні lint-<domain>-джоби з гейтом по outputs плану + тести сервісу → deploy з needs на всі перевірки (skipped не блокує, failed блокує). Форму перевіряє rego-концерн service_deploy_workflow — вимоги вмикаються лише за наявності lint-джоб у workflow; приклад — deploy-service.yml:

# Документаційний приклад сервіс-орієнтованого deploy-workflow (ga.mdc).
# Це НЕ deep-subset-канон (перелік сервісів консюмер-специфічний) — форму
# перевіряє service_deploy_workflow.rego за ЗМІСТОМ: сервісний workflow =
# dir-scoped glob у on.push.paths. Імʼя файлу довільне (npm-publish.yml,
# deploy-<service>.yml, …) — не перейменовуй наявні: OIDC trusted publishing
# привʼязаний до імені workflow. Плейсхолдер run/<service> заміни на каталог
# сервісу; набір lint-<domain> джоб добери під стеки сервісу (зайва джоба
# нешкідлива — ci plan її скіпне).
name: Deploy <service>

on:
  push:
    branches:
      - dev
      - main
    paths:
      - 'run/<service>/**'

concurrency:
  group: ${{ github.ref }}-${{ github.workflow }}
  cancel-in-progress: true

jobs:
  plan:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    outputs:
      js: ${{ steps.plan.outputs.js }}
      python: ${{ steps.plan.outputs.python }}
      any: ${{ steps.plan.outputs.any }}
    steps:
      - uses: actions/checkout@v6
        with:
          persist-credentials: false
          fetch-depth: 0

      - uses: ./.github/actions/setup-bun-deps

      - id: plan
        run: bunx n-rules ci plan --path run/<service> --github

  lint-js:
    needs: plan
    if: needs.plan.outputs.js == 'true'
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v6
        with:
          persist-credentials: false
          fetch-depth: 0

      - uses: ./.github/actions/setup-bun-deps

      - run: bunx n-rules lint js --path run/<service> --no-fix

  # …lint-<domain> для кожного домену сервісу (python/docker/k8s/security/…)

  test:
    needs: plan
    if: needs.plan.outputs.any == 'true'
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v6
        with:
          persist-credentials: false
          fetch-depth: 0

      - uses: ./.github/actions/setup-bun-deps

      # python-стек: перед тестами ще uv (uses: astral-sh/setup-uv@v7 + uv sync --locked)
      - run: bun test run/<service>

  deploy:
    needs:
      - plan
      - lint-js
      - test
    # Skipped-лінт (гейт ci plan) НЕ блокує деплой; failed — блокує.
    if: ${{ !cancelled() && needs.plan.result == 'success' && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          persist-credentials: false

      # …кроки деплою сервісу (build/push/apply)
```, деталі — [service_deploy_workflow.mdc](./service_deploy_workflow/service_deploy_workflow.mdc). Співіснує з file-type-workflow (`lint-js.yml` тощо) — ті покривають зміни поза сервіс-каталогами.

## Структура `clean-ga-workflows.yml` — видалення завершених workflow runs

Rego-пакет: `ga.clean_ga_workflows`

**Цільовий файл:** `.github/workflows/clean-ga-workflows.yml`

### Що перевіряється

- `name` — точна відповідність значенню з template
- `on.schedule[].cron` — має містити cron із template (`0 1 16 * *`)
- `on.workflow_dispatch` — має бути об'єктом `{}`
- `jobs.cleanup_old_workflows` — job має існувати
- `jobs.cleanup_old_workflows.runs-on` — відповідно до template (`ubuntu-latest`)
- `jobs.cleanup_old_workflows.permissions` — `actions: write`, `contents: read`
- `steps[0].name` і `steps[0].uses` — відповідно до template (`dmvict/clean-workflow-runs@v1`)
- `steps[0].with` — `token`, `save_period`, `save_min_runs_number` як у template

**Pin-aware `uses`:** SHA-пін того самого action (`owner/action@<40-hex SHA>`, з тег-коментарем `# vX` чи без) задовольняє канонічний тег із template. Якщо в репо вже SHA-пін (zizmor-політика ref-pin) — НЕ замінюй його тегом.

Канон: [clean-ga-workflows.yml.snippet.yml](./template/clean-ga-workflows.yml.snippet.yml)

## Структура `clean-merged-branch.yml` — видалення злитих гілок

Rego-пакет: `ga.clean_merged_branch`

**Цільовий файл:** `.github/workflows/clean-merged-branch.yml`

### Що перевіряється

- `name` — точна відповідність значенню з template
- `on.schedule[].cron` — має містити cron із template (`0 1 15 * *`)
- `on.workflow_dispatch` — має бути об'єктом `{}`
- `jobs.cleanup_old_branches` — job має існувати
- `jobs.cleanup_old_branches.permissions` — кожне поле із template (`contents: write`, `pull-requests: read`)
- `steps` — має бути рівно 2 кроки
- `steps[0].id` — `delete_stuff`; `steps[0].uses` — `phpdocker-io/github-actions-delete-abandoned-branches@v2.0.3`
- `steps[0].with.github_token`, `last_commit_age_days` — за template
- `steps[0].with.ignore_branches` — має містити всі гілки з template (`main,dev`)
- `steps[0].with.dry_run` — `no` (нормалізується: YAML 1.1 `no` → boolean `false` у conftest)
- `steps[1].name` — за template; `steps[1].env.DELETED_BRANCHES` — за template
- `steps[1].run` — містить `Deleted branches:` та `${DELETED_BRANCHES}`

**Pin-aware `uses`:** SHA-пін того самого action (`owner/action@<40-hex SHA>`, з тег-коментарем `# vX` чи без) задовольняє канонічний тег із template. Якщо в репо вже SHA-пін (zizmor-політика ref-pin) — НЕ замінюй його тегом.

Канон: [clean-merged-branch.yml.snippet.yml](./template/clean-merged-branch.yml.snippet.yml)

## Структура `git-ai.yml` — автоматичний запуск git-ai після мержу PR

Rego-пакет: `ga.git_ai`

**Цільовий файл:** `.github/workflows/git-ai.yml`

### Що перевіряється

- `name` — точна відповідність значенню з template (`Git AI`)
- `on.pull_request.types` — має містити `closed`
- `jobs.git-ai` — job має існувати
- `jobs.git-ai.if` — містить `github.event.pull_request.merged == true`
- `jobs.git-ai.permissions.contents` — за template (`write`)
- `steps[*].run` (сукупно) — містить substring `https://usegitai.com/install.sh` (інсталяція)
- `steps[*].run` (сукупно) — містить substring `git-ai ci github run` (запуск)

Substring-перевірки замість exact-match через крихкість multi-line `run:` блоків.

Канон: [git-ai.yml.snippet.yml](./template/git-ai.yml.snippet.yml)

## Структура `lint-ga.yml` — CI-лінт GitHub Actions файлів

Rego-пакет: `ga.lint_ga`

**Цільовий файл:** `.github/workflows/lint-ga.yml`

### Що перевіряєтьс

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars0
CategoryAutomation
UpdatedNaNy ago
Forks0

Security Score

68/100

Audited on Invalid Date

2 medium1 low