Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/ModuleCI.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
name: CI
on:
push:
branches: [ $default-branch ]
pull_request:
workflow_dispatch:
workflow_call:
permissions:
Expand Down
51 changes: 22 additions & 29 deletions .github/workflows/PublishModule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ on:
description: "The version to publish. Leave empty to use the version in the module manifest."
required: false
type: string
isPrerelease:
description: "Is this a prerelease version?"
force:
type: boolean
description: "If true, bypass the PSGallery version existence check. Use when re-triggering a failed publish job (pattern: force=true, create_release=false, publish=true)."
required: false
default: false
type: boolean
dry_run:
type: boolean
description: "If true, skip actual publishing and just validate the workflow logic."
Expand Down Expand Up @@ -62,42 +62,38 @@ jobs:
run: |
Import-Module BuildHelpers
Set-BuildEnvironment -Force
[version]$githubVersion = Get-MetaData -Path $env:BHPSModuleManifest -PropertyName 'ModuleVersion' -ErrorAction 'Stop'
Write-Host "Current Version: $githubVersion"

[version]$manifestVersion = Get-MetaData -Path $env:BHPSModuleManifest -PropertyName 'ModuleVersion' -ErrorAction 'Stop'
$PSData = Get-MetaData -Path $env:BHPSModuleManifest -PropertyName PrivateData.PSData -ErrorAction 'Stop'
$prereleaseSuffix = $PSData.Prerelease

Write-Host "Manifest Version: $manifestVersion"
Write-Host "Manifest Prerelease: $prereleaseSuffix"

