---
name: github-actions-templates
description: "Production-ready GitHub Actions workflow patterns for testing, building, and deploying applications."
risk: critical
source: community
date_added: "2026-02-27"
---

# GitHub Actions Templates

Production-ready GitHub Actions workflow patterns for testing, building, and deploying applications.

## Do not use this skill when

- The task is unrelated to github actions templates
- You need a different domain or tool outside this scope

## Instructions

- Clarify goals, constraints, and required inputs.
- Apply relevant best practices and validate outcomes.
- Provide actionable steps and verification.
- If detailed examples are required, open `resources/implementation-playbook.md`.

## Purpose

Create efficient, secure GitHub Actions workflows for continuous integration and deployment across various tech stacks.

## Use this skill when

- Automate testing and deployment
- Build Docker images and push to registries
- Deploy to Kubernetes clusters
- Run security scans
- Implement matrix builds for multiple environments

## Common Workflow Patterns

### Pattern 1: Test Workflow

```yaml
name: Test

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [18.x, 20.x]

    steps:
    - uses: actions/checkout@v4

    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v4
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'

    - name: Install dependencies
      run: npm ci

    - name: Run linter
      run: npm run lint

    - name: Run tests
      run: npm test

    - name: Upload coverage
      uses: codecov/codecov-action@v3
      with:
        files: ./coverage/lcov.info
```

**Reference:** See `assets/test-workflow.yml`

### Pattern 2: Build and Push Docker Image

```yaml
name: Build and Push

on:
  push:
    branches: [ main ]
    tags: [ 'v*' ]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
    - uses: actions/checkout@v4

    - name: Log in to Container Registry
      uses: docker/login-action@v3
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}

    - name: Extract metadata
      id: meta
      uses: docker/metadata-action@v5
      with:
        images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
        tags: |
          type=ref,event=branch
          type=ref,event=pr
          type=semver,pattern={{version}}
          type=semver,pattern={{major}}.{{minor}}

    - name: Build and push
      uses: docker/build-push-action@v5
      with:
        context: .
        push: true
        tags: ${{ steps.meta.outputs.tags }}
        labels: ${{ steps.meta.outputs.labels }}
        cache-from: type=gha
        cache-to: type=gha,mode=max
```

**Reference:** See `assets/deploy-workflow.yml`

### Pattern 3: Deploy to Kubernetes

```yaml
name: Deploy to Kubernetes

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v4
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: us-west-2

    - name: Update kubeconfig
      run: |
        aws eks update-kubeconfig --name production-cluster --region us-west-2

    - name: Deploy to Kubernetes
      run: |
        kubectl apply -f k8s/
        kubectl rollout status deployment/my-app -n production
        kubectl get services -n production

    - name: Verify deployment
      run: |
        kubectl get pods -n production
        kubectl describe deployment my-app -n production
```

### Pattern 4: Matrix Build

```yaml
name: Matrix Build

on: [push, pull_request]

jobs:
  build:
    runs-on: ${{ matrix.os }}

    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python-version: ['3.9', '3.10', '3.11', '3.12']

    steps:
    - uses: actions/checkout@v4

    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: ${{ matrix.python-version }}

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt

    - name: Run tests
      run: pytest
```

**Reference:** See `assets/matrix-build.yml`

## Workflow Best Practices

1. **Use specific action versions** (@v4, not @latest)
2. **Cache dependencies** to speed up builds
3. **Use secrets** for sensitive data
4. **Implement status checks** on PRs
5. **Use matrix builds** for multi-version testing
6. **Set appropriate permissions**
7. **Use reusable workflows** for common patterns
8. **Implement approval gates** for production
9. **Add notification steps** for failures
10. **Use self-hosted runners** for sensitive workloads

## Reusable Workflows

```yaml
# .github/workflows/reusable-test.yml
name: Reusable Test Workflow

on:
  workflow_call:
    inputs:
      node-version:
        required: true
        type: string
    secrets:
      NPM_TOKEN:
        required: true

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}
    - run: npm ci
    - run: npm test
```

**Use reusable workflow:**
```yaml
jobs:
  call-test:
    uses: ./.github/workflows/reusable-test.yml
    with:
      node-version: '20.x'
    secrets:
      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
```

## Security Scanning

```yaml
name: Security Scan

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  security:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - name: Run Trivy vulnerability scanner
      uses: aquasecurity/trivy-action@master
      with:
        scan-type: 'fs'
        scan-ref: '.'
        format: 'sarif'
        output: 'trivy-results.sarif'

    - name: Upload Trivy results to GitHub Security
      uses: github/codeql-action/upload-sarif@v2
      with:
        sarif_file: 'trivy-results.sarif'

    - name: Run Snyk Security Scan
      uses: snyk/actions/node@master
      env:
        SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
```

## Deployment with Approvals

```yaml
name: Deploy to Production

on:
  push:
    tags: [ 'v*' ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://app.example.com

    steps:
    - uses: actions/checkout@v4

    - name: Deploy application
      run: |
        echo "Deploying to production..."
        # Deployment commands here

    - name: Notify Slack
      if: success()
      uses: slackapi/slack-github-action@v1
      with:
        webhook-url: ${{ secrets.SLACK_WEBHOOK }}
        payload: |
          {
            "text": "Deployment to production completed successfully!"
          }
```

## Reference Files

- `assets/test-workflow.yml` - Testing workflow template
- `assets/deploy-workflow.yml` - Deployment workflow template
- `assets/matrix-build.yml` - Matrix build template
- `references/common-workflows.md` - Common workflow patterns

## Related Skills

- `gitlab-ci-patterns` - For GitLab CI workflows
- `deployment-pipeline-design` - For pipeline architecture
- `secrets-management` - For secrets handling

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: github-automation
description: "Operate GitHub issues, pull requests, branches, checks, workflows, and permissions through Rube MCP. Use when GitHub work must be queried or changed programmatically with repository-policy safeguards."
risk: critical
source: community
date_added: "2026-02-27"
---

# GitHub Automation via Rube MCP

Use Composio's GitHub toolkit through Rube MCP while preserving repository policy, exact revision identity, and branch protection.

## When to Use

Use for programmatic GitHub issue, pull-request, branch, Actions, deployment, collaborator, or protection tasks when Rube MCP is available. Prefer the native `gh` workflow or a repository-specific maintainer command when local repository policy requires it.

## Setup

1. Confirm `RUBE_SEARCH_TOOLS` is available.
2. Search for the current GitHub tool schemas before composing calls.
3. Use `RUBE_MANAGE_CONNECTIONS` with toolkit `github` and complete OAuth only if the connection is not active.
4. Resolve the exact `owner/repo`; do not rely on a similarly named repository.

Never request, print, or persist GitHub credentials in prompts or artifacts.

## Repository Policy Gate

Before mutation, read `AGENTS.md`, contribution and maintainer docs, then inspect the default branch and effective protection. Repository-native commands and required checks take precedence over generic Rube operations.

If a repository provides a guarded merge or release command, use it instead of the generic merge tool. In `agentic-awesome-skills`, use `antigravity-maintainer-batch-release` and `npm run merge:batch` so exact-SHA review, fresh check-suite binding, and protected `main` are enforced.

## Workflows

### Issues

1. List or search existing issues before creating a duplicate.
2. Distinguish issues from pull requests in mixed results.
3. Read the current item, comments, labels, and linked PRs before changing state.
4. Create, comment, label, assign, or close only within the user's requested scope.
5. Re-read the item and verify the resulting state.

Paginate until the requested result set is complete. Treat silent omission of labels or assignees as a permissions failure, not success.

### Pull requests

1. Resolve the PR and capture its number, base, full head SHA, draft state, author, fork identity, and mergeability.
2. Inspect changed files, reviews, conversations, and required check runs.
3. Bind every review or approval decision to the current full head SHA.
4. Create or update the PR body truthfully; never mark pending tests or reviews as completed.
5. Immediately before merge, re-read base/head identity, branch protection, mergeability, required checks, and repository policy.
6. Use the repository's guarded merge path. Call a generic merge tool only when policy permits it and the user authorized the merge.
7. Verify the PR reports `MERGED` and confirm the target branch contains the intended commit.

Do not treat a successful API call that enables auto-merge or queues work as an immediate merge.

### Branches and references

1. Resolve the source commit SHA and target ref explicitly.
2. Create topic branches rather than updating protected/default branches directly.
3. Reject non-fast-forward or force updates unless the user explicitly authorizes them and repository policy permits them.
4. Confirm the remote ref after mutation.

Deletion, force-push, default-branch changes, and protection changes are destructive or high-impact actions requiring explicit authorization.

### Actions and deployments

1. Resolve the workflow by trusted ID or path and confirm `workflow_dispatch` support before dispatch.
2. Bind run inspection to the intended event, ref, and head SHA.
3. Distinguish `queued`, `in_progress`, `action_required`, `completed`, and `skipped` states.
4. Read failed job logs before proposing source changes.
5. Wait for terminal success and verify the deployed or published surface separately.

Do not approve fork workflow runs by raw run ID when the repository provides a guarded approval command.

### Permissions and protection

1. Read collaborators, role, branch protection, and applicable rulesets before proposing changes.
2. Treat a 404 protection response as “not configured” only after confirming repository and branch identity.
3. Show the exact before/after policy and impact before any protection or permission mutation.
4. Re-read effective state after the change.

## Failure Rules

- Re-resolve tool schemas when Rube reports missing or changed parameters.
- Stop on repository ambiguity, stale head/base SHA, missing permissions, incomplete pagination, or inconclusive protection state.
- Never bypass required checks, reviews, merge queues, maintainer commands, or server-side branch protection.
- Do not claim a merge, workflow, deployment, or permission change succeeded without reading the resulting remote state.

## Limitations

- Available Rube tool names and schemas can change; discover them at runtime.
- GitHub permissions, organization policy, and external checks can block otherwise valid operations.
- This skill does not authorize repository deletion, force pushes, protection changes, merges, deployments, or releases beyond explicit user intent.


---
name: github-issue-creator
description: "Turn error logs, screenshots, voice notes, and rough bug reports into crisp, developer-ready GitHub issues with repro steps, impact, and evidence."
risk: critical
source: community
date_added: "2026-02-27"
---

# GitHub Issue Creator

Transform messy input (error logs, voice notes, screenshots) into clean, actionable GitHub issues.

## Output Template

```markdown
## Summary
[One-line description of the issue]

## Environment
- **Product/Service**:
- **Region/Version**:
- **Browser/OS**: (if relevant)

## Reproduction Steps
1. [Step]
2. [Step]
3. [Step]

## Expected Behavior
[What should happen]

## Actual Behavior
[What actually happens]

## Error Details
```
[Error message/code if applicable]
```

## Visual Evidence
[Reference to attached screenshots/GIFs]

## Impact
[Severity: Critical/High/Medium/Low + brief explanation]

## Additional Context
[Any other relevant details]
```

## Output Location

