make-github-actions-workflow

$npx mdskill add dotnet/efcore/make-github-actions-workflow

Create and configure GitHub Actions workflows that follow this repository's conventions and patterns. Workflows automate tasks like CI validation, PR management, issue labeling, and notifications.

SKILL.md

.github/skills/make-github-actions-workflowView on GitHub ↗
---
name: make-github-actions-workflow
description: 'Create GitHub Actions workflows for CI, automation, or PR management. Use when asked to create, scaffold, or add a GitHub Actions workflow (.yml file under .github/workflows/).'
---

# Create GitHub Actions Workflow

Create and configure GitHub Actions workflows that follow this repository's conventions and patterns. Workflows automate tasks like CI validation, PR management, issue labeling, and notifications.

## Repository Conventions

This repository uses specific patterns across all workflows. Follow these conventions when creating new workflows:

### File Location and Naming

- All workflows live in `.github/workflows/`
- Use kebab-case names: `label-and-milestone-issues.yml`, `validate-pr-target-branch.yml`
- Start with a descriptive comment block explaining the workflow's purpose

### Runner

- Use `ubuntu-latest` for general-purpose jobs
- Use `ubuntu-24.04` when a specific OS version is needed (e.g., copilot setup steps)

### Permissions

- **Always** declare explicit permissions — never rely on defaults
- Use **minimal permissions**: only request what the workflow needs
- Common patterns:
  - Read-only: `permissions: {}`
  - PR comments: `pull-requests: write`
  - Issue management: `issues: write`
  - Code read: `contents: read`
- For workflows that need write access to PRs from external contributors, use `pull_request_target` instead of `pull_request`
  - **Security warning:** `pull_request_target` workflows run in the base repository context with its permissions. Do **not** check out or execute code from the PR branch in these workflows. Instead, use the event payload and/or GitHub API (`actions/github-script`, `github.rest.*`, etc.) to inspect and act on the PR safely.

### Scripting

- Use `actions/github-script@v8` for complex logic instead of shell scripts
- Write JavaScript with `async/await` — the `github` object (Octokit) and `context` are available
- Use `github.rest.*` for REST API calls and `github.graphql()` for GraphQL queries
- Access PR/issue data via `context.payload.pull_request`, `context.repo.owner`, `context.repo.repo`
- Log with `console.log()` for debugging; use `core.setFailed()` for errors

### Error Handling

- Wrap API calls in try/catch blocks
- Collect errors and report at the end rather than failing on the first error
- Log skipped operations with a reason

## Workflow

### Step 1: Understand the Requirements

Before writing the workflow, clarify:
- [ ] What event(s) should trigger it? (push, pull_request, check_suite, schedule, etc.)
- [ ] What permissions are needed?
- [ ] What conditions should gate execution? (author, branch, labels, etc.)
- [ ] What API calls are needed?
- [ ] Are there rate limiting or idempotency concerns?

### Step 2: Choose the Trigger Event

| Use case | Event | Notes |
|----------|-------|-------|
| PR opened/updated | `pull_request` | Read-only access to PR |
| PR with write access | `pull_request_target` | Can comment, label, close |
| PR merged | `pull_request_target: [closed]` | Check `github.event.pull_request.merged == true` |
| CI checks complete | `check_suite: [completed]` | Filter `app.slug != 'github-actions'` to skip self |
| Code pushed | `push` | Filter by branches/paths |
| Manual trigger | `workflow_dispatch` | Add `inputs:` for parameters |
| Scheduled | `schedule` | Use cron syntax |

### Step 3: Write the Workflow

Create the YAML file following this template:

```yaml
# Description of what this workflow does and why.

name: Descriptive Workflow Name

on:
  <trigger_event>:
    types: [<event_types>]

permissions:
  <resource>: <read|write>

jobs:
  <job-name>:
    if: <guard_condition>  # Optional: skip when not needed
    runs-on: ubuntu-latest
    steps:
      - name: Descriptive step name
        uses: actions/github-script@v8
        with:
          script: |
            // Your logic here
```

### Step 4: Implement Guard Conditions

Add conditions to avoid unnecessary runs:
- Job-level `if:` for event payload checks (e.g., `github.event.check_suite.app.slug != 'github-actions'`)
- Early `return` in scripts for PR author, draft status, etc.
- Idempotency checks (e.g., hidden HTML comments as tags to prevent duplicate actions)

### Step 5: Validate