# Override version if specified as input
if (-not [String]::IsNullOrEmpty('${{ inputs.version }}')) {
# Split version and prerelease suffix if present
if('${{ inputs.version }}' -match '^(?<version>\d+\.\d+\.\d+)(-(?<prerelease>.+))?$') {
$githubVersion = [version]$matches['version']
if ($matches['prerelease']) {
$prereleaseSuffix = $matches['prerelease']
}
if ('${{ inputs.version }}' -match '^(?<version>\d+\.\d+\.\d+)(-(?<prerelease>.+))?$') {
$manifestVersion = [version]$matches['version']
$prereleaseSuffix = $matches['prerelease'] # null if no suffix = stable release
Write-Host "Version override: $manifestVersion, Prerelease override: $prereleaseSuffix"
} else {
Write-Warning "Invalid version format: '${{ inputs.version }}'. Expected format: '1.2.3' or '1.2.3-beta'"
}
Write-Host "Module version was specified in workflow: $githubVersion"
Update-MetaData -Path $env:BHPSModuleManifest -PropertyName ModuleVersion -Value $githubVersion -ErrorAction 'Stop'
Update-MetaData -Path $env:BHPSModuleManifest -PropertyName ModuleVersion -Value $manifestVersion -ErrorAction 'Stop'
}

$moduleSplat = @{
Name = $env:BHProjectName
}
$moduleSplat = @{ Name = $env:BHProjectName }

# Handle pre-release versions
$isPrerelease = '${{ inputs.isPrerelease }}' -eq 'true'
Write-Host "Prerelease: $isPrerelease"
if ($isPrerelease) {
$PSData = Get-MetaData -Path $env:BHPSModuleManifest -PropertyName PrivateData.PSData -ErrorAction 'Stop'
if (-not [String]::IsNullOrEmpty($prereleaseSuffix)) {
$moduleSplat['AllowPrerelease'] = $true
$moduleSplat['RequiredVersion'] = "$githubVersion-$($PSData.Prerelease)"
$moduleSplat['RequiredVersion'] = "$manifestVersion-$prereleaseSuffix"
} else {
$moduleSplat['AllowPrerelease'] = $false
$moduleSplat['RequiredVersion'] = $githubVersion
$moduleSplat['RequiredVersion'] = "$manifestVersion"
}

Write-Host "Version to Publish: $($moduleSplat.RequiredVersion)"

# Check if exact version exists in PSGallery
try {
$existingModule = Find-Module @moduleSplat -ErrorAction Stop
$bumped = $false
Expand All @@ -112,9 +108,6 @@ jobs:
}
}

# Strip prerelease suffix for changelog lookup
$versionForChangelog = "$($moduleSplat.RequiredVersion)" -replace '-.*$', ''

Add-Content -LiteralPath $env:GITHUB_OUTPUT -Value "BUMPED=$bumped" -Confirm:$false -Encoding UTF8
Add-Content -LiteralPath $env:GITHUB_OUTPUT -Value "MODULE_NAME=$env:BHProjectName" -Confirm:$false -Encoding UTF8
Add-Content -LiteralPath $env:GITHUB_OUTPUT -Value "NEW_VERSION=$($moduleSplat.RequiredVersion)" -Confirm:$false -Encoding UTF8
Expand All @@ -124,7 +117,7 @@ jobs:
runs-on: ubuntu-latest
needs:
- check_version
if: needs.check_version.outputs.version_bumped == 'True' && inputs.create_release
if: (needs.check_version.outputs.version_bumped == 'True' || inputs.force) && inputs.create_release
steps:
- uses: actions/checkout@v4
- name: Read and validate changelog (keepachangelog)
Expand All @@ -148,7 +141,7 @@ jobs:
runs-on: windows-latest
needs:
- check_version
if: needs.check_version.outputs.version_bumped == 'True' && inputs.publish
if: (needs.check_version.outputs.version_bumped == 'True' || inputs.force) && inputs.publish
steps:
- uses: actions/checkout@v4
- name: Publish to PSGallery
Expand Down
13 changes: 13 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Agent skills

### Issue tracker

Issues live in GitHub Issues for HeyItsGilbert/.github — uses the `gh` CLI. See `docs/agents/issue-tracker.md`.

### Triage labels

Default label vocabulary: needs-triage, needs-info, ready-for-agent, ready-for-human, wontfix. See `docs/agents/triage-labels.md`.

### Domain docs

Single-context layout: one CONTEXT.md + docs/adr/ at the repo root. See `docs/agents/domain.md`.
10 changes: 10 additions & 0 deletions docs/adr/0001-force-flag-and-inferred-prerelease.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Force flag for re-triggering failed publish jobs; isPrerelease inferred from version string

The publish workflow originally used an `isPrerelease` boolean input and an `inputs.version` escape hatch that could carry a prerelease suffix — but silently ignored that suffix in favour of `PSData.Prerelease` from the manifest. This created a class of contradictions with no clear resolution rule, and left no clean way to re-trigger a failed `publish` job when `create_release` had already succeeded (re-running the full workflow would try to create a duplicate tag).

We replaced `isPrerelease` with inference: a prerelease suffix is present in the reconciled version string or it isn't. We added `inputs.force` to bypass the PSGallery existence check; the intended re-trigger pattern is `force: true, create_release: false, publish: true`. `inputs.version` is now a pure version-override escape hatch — a bare version (e.g. `1.2.3`) means stable release even if the manifest carries a prerelease suffix.

## Considered options

- **Re-run failed jobs only** — GitHub Actions supports re-running only failed jobs, but `create_release` and `publish` are independent jobs; if `create_release` succeeded and `publish` failed, a full re-run recreates the tag and fails. Per-job re-run doesn't help because `publish` depends on `check_version` outputs that aren't re-evaluated.
- **Separate dispatch workflow for publish-only** — cleaner separation of concerns, but adds another workflow file callers must know about; `force` achieves the same goal within the existing interface.
36 changes: 36 additions & 0 deletions docs/agents/domain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Domain Docs

How the engineering skills should consume this repo's domain documentation when exploring the codebase.

## Before exploring, read these

- **`CONTEXT.md`** at the repo root, or
- **`CONTEXT-MAP.md`** at the repo root if it exists — it points at one `CONTEXT.md` per context. Read each one relevant to the topic.
- **`docs/adr/`** — read ADRs that touch the area you're about to work in. In multi-context repos, also check `src/<context>/docs/adr/` for context-scoped decisions.

If any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The producer skill (`/grill-with-docs`) creates them lazily when terms or decisions actually get resolved.

## File structure

Single-context repo (most repos):

```
/
├── CONTEXT.md
├── docs/adr/
│ ├── 0001-event-sourced-orders.md
│ └── 0002-postgres-for-write-model.md
└── src/
```

## Use the glossary's vocabulary

When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids.

If the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/grill-with-docs`).

## Flag ADR conflicts

If your output contradicts an existing ADR, surface it explicitly rather than silently overriding:

> _Contradicts ADR-0007 (event-sourced orders) — but worth reopening because…_
22 changes: 22 additions & 0 deletions docs/agents/issue-tracker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Issue tracker: GitHub

Issues and PRDs for this repo live as GitHub issues. Use the `gh` CLI for all operations.

## Conventions

- **Create an issue**: `gh issue create --title "..." --body "..."`. Use a heredoc for multi-line bodies.
- **Read an issue**: `gh issue view <number> --comments`, filtering comments by `jq` and also fetching labels.
- **List issues**: `gh issue list --state open --json number,title,body,labels,comments --jq '[.[] | {number, title, body, labels: [.labels[].name], comments: [.comments[].body]}]'` with appropriate `--label` and `--state` filters.
- **Comment on an issue**: `gh issue comment <number> --body "..."`
- **Apply / remove labels**: `gh issue edit <number> --add-label "..."` / `--remove-label "..."`
- **Close**: `gh issue close <number> --comment "..."`

Infer the repo from `git remote -v` — `gh` does this automatically when run inside a clone.

## When a skill says "publish to the issue tracker"

Create a GitHub issue.

## When a skill says "fetch the relevant ticket"

Run `gh issue view <number> --comments`.
15 changes: 15 additions & 0 deletions docs/agents/triage-labels.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Triage Labels

The skills speak in terms of five canonical triage roles. This file maps those roles to the actual label strings used in this repo's issue tracker.

| Label in mattpocock/skills | Label in our tracker | Meaning |
| -------------------------- | -------------------- | ---------------------------------------- |
| `needs-triage` | `needs-triage` | Maintainer needs to evaluate this issue |
| `needs-info` | `needs-info` | Waiting on reporter for more information |
| `ready-for-agent` | `ready-for-agent` | Fully specified, ready for an AFK agent |
| `ready-for-human` | `ready-for-human` | Requires human implementation |
| `wontfix` | `wontfix` | Will not be actioned |

When a skill mentions a role (e.g. "apply the AFK-ready triage label"), use the corresponding label string from this table.

Edit the right-hand column to match whatever vocabulary you actually use.