**Create issues as markdown files** in `/issues/` directory at the repo root. Use naming convention: `YYYY-MM-DD-short-description.md`

## Guidelines

**Be crisp**: No fluff. Every word should add value.

**Extract structure from chaos**: Voice dictation and raw notes often contain the facts buried in casual language. Pull them out.

**Infer missing context**: If user mentions "same project" or "the dashboard", use context from conversation or memory to fill in specifics.

**Placeholder sensitive data**: Use `[PROJECT_NAME]`, `[USER_ID]`, etc. for anything that might be sensitive.

**Match severity to impact**:
- Critical: Service down, data loss, security issue
- High: Major feature broken, no workaround
- Medium: Feature impaired, workaround exists
- Low: Minor inconvenience, cosmetic

**Image/GIF handling**: Reference attachments inline. Format: `!Description`

## Examples

**Input (voice dictation)**:
> so I was trying to deploy the agent and it just failed silently no error nothing the workflow ran but then poof gone from the list had to refresh and try again three times

**Output**:
```markdown
## Summary
Agent deployment fails silently - no error displayed, agent disappears from list

## Environment
- **Product/Service**: Azure AI Foundry
- **Region/Version**: westus2

## Reproduction Steps
1. Navigate to agent deployment
2. Configure and deploy agent
3. Observe workflow completes
4. Check agent list

## Expected Behavior
Agent appears in list with deployment status, errors shown if deployment fails

## Actual Behavior
Agent disappears from list. No error message. Requires page refresh and retry.

## Impact
**High** - Blocks agent deployment workflow, no feedback on failure cause

## Additional Context
Required 3 retry attempts before successful deployment
```

---

**Input (error paste)**:
> Error: PERMISSION_DENIED when publishing to Teams channel. Code: 403. Was working yesterday.

**Output**:
```markdown
## Summary
403 PERMISSION_DENIED error when publishing to Teams channel

## Environment
- **Product/Service**: Copilot Studio → Teams integration
- **Region/Version**: [REGION]

## Reproduction Steps
1. Configure agent for Teams channel
2. Attempt to publish

## Expected Behavior
Agent publishes successfully to Teams channel

## Actual Behavior
Returns `PERMISSION_DENIED` with code 403

## Error Details
```
Error: PERMISSION_DENIED
Code: 403
```

## Impact
**High** - Blocks Teams integration, regression from previous working state

## Additional Context
Was working yesterday - possible permission/config change or service regression
```

## When to Use
Use this skill when you have unstructured bug input such as pasted errors, support notes, screenshots, or voice dictation and need to turn it into a clean GitHub issue with a summary, reproduction steps, expected vs actual behavior, impact, and attachment references.

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: github-presence
description: When the user wants to optimize their GitHub profile, README, or project discoverability. Trigger phrases include "GitHub README," "README optimization," "GitHub profile," "GitHub stars," "GitHub discoverability," "awesome lists," or "GitHub marketing."
risk: critical
source: https://github.com/jonathimer/devmarketing-skills/tree/main/skills/github-presence
source_repo: jonathimer/devmarketing-skills
source_type: community
date_added: 2026-07-01
license: MIT
license_source: https://github.com/jonathimer/devmarketing-skills/blob/main/LICENSE
---

# GitHub Presence
## When to Use

Use this skill when you need when the user wants to optimize their GitHub profile, README, or project discoverability. Trigger phrases include "GitHub README," "README optimization," "GitHub profile," "GitHub stars," "GitHub discoverability," "awesome lists," or "GitHub marketing.".

GitHub is where developers evaluate your project before trying it. This skill covers README optimization, profile READMEs, discoverability through topics and awesome lists, and using GitHub features for marketing.

---

## Before You Start

1. Read `.agents/developer-audience-context.md` if it exists
2. Audit your current GitHub presence (profile, pinned repos, READMEs)
3. Understand: GitHub is often the first technical evaluation — optimize accordingly

---

## README Structure

### The Anatomy of a Great README

| Section | Purpose | Required? |
|---------|---------|-----------|
| **Logo/Banner** | Brand recognition, visual appeal | Recommended |
| **Badges** | Quick trust signals, status | Recommended |
| **One-liner** | What it does in one sentence | Required |
| **Hero example** | Immediate "what does it look like?" | Highly recommended |
| **Features** | Why use this over alternatives | Required |
| **Quick start** | Get running in < 2 minutes | Required |
| **Installation** | All installation methods | Required |
| **Usage** | Core usage examples | Required |
| **Documentation** | Link to full docs | Required |
| **Contributing** | How to contribute | Recommended |
| **License** | Legal clarity | Required |

### README Template

```markdown
<div align="center">
  <img src="logo.svg" alt="Project Name" width="200">
  <h1>Project Name</h1>
  <p><strong>One compelling sentence explaining what this does.</strong></p>

  <!-- Badges -->
  <a href="https://github.com/org/repo/actions"><img src="https://github.com/org/repo/workflows/CI/badge.svg" alt="CI"></a>
  <a href="https://www.npmjs.com/package/name"><img src="https://img.shields.io/npm/v/name.svg" alt="npm version"></a>
  <a href="https://github.com/org/repo/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
  <a href="https://discord.gg/invite"><img src="https://img.shields.io/discord/123456789" alt="Discord"></a>

  <br>
  <br>

  <a href="https://docs.example.com">Documentation</a> •
  <a href="https://example.com">Website</a> •
  <a href="https://discord.gg/invite">Discord</a>
</div>

---

## Why Project Name?

- **Feature 1** — Brief explanation
- **Feature 2** — Brief explanation
- **Feature 3** — Brief explanation

## Quick Start

```bash
npm install project-name
```

```javascript
import { thing } from 'project-name';

const result = thing.doSomething();
console.log(result);
```

## Installation

### npm
```bash
npm install project-name
```

### yarn
```bash
yarn add project-name
```

### pnpm
```bash
pnpm add project-name
```

## Usage

### Basic Example

```javascript
// Code example with comments
```

### Advanced Example

```javascript
// More complex example
```

## Documentation

Full documentation available at [docs.example.com](https://docs.example.com)

- [Getting Started](https://docs.example.com/getting-started)
- [API Reference](https://docs.example.com/api)
- [Examples](https://docs.example.com/examples)

## Contributing

We welcome contributions! Please see [CONTRIBUTING.md](https://github.com/jonathimer/devmarketing-skills/tree/main/skills/github-presence/CONTRIBUTING.md) for details.

## License

MIT © [Your Name](https://yoursite.com)
```

---

## Badges That Matter

### Trust Signal Badges

| Badge | What it shows | When to use |
|-------|--------------|-------------|
| CI/Build status | Code quality | Always |
| Version | Latest release | Always for packages |
| License | Legal clarity | Always |
| Downloads/installs | Adoption | When impressive |
| Coverage | Test quality | If > 70% |
| Security | Audit status | If you have it |

### Community Badges

| Badge | Source | Purpose |
|-------|--------|---------|
| Discord members | shields.io | Show active community |
| GitHub stars | shields.io | Social proof |
| Contributors | shields.io | Open source health |
| Last commit | shields.io | Project activity |

### Badge Services

| Service | URL | Best for |
|---------|-----|----------|
| Shields.io | shields.io | Most badges |
| Badgen | badgen.net | Fast, minimal |
| GitHub badges | Native | Actions, issues |

### Badge Examples

```markdown
<!-- Build status -->
![CI](https://github.com/org/repo/workflows/CI/badge.svg)

<!-- npm version -->
[![npm](https://img.shields.io/npm/v/package-name.svg)](https://www.npmjs.com/package/package-name)

<!-- Downloads -->
[![Downloads](https://img.shields.io/npm/dm/package-name.svg)](https://www.npmjs.com/package/package-name)

<!-- License -->
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

<!-- Discord -->
[![Discord](https://img.shields.io/discord/SERVER_ID?color=7289da&logo=discord&logoColor=white)](https://discord.gg/invite)

<!-- Stars -->
[![GitHub stars](https://img.shields.io/github/stars/org/repo?style=social)](https://github.com/org/repo)
```

---

## Profile README

### Setting Up Profile README

1. Create a repository with your username (e.g., `github.com/yourname/yourname`)
2. Add a `README.md` file
3. This displays on your profile page

### Profile README Structure

```markdown
# Hi, I'm [Name] 👋

[One sentence about what you do]

## What I'm Working On

- 🔭 Building [project] — [brief description]
- 🌱 Learning [technology]
- 💬 Ask me about [expertise areas]

## Projects

| Project | Description | Stars |
|---------|-------------|-------|
| [Project 1](https://github.com/jonathimer/devmarketing-skills/tree/main/skills/github-presence/link) | Brief description | ![Stars](https://github.com/jonathimer/devmarketing-skills/tree/main/skills/github-presence/badge) |
| [Project 2](https://github.com/jonathimer/devmarketing-skills/tree/main/skills/github-presence/link) | Brief description | ![Stars](https://github.com/jonathimer/devmarketing-skills/tree/main/skills/github-presence/badge) |

## Recent Blog Posts

<!-- BLOG-POST-LIST:START -->
<!-- Automated with GitHub Actions -->
<!-- BLOG-POST-LIST:END -->

## Connect

[![Twitter](https://img.shields.io/badge/-Twitter-1DA1F2?style=flat&logo=twitter&logoColor=white)](https://twitter.com/handle)
[![LinkedIn](https://img.shields.io/badge/-LinkedIn-0077B5?style=flat&logo=linkedin&logoColor=white)](https://linkedin.com/in/handle)

## GitHub Stats

![Your GitHub stats](https://github-readme-stats.vercel.app/api?username=yourusername&show_icons=true)
```

### Profile README Best Practices

| Do | Don't |
|----|-------|
| Keep it scannable | Write paragraphs |
| Show your best projects | List everything |
| Include current work | Let it get stale |
| Add contact methods | Make it hard to reach you |
| Show personality | Be generic |

---

## Discoverability

### GitHub Topics

Topics are how people find repositories. Optimize for search.

| Topic strategy | Example |
|----------------|---------|
| Technology | `javascript`, `rust`, `python` |
| Framework | `react`, `nextjs`, `django` |
| Use case | `cli`, `api`, `testing` |
| Category | `developer-tools`, `devops` |
| Problem | `authentication`, `caching` |

**Add topics**: Repository settings → Topics (up to 20)

### Search Optimization

GitHub search considers:
1. **Repository name** — Include main keyword
2. **Description** — 350 chars, keyword-rich
3. **README content** — Full text indexed
4. **Topics** — Category matching
5. **Language** — Auto-detected

### Awesome Lists

Getting on awesome lists drives traffic and credibility.

| Step | Action |
|------|--------|
| 1 | Find relevant awesome lists (search "awesome + [topic]") |
| 2 | Check list requirements (quality, activity, docs) |
| 3 | Ensure your project meets criteria |
| 4 | Submit PR following list's guidelines |
| 5 | Be patient — curation takes time |