After creating the workflow:
- [ ] Permissions are minimal and explicitly declared
- [ ] Uses `actions/github-script@v8` for complex logic
- [ ] Guard conditions prevent unnecessary runs
- [ ] API calls handle pagination where needed (use `per_page: 100`)
- [ ] Error handling doesn't silently swallow failures
- [ ] No secrets or tokens are hardcoded
- [ ] Workflow doesn't create infinite loops (e.g., a workflow that triggers itself)

## Existing Workflows in This Repository

Study these workflows as reference:

| Workflow | Trigger | Purpose |
|----------|---------|---------|
| `validate-pr-target-branch.yml` | `pull_request_target: [opened, edited, reopened]` | Closes external PRs targeting release branches, adds community labels |
| `label-and-milestone-issues.yml` | `pull_request_target: [closed]` | Labels and milestones issues when their fixing PR is merged |
| `copilot-setup-steps.yml` | `workflow_dispatch`, `push`, `pull_request` | Sets up the development environment for Copilot |
| `inter-branch-merge-flow.yml` | `push` to `release/**` | Triggers inter-branch merge via arcade |

## Common Patterns

### Commenting on a PR

```javascript
await github.rest.issues.createComment({
  owner: context.repo.owner,
  repo: context.repo.repo,
  issue_number: prNumber,
  body: 'Comment text'
});
```

### Checking User Permissions

```javascript
const { data: permissions } = await github.rest.repos.getCollaboratorPermissionLevel({
  owner: context.repo.owner,
  repo: context.repo.repo,
  username: context.actor
});
const hasWriteAccess = ['admin', 'write'].includes(permissions.permission);
```

### Preventing Duplicate Comments (SHA Tag Pattern)

```javascript
const shaTag = `<!-- tag: ${headSha} -->`;
const { data: comments } = await github.rest.issues.listComments({
  owner: context.repo.owner,
  repo: context.repo.repo,
  issue_number: prNumber,
  per_page: 100
});
if (comments.some(c => c.body?.includes(shaTag))) {
  console.log('Already processed');
  return;
}
```

### Reading Repository Files at a Specific Commit

```javascript
const { data: fileData } = await github.rest.repos.getContent({
  owner, repo,
  path: 'eng/Versions.props',
  ref: commitSha
});
const content = Buffer.from(fileData.content, 'base64').toString('utf-8');
```

## References

- [GitHub Actions documentation](https://docs.github.com/en/actions)
- [Workflow syntax](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions)
- [Events that trigger workflows](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows)
- [actions/github-script](https://github.com/actions/github-script)

More from dotnet/efcore

SkillDescription
change-trackingImplementation details for EF Core change tracking. Use when changing InternalEntityEntry, ChangeDetector, SnapshotFactoryFactory, or related entity state, snapshot, or property accessor code.
cosmos-providerImplementation details for the EF Core Azure Cosmos DB provider. Use when changing Cosmos-specific code.
make-custom-agentCreate custom GitHub Copilot agents. Use when asked to create, scaffold, or configure a custom agent, declarative agent, or @-invokable chat participant for GitHub Copilot.
make-instructionsCreate VS Code file-based instructions (.instructions.md files). Use when asked to create, scaffold, or add file-based instructions for Copilot. Generates .instructions.md with YAML frontmatter and background knowledge content.
make-skillCreate new Agent Skills for GitHub Copilot. Use when asked to create, scaffold, or add a skill. Generates SKILL.md with frontmatter, directory structure, and optional resources.
migrationsImplementation details for EF Core migrations. Use when changing MigrationsSqlGenerator, model diffing, migration operations, HistoryRepository, the Migrator or related classes.
model-buildingImplementation details for EF Core model building. Use when changing ConventionSet, ModelBuilder, IConvention implementations, ModelRuntimeInitializer, RuntimeModel, or related classes.
query-pipelineImplementation details for EF Core LINQ query translation, SQL generation, and bulk operations (ExecuteUpdate/ExecuteDelete). Use when changing expression visitors, SqlExpressions, QuerySqlGenerator, ShaperProcessingExpressionVisitor, UpdateExpression, DeleteExpression, or related classes.
run-apichiefRun ApiChief in the EF Core repo to emit baselines, summaries, deltas, review files, or breaking-change checks. Use when refreshing `*.baseline.json`, preparing API review artifacts, or validating API changes.
scaffoldingImplementation details for EF Core scaffolding (reverse engineering). Use when changing ef dbcontext scaffold pipeline implementation, database schema reading, CSharpModelGenerator, or related classes.