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
82 changes: 82 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Release

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

permissions:
contents: read

jobs:
test:
name: test
runs-on: ubuntu-latest
steps:
- name: Check out source
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20

- name: Run tests
run: npm test

release:
name: release
if: github.event_name == 'push'
needs: test
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Check out the pushed commit
uses: actions/checkout@v4
with:
ref: ${{ github.sha }}
fetch-depth: 0

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20

- name: Derive release tag
id: version
run: |
version="$(node -p 'require("./package.json").version')"
echo "tag=v${version}" >> "$GITHUB_OUTPUT"

- name: Create annotated tag when absent
env:
TAG: ${{ steps.version.outputs.tag }}
SHA: ${{ github.sha }}
run: |
if git ls-remote --exit-code --tags origin "refs/tags/${TAG}" >/dev/null 2>&1; then
echo "Tag ${TAG} already exists; leaving it unchanged."
exit 0
fi

git -c user.name="github-actions[bot]" \
-c user.email="41898282+github-actions[bot]@users.noreply.github.com" \
tag --annotate "${TAG}" "${SHA}" --message "Release ${TAG}"
git push origin "refs/tags/${TAG}"
echo "Created annotated tag ${TAG} at ${SHA}."

- name: Create GitHub Release when absent
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.version.outputs.tag }}
run: |
if gh release view "${TAG}" --repo "${GITHUB_REPOSITORY}" >/dev/null 2>&1; then
echo "GitHub Release ${TAG} already exists; skipping creation."
exit 0
fi

gh release create "${TAG}" \
--repo "${GITHUB_REPOSITORY}" \
--title "${TAG}" \
--generate-notes
63 changes: 53 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,64 @@
# GitHub Repository Bootstrap
<h1 align="center">GitHub Repository Bootstrap</h1>

A reusable Pi package that plans and applies safe, repeatable GitHub repository bootstrap changes.
<p align="center">A small Pi skill for planning and applying repeatable GitHub repository setup without bypassing repository governance.</p>

## Use as a Pi package
<p align="center">
<a href="https://github.com/egdev6/github-repository-bootstrap/releases"><img src="https://img.shields.io/github/v/release/egdev6/github-repository-bootstrap?display_name=tag" alt="Release"></a>
<a href="https://github.com/egdev6/github-repository-bootstrap/actions/workflows/release.yml?query=branch%3Amain"><img src="https://github.com/egdev6/github-repository-bootstrap/actions/workflows/release.yml/badge.svg?branch=main" alt="CI"></a>
<a href="https://github.com/egdev6/github-repository-bootstrap/issues"><img src="https://img.shields.io/github/issues/egdev6/github-repository-bootstrap" alt="Issues"></a>
<a href="LICENSE"><img src="https://img.shields.io/github/license/egdev6/github-repository-bootstrap" alt="License"></a>
</p>

Install a reviewed immutable ref at project scope:
## Status

```bash
pi install -l git:github.com/egdev6/github-repository-bootstrap@<tag-or-commit>
```
This public repository is distributed directly as a Pi package. `package.json` remains `private: true` only to prevent npm publication; install the skill from a reviewed release tag.

## Quick path

1. Install the existing immutable release tag in the target project:

```bash
pi install -l git:github.com/egdev6/github-repository-bootstrap@v1.0.0
```

2. Ask Pi to bootstrap repository governance, such as labels, milestones, issue templates, or a Projects v2 board.
3. Review the generated manifest and plan, then explicitly authorize the exact plan before any mutation.

Use a version tag such as `v1.0.0`, never a moving branch reference, for future installs.

## Capabilities

The package exposes `github-repository-bootstrap` through the conventional `skills/` directory and its `pi.skills` manifest entry.
| Area | What the skill does |
| --- | --- |
| Intake | Infers available repository facts and asks only for unresolved governance choices. |
| Configuration | Validates a reviewed manifest against its configuration schema. |
| Planning | Discovers current state and reports the exact creates, updates, skips, and failures before changes run. |
| Managed resources | Supports labels, milestones, repository files, legacy templates, and optional Projects v2 configuration. |
| Application | Applies only the reviewed plan after explicit authorization tied to its SHA-256 value. |

## Verify
## Safety model

- Discovery happens before every managed-resource change; configured resources are preserved unless they are explicitly managed.
- The workflow never deletes resources. Repository-file sources and destinations are constrained to safe paths under the target repository.
- `plan` is required before `apply`; authorization is bound to the exact reviewed plan and cannot be reused after relevant state changes.
- Failed operations remain visible in the JSON report instead of being represented as success.

## Release policy

The GitHub Actions workflow runs `npm test` for pull requests to `main` and pushes to `main`. After successful `main` checks, it derives `v<package.json version>`. When that version has no tag yet—normally after a package version change—it creates an annotated tag at the pushed commit and a GitHub Release with generated notes. Existing tags and releases are reported and left unchanged.

GitHub Releases are the only release artifact produced here. npm publication is out of scope, and this package stays private.

## Verification

Run the focused test suite locally:

```bash
npm test
```

The skill instructions and bootstrap implementation live in `skills/github-repository-bootstrap/`.
The same command is the required `test` job in GitHub Actions.

## License

[MIT](LICENSE)
Loading