**Popular awesome lists for dev tools**:
- `awesome-cli-apps`
- `awesome-selfhosted`
- `awesome-nodejs`
- `awesome-python`
- `awesome-go`
- `awesome-rust`
- `awesome-devops`

---

## GitHub Actions for Marketing

### Automated README Updates

```yaml
# .github/workflows/readme-update.yml
name: Update README

on:
  schedule:
    - cron: '0 0 * * *'  # Daily
  workflow_dispatch:

jobs:
  update:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Example: Update blog post list
      - uses: gautamkrishnar/blog-post-workflow@master
        with:
          feed_list: "https://yourblog.com/feed"

      - name: Commit changes
        run: |
          git config --local user.email "action@github.com"
          git config --local user.name "GitHub Action"
          git add -A
          git diff --quiet && git diff --staged --quiet || git commit -m "Update README"
          git push
```

### Metrics and Stats

```yaml
# Auto-update GitHub stats image
- uses: lowlighter/metrics@latest
  with:
    token: ${{ secrets.METRICS_TOKEN }}
    filename: github-metrics.svg
```

### Release Announcements

```yaml
# Tweet on new release
name: Release Announcement
on:
  release:
    types: [published]

jobs:
  announce:
    runs-on: ubuntu-latest
    steps:
      - name: Tweet
        uses: ethomson/send-tweet-action@v1
        with:
          status: "🚀 ${{ github.repository }} ${{ github.event.release.tag_name }} released! ${{ github.event.release.html_url }}"
          consumer-key: ${{ secrets.TWITTER_CONSUMER_KEY }}
          # ... other secrets
```

---

## GitHub Sponsors

### Setting Up Sponsors

1. Join GitHub Sponsors (github.com/sponsors)
2. Create compelling tier descriptions
3. Set up funding.yml in repos

**funding.yml example**:
```yaml
github: [yourusername]
patreon: yourpatreon
open_collective: yourproject
ko_fi: yourkofi
custom: ["https://buymeacoffee.com/you"]
```

### Sponsor Tiers That Work

| Tier | Price | Offer |
|------|-------|-------|
| **Supporter** | $5/mo | Thanks + name in README |
| **Backer** | $15/mo | Logo in README + Discord role |
| **Sponsor** | $50/mo | Priority support + feature voting |
| **Enterprise** | $200+/mo | Dedicated support + consultation |

---

## Platform-Specific Do's and Don'ts

### Do's

1. **Do** optimize your README for first impression
2. **Do** use badges for quick trust signals
3. **Do** add relevant topics (up to 20)
4. **Do** keep your profile README current
5. **Do** respond to issues and PRs promptly
6. **Do** pin your best repositories
7. **Do** include clear installation instructions
8. **Do** submit to relevant awesome lists

### Don'ts

1. **Don't** neglect the README — it's your landing page
2. **Don't** use too many badges (cluttered)
3. **Don't** let issues pile up unanswered
4. **Don't** forget a license file
5. **Don't** use low-quality or broken images
6. **Don't** write walls of text without structure
7. **Don't** ignore contribution guidelines

---

## Measuring Success

### GitHub Metrics to Track

| Metric | What it tells you | Goal |
|--------|-------------------|------|
| Stars | Interest/bookmarks | Growth over time |
| Forks | Active usage | Quality > quantity |
| Clones | People trying it | Pre-install interest |
| Traffic | Profile/repo views | Awareness |
| Referrers | Where traffic comes from | Channel effectiveness |
| Contributors | Community health | Sustainable project |

### Traffic Insights

Access via: Repository → Insights → Traffic

- Views and unique visitors
- Popular content (which files)
- Referring sites
- Clone activity

---

## Tools

| Tool | Use case |
|------|----------|
| **[Octolens](https://octolens.com)** | Monitor GitHub for mentions of your project, competitors, and relevant discussions. Get alerts when people talk about problems you solve. |
| **Shields.io** | Generate status badges |
| **GitHub Readme Stats** | Dynamic stats for profile |
| **Carbon** | Beautiful code screenshots |
| **readme.so** | README generator |
| **Metrics** | Advanced profile stats |

---

## README Audit Checklist

- [ ] Clear, keyword-rich name and description
- [ ] Badges show CI status, version, license
- [ ] One-liner explains what it does
- [ ] Quick start gets users running in < 2 min
- [ ] Code examples are copy-pasteable
- [ ] All links work and are HTTPS
- [ ] Images have alt text
- [ ] Mobile-readable formatting
- [ ] License file present
- [ ] Contributing guidelines exist
- [ ] Topics are set (up to 20)
- [ ] Social preview image uploaded

---

## Related Skills

- `developer-audience-context` — Know who evaluates your repo
- `hacker-news-strategy` — HN users check GitHub before upvoting
- `reddit-engagement` — Redditors evaluate via GitHub
- `dev-to-hashnode` — Link from README to content

## Limitations

- Use this skill only when the task clearly matches its upstream source and local project context.
- Verify commands, generated code, dependencies, credentials, and external service behavior before applying changes.
- Do not treat examples as a substitute for environment-specific tests, security review, or user approval for destructive or costly actions.


---
name: github-workflow-automation
description: "Patterns for automating GitHub workflows with AI assistance, inspired by [Gemini CLI](https://github.com/google-gemini/gemini-cli) and modern DevOps practices."
risk: critical
source: community
date_added: "2026-02-27"
---

# 🔧 GitHub Workflow Automation

> Patterns for automating GitHub workflows with AI assistance, inspired by [Gemini CLI](https://github.com/google-gemini/gemini-cli) and modern DevOps practices.

## When to Use This Skill

Use this skill when:

- Automating PR reviews with AI
- Setting up issue triage automation
- Creating GitHub Actions workflows
- Integrating AI into CI/CD pipelines
- Automating Git operations (rebases, cherry-picks)

---

## 1. Automated PR Review

### 1.1 PR Review Action

```yaml
# .github/workflows/ai-review.yml
name: AI Code Review

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  review:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Get changed files
        id: changed
        run: |
          files=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
          echo "files<<EOF" >> $GITHUB_OUTPUT
          echo "$files" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Get diff
        id: diff
        run: |
          diff=$(git diff origin/${{ github.base_ref }}...HEAD)
          echo "diff<<EOF" >> $GITHUB_OUTPUT
          echo "$diff" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: AI Review
        uses: actions/github-script@v7
        with:
          script: |
            const { Anthropic } = require('@anthropic-ai/sdk');
            const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });

            const response = await client.messages.create({
              model: "claude-3-sonnet-20240229",
              max_tokens: 4096,
              messages: [{
                role: "user",
                content: `Review this PR diff and provide feedback:

                Changed files: ${{ steps.changed.outputs.files }}

                Diff:
                ${{ steps.diff.outputs.diff }}

                Provide:
                1. Summary of changes
                2. Potential issues or bugs
                3. Suggestions for improvement
                4. Security concerns if any

                Format as GitHub markdown.`
              }]
            });

            await github.rest.pulls.createReview({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: context.issue.number,
              body: response.content[0].text,
              event: 'COMMENT'
            });
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
```

### 1.2 Review Comment Patterns

````markdown
# AI Review Structure

## 📋 Summary

Brief description of what this PR does.

## ✅ What looks good

- Well-structured code
- Good test coverage
- Clear naming conventions

## ⚠ Potential Issues

1. **Line 42**: Possible null pointer exception
   ```javascript
   // Current
   user.profile.name;
   // Suggested
   user?.profile?.name ?? "Unknown";
   ```
````

2. **Line 78**: Consider error handling
   ```javascript
   // Add try-catch or .catch()
   ```

## 💡 Suggestions

- Consider extracting the validation logic into a separate function
- Add JSDoc comments for public methods

## 🔒 Security Notes

- No sensitive data exposure detected
- API key handling looks correct

````

### 1.3 Focused Reviews

```yaml
# Review only specific file types
- name: Filter code files
  run: |
    files=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | \
            grep -E '\.(ts|tsx|js|jsx|py|go)$' || true)
    echo "code_files=$files" >> $GITHUB_OUTPUT

# Review with context
- name: AI Review with context
  run: |
    # Include relevant context files
    context=""
    for file in ${{ steps.changed.outputs.files }}; do
      if [[ -f "$file" ]]; then
        context+="=== $file ===\n$(cat $file)\n\n"
      fi
    done

    # Send to AI with full file context
````

---

## 2. Issue Triage Automation

### 2.1 Auto-label Issues

```yaml
# .github/workflows/issue-triage.yml
name: Issue Triage

on:
  issues:
    types: [opened]

jobs:
  triage:
    runs-on: ubuntu-latest
    permissions:
      issues: write

    steps:
      - name: Analyze issue
        uses: actions/github-script@v7
        with:
          script: |
            const issue = context.payload.issue;

            // Call AI to analyze
            const analysis = await analyzeIssue(issue.title, issue.body);

            // Apply labels
            const labels = [];

            if (analysis.type === 'bug') {
              labels.push('bug');
              if (analysis.severity === 'high') labels.push('priority: high');
            } else if (analysis.type === 'feature') {
              labels.push('enhancement');
            } else if (analysis.type === 'question') {
              labels.push('question');
            }

            if (analysis.area) {
              labels.push(`area: ${analysis.area}`);
            }

            await github.rest.issues.addLabels({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: issue.number,
              labels: labels
            });

            // Add initial response
            if (analysis.type === 'bug' && !analysis.hasReproSteps) {
              await github.rest.issues.createComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: issue.number,
                body: `Thanks for reporting this issue!

To help us investigate, could you please provide:
- Steps to reproduce the issue
- Expected behavior
- Actual behavior
- Environment (OS, version, etc.)

This will help us resolve your issue faster. 🙏`
              });
            }
```

### 2.2 Issue Analysis Prompt

```typescript
const TRIAGE_PROMPT = `
Analyze this GitHub issue and classify it:

Title: {title}
Body: {body}

Return JSON with:
{
  "type": "bug" | "feature" | "question" | "docs" | "other",
  "severity": "low" | "medium" | "high" | "critical",
  "area": "frontend" | "backend" | "api" | "docs" | "ci" | "other",
  "summary": "one-line summary",
  "hasReproSteps": boolean,
  "isFirstContribution": boolean,
  "suggestedLabels": ["label1", "label2"],
  "suggestedAssignees": ["username"] // based on area expertise
}
`;
```

### 2.3 Stale Issue Management

```yaml
# .github/workflows/stale.yml
name: Manage Stale Issues

on:
  schedule:
    - cron: "0 0 * * *" # Daily

jobs:
  stale:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/stale@v9
        with:
          stale-issue-message: |
            This issue has been automatically marked as stale because it has not had
            recent activity. It will be closed in 14 days if no further activity occurs.

            If this issue is still relevant:
            - Add a comment with an update
            - Remove the `stale` label

            Thank you for your contributions! 🙏

          stale-pr-message: |
            This PR has been automatically marked as stale. Please update it or it
            will be closed in 14 days.

          days-before-stale: 60
          days-before-close: 14
          stale-issue-label: "stale"
          stale-pr-label: "stale"
          exempt-issue-labels: "pinned,security,in-progress"
          exempt-pr-labels: "pinned,security"
```

---

## 3. CI/CD Integration

### 3.1 Smart Test Selection

```yaml
# .github/workflows/smart-tests.yml
name: Smart Test Selection

on:
  pull_request:

jobs:
  analyze:
    runs-on: ubuntu-latest
    outputs:
      test_suites: ${{ steps.analyze.outputs.suites }}

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Analyze changes
        id: analyze
        run: |
          # Get changed files
          changed=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)

          # Determine which test suites to run
          suites="[]"

          if echo "$changed" | grep -q "^src/api/"; then
            suites=$(echo $suites | jq '. + ["api"]')
          fi

          if echo "$changed" | grep -q "^src/frontend/"; then
            suites=$(echo $suites | jq '. + ["frontend"]')
          fi

          if echo "$changed" | grep -q "^src/database/"; then
            suites=$(echo $suites | jq '. + ["database", "api"]')
          fi

          # If nothing specific, run all
          if [ "$suites" = "[]" ]; then
            suites='["all"]'
          fi

          echo "suites=$suites" >> $GITHUB_OUTPUT

  test:
    needs: analyze
    runs-on: ubuntu-latest
    strategy:
      matrix:
        suite: ${{ fromJson(needs.analyze.outputs.test_suites) }}

    steps:
      - uses: actions/checkout@v4

      - name: Run tests
        run: |
          if [ "${{ matrix.suite }}" = "all" ]; then
            npm test
          else
            npm test -- --suite ${{ matrix.suite }}
          fi
```

### 3.2 Deployment with AI Validation

```yaml
# .github/workflows/deploy.yml
name: Deploy with AI Validation

on:
  push:
    branches: [main]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Get deployment changes
        id: changes
        run: |
          # Get commits since last deployment
          last_deploy=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
          if [ -n "$last_deploy" ]; then
            changes=$(git log --oneline $last_deploy..HEAD)
          else
            changes=$(git log --oneline -10)
          fi
          echo "changes<<EOF" >> $GITHUB_OUTPUT
          echo "$changes" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: AI Risk Assessment
        id: assess
        uses: actions/github-script@v7
        with:
          script: |
            // Analyze changes for deployment risk
            const prompt = `
            Analyze these changes for deployment risk:

            ${process.env.CHANGES}

            Return JSON:
            {
              "riskLevel": "low" | "medium" | "high",
              "concerns": ["concern1", "concern2"],
              "recommendations": ["rec1", "rec2"],
              "requiresManualApproval": boolean
            }
            `;

            // Call AI and parse response
            const analysis = await callAI(prompt);

            if (analysis.riskLevel === 'high') {
              core.setFailed('High-risk deployment detected. Manual review required.');
            }

            return analysis;
        env:
          CHANGES: ${{ steps.changes.outputs.changes }}

  deploy:
    needs: validate
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Deploy
        run: |
          echo "Deploying to production..."
          # Deployment commands here
```

### 3.3 Rollback Automation

```yaml
# .github/workflows/rollback.yml
name: Automated Rollback

on:
  workflow_dispatch:
    inputs:
      reason:
        description: "Reason for rollback"
        required: true

jobs:
  rollback:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Find last stable version
        id: stable
        run: |
          # Find last successful deployment
          stable=$(git tag -l 'v*' --sort=-version:refname | head -1)
          echo "version=$stable" >> $GITHUB_OUTPUT

      - name: Rollback
        run: |
          git checkout ${{ steps.stable.outputs.version }}
          # Deploy stable version
          npm run deploy

      - name: Notify team
        uses: slackapi/slack-github-action@v1
        with:
          payload: |
            {
              "text": "🔄 Production rolled back to ${{ steps.stable.outputs.version }}",
              "blocks": [
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "*Rollback executed*\n• Version: `${{ steps.stable.outputs.version }}`\n• Reason: ${{ inputs.reason }}\n• Triggered by: ${{ github.actor }}"
                  }
                }
              ]
            }
```

---

## 4. Git Operations

### 4.1 Automated Rebasing

```yaml
# .github/workflows/auto-rebase.yml
name: Auto Rebase

on:
  issue_comment:
    types: [created]

jobs:
  rebase:
    if: github.event.issue.pull_request && contains(github.event.comment.body, '/rebase')
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
          token: ${{ secrets.GITHUB_TOKEN }}

      - name: Setup Git
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"

      - name: Rebase PR
        run: |
          # Fetch PR branch
          gh pr checkout ${{ github.event.issue.number }}

          # Rebase onto main
          git fetch origin main
          git rebase origin/main

          # Force push
          git push --force-with-lease
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Comment result
        uses: actions/github-script@v7
        with:
          script: |
            github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: '✅ Successfully rebased onto main!'
            })
```

### 4.2 Smart Cherry-Pick

```typescript
// AI-assisted cherry-pick that handles conflicts
async function smartCherryPick(commitHash: string, targetBranch: string) {
  // Get commit info
  const commitInfo = await exec(`git show ${commitHash} --stat`);

  // Check for potential conflicts
  const targetDiff = await exec(
    `git diff ${targetBranch}...HEAD -- ${affectedFiles}`
  );

  // AI analysis
  const analysis = await ai.analyze(`
    I need to cherry-pick this commit to ${targetBranch}:

    ${commitInfo}

    Current state of affected files on ${targetBranch}:
    ${targetDiff}

    Will there be conflicts? If so, suggest resolution strategy.
  `);

  if (analysis.willConflict) {
    // Create branch for manual resolution
    await exec(
      `git checkout -b cherry-pick-${commitHash.slice(0, 7)} ${targetBranch}`
    );
    const result = await exec(`git cherry-pick ${commitHash}`, {
      allowFail: true,
    });

    if (result.failed) {
      // AI-assisted conflict resolution
      const conflicts = await getConflicts();
      for (const conflict of conflicts) {
        const resolution = await ai.resolveConflict(conflict);
        await applyResolution(conflict.file, resolution);
      }
    }
  } else {
    await exec(`git checkout ${targetBranch}`);
    await exec(`git cherry-pick ${commitHash}`);
  }
}
```

### 4.3 Branch Cleanup

```yaml
# .github/workflows/branch-cleanup.yml
name: Branch Cleanup

on:
  schedule:
    - cron: '0 0 * * 0'  # Weekly
  workflow_dispatch:

jobs:
  cleanup:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Find stale branches
        id: stale
        run: |
          # Branches not updated in 30 days
          stale=$(git for-each-ref --sort=-committerdate refs/remotes/origin \
            --format='%(refname:short) %(committerdate:relative)' | \
            grep -E '[3-9][0-9]+ days|[0-9]+ months|[0-9]+ years' | \
            grep -v 'origin/main\|origin/develop' | \
            cut -d' ' -f1 | sed 's|origin/||')

          echo "branches<<EOF" >> $GITHUB_OUTPUT
          echo "$stale" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Create cleanup PR
        if: steps.stale.outputs.branches != ''
        uses: actions/github-script@v7
        with:
          script: |
            const branches = `${{ steps.stale.outputs.branches }}`.split('\n').filter(Boolean);

            const body = `## 🧹 Stale Branch Cleanup

The following branches haven't been updated in over 30 days:

${branches.map(b => `- \`${b}\``).join('\n')}

### Actions:
- [ ] Review each branch
- [ ] Delete branches that are no longer needed
- Comment \`/keep branch-name\` to preserve specific branches
`;

            await github.rest.issues.create({
              owner: context.repo.owner,
              repo: context.repo.repo,
              title: 'Stale Branch Cleanup',
              body: body,
              labels: ['housekeeping']
            });
```

---

## 5. On-Demand Assistance

### 5.1 @mention Bot

```yaml
# .github/workflows/mention-bot.yml
name: AI Mention Bot

on:
  issue_comment:
    types: [created]
  pull_request_review_comment:
    types: [created]

jobs:
  respond:
    if: contains(github.event.comment.body, '@ai-helper')
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Extract question
        id: question
        run: |
          # Extract text after @ai-helper
          question=$(echo "${{ github.event.comment.body }}" | sed 's/.*@ai-helper//')
          echo "question=$question" >> $GITHUB_OUTPUT

      - name: Get context
        id: context
        run: |
          if [ "${{ github.event.issue.pull_request }}" != "" ]; then
            # It's a PR - get diff
            gh pr diff ${{ github.event.issue.number }} > context.txt
          else
            # It's an issue - get description
            gh issue view ${{ github.event.issue.number }} --json body -q .body > context.txt
          fi
          echo "context=$(cat context.txt)" >> $GITHUB_OUTPUT
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: AI Response
        uses: actions/github-script@v7
        with:
          script: |
            const response = await ai.chat(`
              Context: ${process.env.CONTEXT}

              Question: ${process.env.QUESTION}

              Provide a helpful, specific answer. Include code examples if relevant.
            `);

            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: response
            });
        env:
          CONTEXT: ${{ steps.context.outputs.context }}
          QUESTION: ${{ steps.question.outputs.question }}
```

### 5.2 Command Patterns

```markdown
## Available Commands

| Command              | Description                 |
| :------------------- | :-------------------------- |
| `@ai-helper explain` | Explain the code in this PR |
| `@ai-helper review`  | Request AI code review      |
| `@ai-helper fix`     | Suggest fixes for issues    |
| `@ai-helper test`    | Generate test cases         |
| `@ai-helper docs`    | Generate documentation      |
| `/rebase`            | Rebase PR onto main         |
| `/update`            | Update PR branch from main  |
| `/approve`           | Mark as approved by bot     |
| `/label bug`         | Add 'bug' label             |
| `/assign @user`      | Assign to user              |
```

---

## 6. Repository Configuration

### 6.1 CODEOWNERS

```
# .github/CODEOWNERS

# Global owners
* @org/core-team

# Frontend
/src/frontend/ @org/frontend-team
*.tsx @org/frontend-team
*.css @org/frontend-team

# Backend
/src/api/ @org/backend-team
/src/database/ @org/backend-team

# Infrastructure
/.github/ @org/devops-team
/terraform/ @org/devops-team
Dockerfile @org/devops-team

# Docs
/docs/ @org/docs-team
*.md @org/docs-team

# Security-sensitive
/src/auth/ @org/security-team
/src/crypto/ @org/security-team
```

### 6.2 Branch Protection

```yaml
# Set up via GitHub API
- name: Configure branch protection
  uses: actions/github-script@v7
  with:
    script: |
      await github.rest.repos.updateBranchProtection({
        owner: context.repo.owner,
        repo: context.repo.repo,
        branch: 'main',
        required_status_checks: {
          strict: true,
          contexts: ['test', 'lint', 'ai-review']
        },
        enforce_admins: true,
        required_pull_request_reviews: {
          required_approving_review_count: 1,
          require_code_owner_reviews: true,
          dismiss_stale_reviews: true
        },
        restrictions: null,
        required_linear_history: true,
        allow_force_pushes: false,
        allow_deletions: false
      });
```

---

## Best Practices

### Security

- [ ] Store API keys in GitHub Secrets
- [ ] Use minimal permissions in workflows
- [ ] Validate all inputs
- [ ] Don't expose sensitive data in logs

### Performance

- [ ] Cache dependencies
- [ ] Use matrix builds for parallel testing
- [ ] Skip unnecessary jobs with path filters
- [ ] Use self-hosted runners for heavy workloads

### Reliability

- [ ] Add timeouts to jobs
- [ ] Handle rate limits gracefully
- [ ] Implement retry logic
- [ ] Have rollback procedures

---

## Resources

- [Gemini CLI GitHub Action](https://github.com/google-github-actions/run-gemini-cli)
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
- [GitHub REST API](https://docs.github.com/en/rest)
- [CODEOWNERS Syntax](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners)

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: gitlab-automation
description: "Automate GitLab project management, issues, merge requests, pipelines, branches, and user operations via Rube MCP (Composio). Always search tools first for current schemas."
risk: critical
source: community
date_added: "2026-02-27"
---

# GitLab Automation via Rube MCP

Automate GitLab operations including project management, issue tracking, merge request workflows, CI/CD pipeline monitoring, branch management, and user administration through Composio's GitLab toolkit.

## Prerequisites

- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active GitLab connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `gitlab`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas

## Setup

**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.

1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `gitlab`
3. If connection is not ACTIVE, follow the returned auth link to complete GitLab OAuth
4. Confirm connection status shows ACTIVE before running any workflows

## Core Workflows

### 1. Manage Issues

**When to use**: User wants to create, update, list, or search issues in a GitLab project

**Tool sequence**:
1. `GITLAB_GET_PROJECTS` - Find the target project and get its ID [Prerequisite]
2. `GITLAB_LIST_PROJECT_ISSUES` - List and filter issues for a project [Required]
3. `GITLAB_CREATE_PROJECT_ISSUE` - Create a new issue [Required for create]
4. `GITLAB_UPDATE_PROJECT_ISSUE` - Update an existing issue (title, labels, state, assignees) [Required for update]
5. `GITLAB_LIST_PROJECT_USERS` - Find user IDs for assignment [Optional]

**Key parameters**:
- `id`: Project ID (integer) or URL-encoded path (e.g., `"my-group/my-project"`)
- `title`: Issue title (required for creation)
- `description`: Issue body text (max 1,048,576 characters)
- `labels`: Comma-separated label names (e.g., `"bug,critical"`)
- `add_labels` / `remove_labels`: Add or remove labels without replacing all
- `state`: Filter by `"all"`, `"opened"`, or `"closed"`
- `state_event`: `"close"` or `"reopen"` to change issue state
- `assignee_ids`: Array of user IDs; use `[0]` to unassign all
- `issue_iid`: Internal issue ID within the project (required for updates)
- `milestone`: Filter by milestone title
- `search`: Search in title and description
- `scope`: `"created_by_me"`, `"assigned_to_me"`, or `"all"`
- `page` / `per_page`: Pagination (default per_page: 20)

**Pitfalls**:
- `id` accepts either integer project ID or URL-encoded path; wrong IDs yield 4xx errors
- `issue_iid` is the project-internal ID (shown as #42), different from the global issue ID
- Labels in `labels` field replace ALL existing labels; use `add_labels`/`remove_labels` for incremental changes
- Setting `assignee_ids` to empty array does NOT unassign; use `[0]` instead
- `updated_at` field requires administrator or project/group owner rights

### 2. Manage Merge Requests

**When to use**: User wants to list, filter, or review merge requests in a project

**Tool sequence**:
1. `GITLAB_GET_PROJECT` - Get project details and verify access [Prerequisite]
2. `GITLAB_GET_PROJECT_MERGE_REQUESTS` - List and filter merge requests [Required]
3. `GITLAB_GET_REPOSITORY_BRANCHES` - Verify source/target branches [Optional]
4. `GITLAB_LIST_ALL_PROJECT_MEMBERS` - Find reviewers/assignees [Optional]

**Key parameters**:
- `id`: Project ID or URL-encoded path
- `state`: `"opened"`, `"closed"`, `"locked"`, `"merged"`, or `"all"`
- `scope`: `"created_by_me"` (default), `"assigned_to_me"`, or `"all"`
- `source_branch` / `target_branch`: Filter by branch names
- `author_id` / `author_username`: Filter by MR author
- `assignee_id`: Filter by assignee (use `None` for unassigned, `Any` for assigned)
- `reviewer_id` / `reviewer_username`: Filter by reviewer
- `labels`: Comma-separated label filter
- `search`: Search in title and description
- `wip`: `"yes"` for draft MRs, `"no"` for non-draft
- `order_by`: `"created_at"` (default), `"title"`, `"merged_at"`, `"updated_at"`
- `view`: `"simple"` for minimal fields
- `iids[]`: Filter by specific MR internal IDs

**Pitfalls**:
- Default `scope` is `"created_by_me"` which limits results; use `"all"` for complete listings
- `author_id` and `author_username` are mutually exclusive
- `reviewer_id` and `reviewer_username` are mutually exclusive
- `approved` filter requires the `mr_approved_filter` feature flag (disabled by default)
- Large MR histories can be noisy; use filters and moderate `per_page` values

### 3. Manage Projects and Repositories

**When to use**: User wants to list projects, create new projects, or manage branches

**Tool sequence**:
1. `GITLAB_GET_PROJECTS` - List all accessible projects with filters [Required]
2. `GITLAB_GET_PROJECT` - Get detailed info for a specific project [Optional]
3. `GITLAB_LIST_USER_PROJECTS` - List projects owned by a specific user [Optional]
4. `GITLAB_CREATE_PROJECT` - Create a new project [Required for create]
5. `GITLAB_GET_REPOSITORY_BRANCHES` - List branches in a project [Required for branch ops]
6. `GITLAB_CREATE_REPOSITORY_BRANCH` - Create a new branch [Optional]
7. `GITLAB_GET_REPOSITORY_BRANCH` - Get details of a specific branch [Optional]
8. `GITLAB_LIST_REPOSITORY_COMMITS` - View commit history [Optional]
9. `GITLAB_GET_PROJECT_LANGUAGES` - Get language breakdown [Optional]

**Key parameters**:
- `name` / `path`: Project name and URL-friendly path (both required for creation)
- `visibility`: `"private"`, `"internal"`, or `"public"`
- `namespace_id`: Group or user ID for project placement
- `search`: Case-insensitive substring search for projects
- `membership`: `true` to limit to projects user is a member of
- `owned`: `true` to limit to user-owned projects
- `project_id`: Project ID for branch operations
- `branch_name`: Name for new branch
- `ref`: Source branch or commit SHA for new branch creation
- `order_by`: `"id"`, `"name"`, `"path"`, `"created_at"`, `"updated_at"`, `"star_count"`, `"last_activity_at"`

**Pitfalls**:
- `GITLAB_GET_PROJECTS` pagination is required for complete coverage; stopping at first page misses projects
- Some responses place items under `data.details`; parse the actual returned list structure
- Most follow-up calls depend on correct `project_id`; verify with `GITLAB_GET_PROJECT` first
- Invalid `branch_name`/`ref`/`sha` causes client errors; verify branch existence via `GITLAB_GET_REPOSITORY_BRANCHES` first
- Both `name` and `path` are required for `GITLAB_CREATE_PROJECT`

### 4. Monitor CI/CD Pipelines

**When to use**: User wants to check pipeline status, list jobs, or monitor CI/CD runs

**Tool sequence**:
1. `GITLAB_GET_PROJECT` - Verify project access [Prerequisite]
2. `GITLAB_LIST_PROJECT_PIPELINES` - List pipelines with filters [Required]
3. `GITLAB_GET_SINGLE_PIPELINE` - Get detailed info for a specific pipeline [Optional]
4. `GITLAB_LIST_PIPELINE_JOBS` - List jobs within a pipeline [Optional]

**Key parameters**:
- `id`: Project ID or URL-encoded path
- `status`: Filter by `"created"`, `"waiting_for_resource"`, `"preparing"`, `"pending"`, `"running"`, `"success"`, `"failed"`, `"canceled"`, `"skipped"`, `"manual"`, `"scheduled"`
- `scope`: `"running"`, `"pending"`, `"finished"`, `"branches"`, `"tags"`
- `ref`: Branch or tag name
- `sha`: Specific commit SHA
- `source`: Pipeline source (use `"parent_pipeline"` for child pipelines)
- `order_by`: `"id"` (default), `"status"`, `"ref"`, `"updated_at"`, `"user_id"`
- `created_after` / `created_before`: ISO 8601 date filters
- `pipeline_id`: Specific pipeline ID for job listing
- `include_retried`: `true` to include retried jobs (default `false`)

**Pitfalls**:
- Large pipeline histories can be noisy; use `status`, `ref`, and date filters to narrow results
- Use moderate `per_page` values to keep output manageable
- Pipeline job `scope` accepts single status string or array of statuses
- `yaml_errors: true` returns only pipelines with invalid configurations

### 5. Manage Users and Members

**When to use**: User wants to find users, list project members, or check user status

**Tool sequence**:
1. `GITLAB_GET_USERS` - Search and list GitLab users [Required]
2. `GITLAB_GET_USER` - Get details for a specific user by ID [Optional]
3. `GITLAB_GET_USERS_ID_STATUS` - Get user status message and availability [Optional]
4. `GITLAB_LIST_ALL_PROJECT_MEMBERS` - List all project members (direct + inherited) [Required for member listing]
5. `GITLAB_LIST_PROJECT_USERS` - List project users with search filter [Optional]

**Key parameters**:
- `search`: Search by name, username, or public email
- `username`: Get specific user by username
- `active` / `blocked`: Filter by user state
- `id`: Project ID for member listing
- `query`: Filter members by name, email, or username
- `state`: Filter members by `"awaiting"` or `"active"` (Premium/Ultimate)
- `user_ids`: Filter by specific user IDs

**Pitfalls**:
- Many user filters (admins, auditors, extern_uid, two_factor) are admin-only
- `GITLAB_LIST_ALL_PROJECT_MEMBERS` includes direct, inherited, and invited members
- User search is case-insensitive but may not match partial email domains
- Premium/Ultimate features (state filter, seat info) are not available on free plans

## Common Patterns

### ID Resolution
GitLab uses two identifier formats for projects:
- **Numeric ID**: Integer project ID (e.g., `123`)
- **URL-encoded path**: Namespace/project format (e.g., `"my-group%2Fmy-project"` or `"my-group/my-project"`)
- **Issue IID vs ID**: `issue_iid` is the project-internal number (#42); the global `id` is different
- **User ID**: Numeric; resolve via `GITLAB_GET_USERS` with `search` or `username`

### Pagination
GitLab uses offset-based pagination:
- Set `page` (starting at 1) and `per_page` (1-100, default 20)
- Continue incrementing `page` until response returns fewer items than `per_page` or is empty
- Total count may be available in response headers (`X-Total`, `X-Total-Pages`)
- Always paginate to completion for accurate results

### URL-Encoded Paths
When using project paths as identifiers:
- Forward slashes must be URL-encoded: `my-group/my-project` becomes `my-group%2Fmy-project`
- Some tools accept unencoded paths; check schema for each tool
- Prefer numeric IDs when available for reliability

## Known Pitfalls

### ID Formats
- Project `id` field accepts both integer and string (URL-encoded path)
- Issue `issue_iid` is project-scoped; do not confuse with global issue ID
- Pipeline IDs are project-scoped integers
- User IDs are global integers across the GitLab instance

### Rate Limits
- GitLab has per-user rate limits (typically 300-2000 requests/minute depending on plan)
- Large pipeline/issue histories should use date and status filters to reduce result sets
- Paginate responsibly with moderate `per_page` values

### Parameter Quirks
- `labels` field replaces ALL labels; use `add_labels`/`remove_labels` for incremental changes
- `assignee_ids: [0]` unassigns all; empty array does nothing
- `scope` defaults vary: `"created_by_me"` for MRs, `"all"` for issues
- `author_id` and `author_username` are mutually exclusive in MR filters
- Date parameters use ISO 8601 format: `"2024-01-15T10:30:00Z"`

### Plan Restrictions
- Some features require Premium/Ultimate: `epic_id`, `weight`, `iteration_id`, `approved_by_ids`, member `state` filter
- Admin-only features: user management filters, `updated_at` override, custom attributes
- The `mr_approved_filter` feature flag is disabled by default

## Quick Reference

| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List projects | `GITLAB_GET_PROJECTS` | `search`, `membership`, `visibility` |
| Get project details | `GITLAB_GET_PROJECT` | `id` |
| User's projects | `GITLAB_LIST_USER_PROJECTS` | `id`, `search`, `owned` |
| Create project | `GITLAB_CREATE_PROJECT` | `name`, `path`, `visibility` |
| List issues | `GITLAB_LIST_PROJECT_ISSUES` | `id`, `state`, `labels`, `search` |
| Create issue | `GITLAB_CREATE_PROJECT_ISSUE` | `id`, `title`, `description`, `labels` |
| Update issue | `GITLAB_UPDATE_PROJECT_ISSUE` | `id`, `issue_iid`, `state_event` |
| List merge requests | `GITLAB_GET_PROJECT_MERGE_REQUESTS` | `id`, `state`, `scope`, `labels` |
| List branches | `GITLAB_GET_REPOSITORY_BRANCHES` | `project_id`, `search` |
| Get branch | `GITLAB_GET_REPOSITORY_BRANCH` | `project_id`, `branch_name` |
| Create branch | `GITLAB_CREATE_REPOSITORY_BRANCH` | `project_id`, `branch_name`, `ref` |
| List commits | `GITLAB_LIST_REPOSITORY_COMMITS` | project ID, branch ref |
| Project languages | `GITLAB_GET_PROJECT_LANGUAGES` | project ID |
| List pipelines | `GITLAB_LIST_PROJECT_PIPELINES` | `id`, `status`, `ref` |
| Get pipeline | `GITLAB_GET_SINGLE_PIPELINE` | `project_id`, `pipeline_id` |
| List pipeline jobs | `GITLAB_LIST_PIPELINE_JOBS` | `id`, `pipeline_id`, `scope` |
| Search users | `GITLAB_GET_USERS` | `search`, `username`, `active` |
| Get user | `GITLAB_GET_USER` | user ID |
| User status | `GITLAB_GET_USERS_ID_STATUS` | user ID |
| List project members | `GITLAB_LIST_ALL_PROJECT_MEMBERS` | `id`, `query`, `state` |
| List project users | `GITLAB_LIST_PROJECT_USERS` | `id`, `search` |

## When to Use
This skill is applicable to execute the workflow or actions described in the overview.

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: gitlab-ci-patterns
description: "Comprehensive GitLab CI/CD pipeline patterns for automated testing, building, and deployment."
risk: critical
source: community
date_added: "2026-02-27"
---

# GitLab CI Patterns

Comprehensive GitLab CI/CD pipeline patterns for automated testing, building, and deployment.

## Do not use this skill when

- The task is unrelated to gitlab ci patterns
- You need a different domain or tool outside this scope

## Instructions

- Clarify goals, constraints, and required inputs.
- Apply relevant best practices and validate outcomes.
- Provide actionable steps and verification.
- If detailed examples are required, open `resources/implementation-playbook.md`.

## Purpose

Create efficient GitLab CI pipelines with proper stage organization, caching, and deployment strategies.

## Use this skill when

- Automate GitLab-based CI/CD
- Implement multi-stage pipelines
- Configure GitLab Runners
- Deploy to Kubernetes from GitLab
- Implement GitOps workflows

## Basic Pipeline Structure

```yaml
stages:
  - build
  - test
  - deploy

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: "/certs"

build:
  stage: build
  image: node:20
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 hour
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/

test:
  stage: test
  image: node:20
  script:
    - npm ci
    - npm run lint
    - npm test
  coverage: '/Lines\s*:\s*(\d+\.\d+)%/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

deploy:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl apply -f k8s/
    - kubectl rollout status deployment/my-app
  only:
    - main
  environment:
    name: production
    url: https://app.example.com
```

## Docker Build and Push

```yaml
build-docker:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker build -t $CI_REGISTRY_IMAGE:latest .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker push $CI_REGISTRY_IMAGE:latest
  only:
    - main
    - tags
```

## Multi-Environment Deployment

```yaml
.deploy_template: &deploy_template
  image: bitnami/kubectl:latest
  before_script:
    - kubectl config set-cluster k8s --server="$KUBE_URL" --insecure-skip-tls-verify=true
    - kubectl config set-credentials admin --token="$KUBE_TOKEN"
    - kubectl config set-context default --cluster=k8s --user=admin
    - kubectl config use-context default

deploy:staging:
  <<: *deploy_template
  stage: deploy
  script:
    - kubectl apply -f k8s/ -n staging
    - kubectl rollout status deployment/my-app -n staging
  environment:
    name: staging
    url: https://staging.example.com
  only:
    - develop

deploy:production:
  <<: *deploy_template
  stage: deploy
  script:
    - kubectl apply -f k8s/ -n production
    - kubectl rollout status deployment/my-app -n production
  environment:
    name: production
    url: https://app.example.com
  when: manual
  only:
    - main
```

## Terraform Pipeline

```yaml
stages:
  - validate
  - plan
  - apply

variables:
  TF_ROOT: ${CI_PROJECT_DIR}/terraform
  TF_VERSION: "1.6.0"

before_script:
  - cd ${TF_ROOT}
  - terraform --version

validate:
  stage: validate
  image: hashicorp/terraform:${TF_VERSION}
  script:
    - terraform init -backend=false
    - terraform validate
    - terraform fmt -check

plan:
  stage: plan
  image: hashicorp/terraform:${TF_VERSION}
  script:
    - terraform init
    - terraform plan -out=tfplan
  artifacts:
    paths:
      - ${TF_ROOT}/tfplan
    expire_in: 1 day

apply:
  stage: apply
  image: hashicorp/terraform:${TF_VERSION}
  script:
    - terraform init
    - terraform apply -auto-approve tfplan
  dependencies:
    - plan
  when: manual
  only:
    - main
```

## Security Scanning

```yaml
include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Dependency-Scanning.gitlab-ci.yml
  - template: Security/Container-Scanning.gitlab-ci.yml

trivy-scan:
  stage: test
  image: aquasec/trivy:latest
  script:
    - trivy image --exit-code 1 --severity HIGH,CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  allow_failure: true
```

## Caching Strategies

```yaml
# Cache node_modules
build:
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/
    policy: pull-push

# Global cache
cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - .cache/
    - vendor/

# Separate cache per job
job1:
  cache:
    key: job1-cache
    paths:
      - build/

job2:
  cache:
    key: job2-cache
    paths:
      - dist/
```

## Dynamic Child Pipelines

```yaml
generate-pipeline:
  stage: build
  script:
    - python generate_pipeline.py > child-pipeline.yml
  artifacts:
    paths:
      - child-pipeline.yml

trigger-child:
  stage: deploy
  trigger:
    include:
      - artifact: child-pipeline.yml
        job: generate-pipeline
    strategy: depend
```

## Reference Files

- `assets/gitlab-ci.yml.template` - Complete pipeline template
- `references/pipeline-stages.md` - Stage organization patterns

## Best Practices

1. **Use specific image tags** (node:20, not node:latest)
2. **Cache dependencies** appropriately
3. **Use artifacts** for build outputs
4. **Implement manual gates** for production
5. **Use environments** for deployment tracking
6. **Enable merge request pipelines**
7. **Use pipeline schedules** for recurring jobs
8. **Implement security scanning**
9. **Use CI/CD variables** for secrets
10. **Monitor pipeline performance**

## Related Skills

- `github-actions-templates` - For GitHub Actions
- `deployment-pipeline-design` - For architecture
- `secrets-management` - For secrets handling

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: gitops-workflow
description: "Complete guide to implementing GitOps workflows with ArgoCD and Flux for automated Kubernetes deployments."
risk: critical
source: community
date_added: "2026-02-27"
---

# GitOps Workflow

Complete guide to implementing GitOps workflows with ArgoCD and Flux for automated Kubernetes deployments.

## Purpose

Implement declarative, Git-based continuous delivery for Kubernetes using ArgoCD or Flux CD, following OpenGitOps principles.

## Use this skill when

- Set up GitOps for Kubernetes clusters
- Automate application deployments from Git
- Implement progressive delivery strategies
- Manage multi-cluster deployments
- Configure automated sync policies
- Set up secret management in GitOps

## Do not use this skill when

- You need a one-off manual deployment
- You cannot manage cluster access or repo permissions
- You are not deploying to Kubernetes

## Instructions

1. Define repo layout and desired-state conventions.
2. Install ArgoCD or Flux and connect clusters.
3. Configure sync policies, environments, and promotion flow.
4. Validate rollbacks and secret handling.

## Safety

- Avoid auto-sync to production without approvals.
- Keep secrets out of Git and use sealed or external secret managers.

## OpenGitOps Principles

1. **Declarative** - Entire system described declaratively
2. **Versioned and Immutable** - Desired state stored in Git
3. **Pulled Automatically** - Software agents pull desired state
4. **Continuously Reconciled** - Agents reconcile actual vs desired state

## ArgoCD Setup

### 1. Installation

```bash
# Create namespace
kubectl create namespace argocd

# Install ArgoCD
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Get admin password
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
```

**Reference:** See `references/argocd-setup.md` for detailed setup

### 2. Repository Structure

```
gitops-repo/
├── apps/
│   ├── production/
│   │   ├── app1/
│   │   │   ├── kustomization.yaml
│   │   │   └── deployment.yaml
│   │   └── app2/
│   └── staging/
├── infrastructure/
│   ├── ingress-nginx/
│   ├── cert-manager/
│   └── monitoring/
└── argocd/
    ├── applications/
    └── projects/
```

### 3. Create Application

```yaml
# argocd/applications/my-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/org/gitops-repo
    targetRevision: main
    path: apps/production/my-app
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
```

### 4. App of Apps Pattern

```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: applications
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/org/gitops-repo
    targetRevision: main
    path: argocd/applications
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated: {}
```

## Flux CD Setup

### 1. Installation

```bash
# Install Flux CLI
brew install fluxcd/tap/flux

# Alternative: download the official installer, inspect it, then execute it
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
curl -fsSLo "$tmpdir/flux-install.sh" https://fluxcd.io/install.sh
cat "$tmpdir/flux-install.sh"  # review the full installer before sudo
sudo bash "$tmpdir/flux-install.sh"

# Bootstrap Flux
flux bootstrap github \
  --owner=org \
  --repository=gitops-repo \
  --branch=main \
  --path=clusters/production \
  --personal
```

### 2. Create GitRepository

```yaml
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/org/my-app
  ref:
    branch: main
```

### 3. Create Kustomization

```yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 5m
  path: ./deploy
  prune: true
  sourceRef:
    kind: GitRepository
    name: my-app
```

## Sync Policies

### Auto-Sync Configuration

**ArgoCD:**
```yaml
syncPolicy:
  automated:
    prune: true      # Delete resources not in Git
    selfHeal: true   # Reconcile manual changes
    allowEmpty: false
  retry:
    limit: 5
    backoff:
      duration: 5s
      factor: 2
      maxDuration: 3m
```

**Flux:**
```yaml
spec:
  interval: 1m
  prune: true
  wait: true
  timeout: 5m
```

**Reference:** See `references/sync-policies.md`

## Progressive Delivery

### Canary Deployment with ArgoCD Rollouts

```yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: my-app
spec:
  replicas: 5
  strategy:
    canary:
      steps:
      - setWeight: 20
      - pause: {duration: 1m}
      - setWeight: 50
      - pause: {duration: 2m}
      - setWeight: 100
```

### Blue-Green Deployment

```yaml
strategy:
  blueGreen:
    activeService: my-app
    previewService: my-app-preview
    autoPromotionEnabled: false
```

## Secret Management

### External Secrets Operator

```yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-credentials
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-manager
    kind: SecretStore
  target:
    name: db-credentials
  data:
  - secretKey: password
    remoteRef:
      key: prod/db/password
```

### Sealed Secrets

```bash
# Encrypt secret
kubeseal --format yaml < secret.yaml > sealed-secret.yaml

# Commit sealed-secret.yaml to Git
```

## Best Practices

1. **Use separate repos or branches** for different environments
2. **Implement RBAC** for Git repositories
3. **Enable notifications** for sync failures
4. **Use health checks** for custom resources
5. **Implement approval gates** for production
6. **Keep secrets out of Git** (use External Secrets)
7. **Use App of Apps pattern** for organization
8. **Tag releases** for easy rollback
9. **Monitor sync status** with alerts
10. **Test changes** in staging first

## Troubleshooting

**Sync failures:**
```bash
argocd app get my-app
argocd app sync my-app --prune
```

**Out of sync status:**
```bash
argocd app diff my-app
argocd app sync my-app --force
```

## Related Skills

- `k8s-manifest-generator` - For creating manifests
- `helm-chart-scaffolding` - For packaging applications

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: glassmorphism
description: Web and App implementation guide for Glassmorphism. Trigger when user wants a frosted glass effect, blurred backgrounds, transparency, or a sleek MacOS-like feel.
date_added: "2026-06-17"
risk: safe
source: self
source_type: self
---

# Glassmorphism

> "Looking through a frosted window. Interfaces that blend seamlessly with vibrant backgrounds."

## When to Use
Use this sub-style when the user's request matches the aesthetic described above. This is a child reference of the `design-it` skill and is not meant to be triggered directly.

## Core Principles
1. **Background Blur (Backdrop Filter)**: The defining characteristic. Elements blur whatever is underneath them.
2. **Semi-transparent White/Dark Backgrounds**: Panels use rgba() colors to let the background shine through.
3. **Subtle Light Borders**: A 1px semi-transparent white (or light) border to simulate the glass edge catching the light.

## Visual DNA
- **Colors**: Requires a vibrant or textured background to work (e.g., gradients, abstract meshes, or photos). Works beautifully over **Yacht Club** or **Earth-Grounded Elegance** if there is underlying visual texture.
- **Typography**: Clean, geometric sans-serifs. High contrast text (pure white or pure black) is required for legibility against the glass.
- **Shadows**: Soft, subtle drop shadows to detach the glass pane from the background.

## Web Implementation
- Rely heavily on `backdrop-filter: blur()`.
- **CSS Example**:
```css
body {
  /* Requires a complex background to see the glass effect */
  background: url('abstract-mesh.jpg') cover;
}

.glass-panel {
  background: rgba(255, 255, 255, 0.15); /* Light glass */
  /* OR background: rgba(0, 0, 0, 0.25); for Dark glass */

  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);

  border: 1px solid rgba(255, 255, 255, 0.3); /* The glass edge */
  border-radius: 16px;
  box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);

  padding: 32px;
}
```

## App Implementation

### SwiftUI
```swift
struct GlassCard: View {
    var body: some View {
        ZStack {
            // Vibrant background required for glass to show
            LinearGradient(
                colors: [.purple, .blue, .cyan],
                startPoint: .topLeading,
                endPoint: .bottomTrailing
            )
            .ignoresSafeArea()

            // Glass panel
            VStack(alignment: .leading, spacing: 16) {
                Text("Glass Panel")
                    .font(.system(size: 22, weight: .semibold))
                    .foregroundColor(.white)
                Text("Content floating on frosted glass.")
                    .font(.system(size: 15))
                    .foregroundColor(.white.opacity(0.8))

                Button(action: {}) {
                    Text("Continue")
                        .font(.system(size: 15, weight: .semibold))
                        .foregroundColor(.white)
                        .padding(.horizontal, 24)
                        .padding(.vertical, 12)
                        .background(.ultraThinMaterial)
                        .cornerRadius(8)
                }
            }
            .padding(24)
            .background(.ultraThinMaterial)  // Built-in frosted glass
            .cornerRadius(16)
            .overlay(
                RoundedRectangle(cornerRadius: 16)
                    .stroke(.white.opacity(0.3), lineWidth: 1) // Glass edge highlight
            )
            .shadow(color: .black.opacity(0.1), radius: 20, x: 0, y: 10)
            .padding(24)
        }
    }
}
```
- Use `.ultraThinMaterial`, `.thinMaterial`, `.regularMaterial`, `.thickMaterial` — Apple built glassmorphism natively.
- Add `.overlay(RoundedRectangle().stroke(.white.opacity(0.3)))` for the light edge catch.
- Glass only works if there's a vibrant background visible behind it.

### Flutter
```dart
class GlassCard extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        // Vibrant background
        Container(
          decoration: const BoxDecoration(
            gradient: LinearGradient(
              colors: [Colors.purple, Colors.blue, Colors.cyan],
              begin: Alignment.topLeft,
              end: Alignment.bottomRight,
            ),
          ),
        ),
        // Glass panel
        Center(
          child: ClipRRect(
            borderRadius: BorderRadius.circular(16),
            child: BackdropFilter(
              filter: ImageFilter.blur(sigmaX: 16, sigmaY: 16),
              child: Container(
                padding: const EdgeInsets.all(24),
                decoration: BoxDecoration(
                  color: Colors.white.withOpacity(0.15),
                  borderRadius: BorderRadius.circular(16),
                  border: Border.all(
                    color: Colors.white.withOpacity(0.3),
                    width: 1,
                  ),
                  boxShadow: [
                    BoxShadow(
                      color: Colors.black.withOpacity(0.1),
                      blurRadius: 20,
                      offset: const Offset(0, 10),
                    ),
                  ],
                ),
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text('Glass Panel',
                      style: TextStyle(fontSize: 22, fontWeight: FontWeight.w600,
                        color: Colors.white)),
                    const SizedBox(height: 16),
                    Text('Content floating on frosted glass.',
                      style: TextStyle(fontSize: 15,
                        color: Colors.white.withOpacity(0.8))),
                  ],
                ),
              ),
            ),
          ),
        ),
      ],
    );
  }
}
```
- **Critical**: `BackdropFilter` MUST be wrapped in `ClipRRect` — without clipping, the blur applies to the entire screen.
- Use `ImageFilter.blur(sigmaX: 10...20, sigmaY: 10...20)` for the frosted effect.
- Set the container color to `Colors.white.withOpacity(0.1...0.2)` — too opaque kills the glass look.

### React Native
```jsx
import { BlurView } from '@react-native-community/blur';

const GlassCard = () => (
  <View style={{ flex: 1 }}>
    {/* Vibrant background */}
    <LinearGradient
      colors={['#9B59B6', '#3498DB', '#1ABC9C']}
      style={StyleSheet.absoluteFill}
    />

    {/* Glass panel */}
    <View style={{
      margin: 24,
      borderRadius: 16,
      overflow: 'hidden', // Required for blur clipping
    }}>
      <BlurView
        blurType="light"
        blurAmount={16}
        style={{ padding: 24 }}
      >
        <View style={{
          // Glass border overlay
          borderRadius: 16,
          borderWidth: 1,
          borderColor: 'rgba(255,255,255,0.3)',
        }}>
          <Text style={{
            fontSize: 22, fontWeight: '600', color: '#FFF',
            marginBottom: 16,
          }}>
            Glass Panel
          </Text>
          <Text style={{
            fontSize: 15, color: 'rgba(255,255,255,0.8)',
          }}>
            Content floating on frosted glass.
          </Text>
        </View>
      </BlurView>
    </View>
  </View>
);
```
- Install `@react-native-community/blur` — React Native has NO native blur support.
- Wrap the `BlurView` parent in a `View` with `overflow: 'hidden'` and `borderRadius` to clip the blur.
- Use `blurType: 'light'` for light glass, `'dark'` for dark glass, `'chromeMaterial'` for iOS Chrome effect.
- **Android limitation**: `BlurView` performance varies on Android. Test thoroughly.

### Jetpack Compose
```kotlin
@Composable
fun GlassCard() {
    Box(modifier = Modifier.fillMaxSize()) {
        // Vibrant background
        Box(modifier = Modifier
            .fillMaxSize()
            .background(Brush.linearGradient(
                colors = listOf(Color(0xFF9B59B6), Color(0xFF3498DB), Color(0xFF1ABC9C)),
                start = Offset.Zero,
                end = Offset.Infinite,
            ))
        )

        // Glass panel — Compose lacks native backdrop-filter,
        // so use a semi-transparent surface with blur via Modifier.blur()
        Card(
            modifier = Modifier
                .padding(24.dp)
                .align(Alignment.Center),
            shape = RoundedCornerShape(16.dp),
            colors = CardDefaults.cardColors(
                containerColor = Color.White.copy(alpha = 0.15f),
            ),
            border = BorderStroke(1.dp, Color.White.copy(alpha = 0.3f)),
            elevation = CardDefaults.cardElevation(defaultElevation = 0.dp),
        ) {
            Column(modifier = Modifier.padding(24.dp)) {
                Text("Glass Panel",
                    fontSize = 22.sp,
                    fontWeight = FontWeight.SemiBold,
                    color = Color.White)
                Spacer(Modifier.height(16.dp))
                Text("Content floating on frosted glass.",
                    fontSize = 15.sp,
                    color = Color.White.copy(alpha = 0.8f))
            }
        }
    }
}
```
- **Compose limitation**: True `backdrop-filter` blur doesn't exist natively. Use `Modifier.blur()` (API 31+) on the background, or use `RenderEffect.createBlurEffect()` for lower APIs.
- Use the `haze` library (`dev.chrisbanes.haze`) for proper glassmorphism in Compose — it provides `Modifier.haze()` and `Modifier.hazeChild()`.
- Without native blur, fallback to `Color.White.copy(alpha = 0.15f)` with a strong `border` to simulate the glass edge.

## Do's and Don'ts
- **DO**: Ensure there is enough contrast between text and the blurred background. Accessibility is often a challenge with this style.
- **DON'T**: Use Glassmorphism on a solid white or solid black background—the effect will be completely invisible.

## Limitations
- This is a styling reference and does not replace environment-specific validation, accessibility testing, or expert review.
- Ensure appropriate contrast ratios and responsive behaviors are verified separately.


---
name: global-chat-agent-discovery
description: "Discover and search 18K+ MCP servers and AI agents across 6+ registries using Global Chat's cross-protocol directory and MCP server."
category: development
risk: safe
source: community
source_repo: pumanitro/global-chat
source_type: community
date_added: "2026-04-06"
author: pumanitro
tags: [mcp, ai-agents, agent-discovery, agents-txt, a2a, developer-tools]
tools: [claude, cursor, gemini, codex]
---

# Global Chat Agent Discovery

## Overview

Global Chat is a cross-protocol AI agent discovery platform that aggregates MCP servers and AI agents from 6+ registries into a single searchable directory. This skill helps you find the right MCP server, A2A agent, or agents.txt endpoint for any task by searching across 18,000+ indexed entries. It also provides an MCP server (`@global-chat/mcp-server`) for programmatic access to the directory from any MCP-compatible client.

## When to Use This Skill

- Use when you need to find an MCP server for a specific capability (e.g., database access, file conversion, API integration)
- Use when evaluating which agent registries carry tools for your use case
- Use when you want to search across multiple protocols (MCP, A2A, agents.txt) simultaneously
- Use when setting up agent-to-agent communication and need to discover available endpoints

## How It Works

### Option 1: Use the MCP Server (Recommended for Agents)

Install the Global Chat MCP server to search the directory programmatically from Claude Code, Cursor, or any MCP client.

```bash
npm install -g @global-chat/mcp-server
```

Add to your MCP client configuration:

```json
{
  "mcpServers": {
    "global-chat": {
      "command": "npx",
      "args": ["-y", "@global-chat/mcp-server"]
    }
  }
}
```

Then ask your agent to search for tools:

```
Search Global Chat for MCP servers that handle PostgreSQL database queries.
```

### Option 2: Use the Web Directory

Browse the full directory at [https://global-chat.io](https://global-chat.io):

1. Visit the search page and enter your query
2. Filter by protocol (MCP, A2A, agents.txt)
3. Filter by registry source
4. View server details, capabilities, and installation instructions

### Option 3: Validate Your agents.txt

If you maintain an `agents.txt` file, use the free validator:

1. Go to [https://global-chat.io/validate](https://global-chat.io/validate)
2. Enter your domain or paste your agents.txt content
3. Get instant feedback on format compliance and discoverability

## Examples

### Example 1: Find MCP Servers for a Task

```
You: "Find MCP servers that can convert PDF files to text"
Agent (via Global Chat MCP): Searching across 6 registries...
  - @anthropic/pdf-tools (mcpservers.org) — PDF parsing and text extraction
  - pdf-converter-mcp (mcp.so) — Convert PDF to text, markdown, or HTML
  - ...
```

### Example 2: Discover A2A Agents

```
You: "What A2A agents are available for code review?"
Agent (via Global Chat MCP): Found 12 A2A agents for code review across 3 registries...
```

### Example 3: Check Agent Protocol Coverage

```
You: "How many registries list tools for Kubernetes management?"
Agent (via Global Chat MCP): 4 registries carry Kubernetes-related agents (23 total entries)...
```

## Best Practices

- Use the MCP server for automated workflows and agent-to-agent discovery
- Use the web directory for manual exploration and comparison
- Validate your agents.txt before publishing to ensure maximum discoverability
- Check multiple registries — coverage varies significantly by domain

## Common Pitfalls

- **Problem:** Search returns too many results
  **Solution:** Add protocol or registry filters to narrow the scope

- **Problem:** MCP server not connecting
  **Solution:** Ensure `npx` is available and run `npx -y @global-chat/mcp-server` manually first to verify

## Related Skills

- `@mcp-client` - For general MCP client setup and configuration
- `@agent-orchestration-multi-agent-optimize` - For orchestrating multiple discovered agents
- `@agent-memory-mcp` - For persisting discovered agent information across sessions

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: gmail-automation
description: "Lightweight Gmail integration with standalone OAuth authentication. No MCP server required."
license: Apache-2.0
risk: critical
source: community
metadata:
  author: sanjay3290
  version: "1.0"
---

# Gmail

Lightweight Gmail integration with standalone OAuth authentication. No MCP server required.

> **⚠ Requires Google Workspace account.** Personal Gmail accounts are not supported.

## When to Use
- You need to search, read, or send Gmail messages from the command line without an MCP server.
- You are automating inbox workflows for a Google Workspace account.
- You want a lightweight Gmail integration backed by standalone OAuth scripts.

## First-Time Setup

Authenticate with Google (opens browser):
```bash
python scripts/auth.py login
```

Check authentication status:
```bash
python scripts/auth.py status
```

Logout when needed:
```bash
python scripts/auth.py logout
```

## Commands

All operations via `scripts/gmail.py`. Auto-authenticates on first use if not logged in.

### Search Emails

```bash
# Search with Gmail query syntax
python scripts/gmail.py search "from:someone@example.com is:unread"

# Search recent emails (no query returns all)
python scripts/gmail.py search --limit 20

# Filter by label
python scripts/gmail.py search --label INBOX --limit 10

# Include spam and trash
python scripts/gmail.py search "subject:important" --include-spam-trash
```

### Read Email Content

```bash
# Get full message content
python scripts/gmail.py get MESSAGE_ID

# Get just metadata (headers)
python scripts/gmail.py get MESSAGE_ID --format metadata

# Get minimal response (IDs only)
python scripts/gmail.py get MESSAGE_ID --format minimal
```

### Send Emails

```bash
# Send a simple email
python scripts/gmail.py send --to "user@example.com" --subject "Hello" --body "Message body"

# Send with CC and BCC
python scripts/gmail.py send --to "user@example.com" --cc "cc@example.com" --bcc "bcc@example.com" \
  --subject "Team Update" --body "Update message"

# Send from an alias (must be configured in Gmail settings)
python scripts/gmail.py send --to "user@example.com" --subject "Hello" --body "Message" \
  --from "Mile9 Accounts <accounts@mile9.io>"

# Send HTML email
python scripts/gmail.py send --to "user@example.com" --subject "HTML Email" \
  --body "<h1>Hello</h1><p>HTML content</p>" --html
```

### Draft Management

```bash
# Create a draft
python scripts/gmail.py create-draft --to "user@example.com" --subject "Draft Subject" \
  --body "Draft content"

# Send an existing draft
python scripts/gmail.py send-draft DRAFT_ID
```

### Modify Messages (Labels)

```bash
# Mark as read (remove UNREAD label)
python scripts/gmail.py modify MESSAGE_ID --remove-label UNREAD

# Mark as unread
python scripts/gmail.py modify MESSAGE_ID --add-label UNREAD

# Archive (remove from INBOX)
python scripts/gmail.py modify MESSAGE_ID --remove-label INBOX

# Star a message
python scripts/gmail.py modify MESSAGE_ID --add-label STARRED

# Unstar a message
python scripts/gmail.py modify MESSAGE_ID --remove-label STARRED

# Mark as important
python scripts/gmail.py modify MESSAGE_ID --add-label IMPORTANT

# Multiple label changes at once
python scripts/gmail.py modify MESSAGE_ID --remove-label UNREAD --add-label STARRED
```

### List Labels

```bash
# List all Gmail labels (system and user-created)
python scripts/gmail.py list-labels
```

## Gmail Query Syntax

Gmail supports powerful search operators:

| Query | Description |
|-------|-------------|
| `from:user@example.com` | Emails from a specific sender |
| `to:user@example.com` | Emails to a specific recipient |
| `subject:meeting` | Emails with "meeting" in subject |
| `is:unread` | Unread emails |
| `is:starred` | Starred emails |
| `is:important` | Important emails |
| `has:attachment` | Emails with attachments |
| `after:2024/01/01` | Emails after a date |
| `before:2024/12/31` | Emails before a date |
| `newer_than:7d` | Emails from last 7 days |
| `older_than:1m` | Emails older than 1 month |
| `label:work` | Emails with a specific label |
| `in:inbox` | Emails in inbox |
| `in:sent` | Sent emails |
| `in:trash` | Trashed emails |

Combine with AND (space), OR, or - (NOT):
```bash
python scripts/gmail.py search "from:boss@company.com is:unread newer_than:1d"
python scripts/gmail.py search "subject:urgent OR subject:important"
python scripts/gmail.py search "from:newsletter@example.com -is:starred"
```

## Common Label IDs

| Label | ID |
|-------|-----|
| Inbox | `INBOX` |
| Sent | `SENT` |
| Drafts | `DRAFT` |
| Spam | `SPAM` |
| Trash | `TRASH` |
| Starred | `STARRED` |
| Important | `IMPORTANT` |
| Unread | `UNREAD` |

## Token Management

Tokens stored securely using the system keyring:
- **macOS**: Keychain
- **Windows**: Windows Credential Locker
- **Linux**: Secret Service API (GNOME Keyring, KDE Wallet, etc.)

Service name: `gmail-skill-oauth`

Tokens automatically refresh when expired using Google's cloud function.

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.