From 7cf1a2db0fc287ffcc4592ab34edf1db9a194470 Mon Sep 17 00:00:00 2001 From: egdev6 Date: Sun, 6 Sep 2026 19:52:32 +0200 Subject: [PATCH] ci: automate GitHub Releases --- .github/workflows/release.yml | 82 +++++++++++++++++++++++++++++++++++ README.md | 63 ++++++++++++++++++++++----- 2 files changed, 135 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..aebc8b6 --- /dev/null +++ b/.github/workflows/release.yml @@ -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 diff --git a/README.md b/README.md index 0e1803d..0a890dd 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,64 @@ -# GitHub Repository Bootstrap +

GitHub Repository Bootstrap

-A reusable Pi package that plans and applies safe, repeatable GitHub repository bootstrap changes. +

A small Pi skill for planning and applying repeatable GitHub repository setup without bypassing repository governance.

-## Use as a Pi package +

+ Release + CI + Issues + License +

-Install a reviewed immutable ref at project scope: +## Status -```bash -pi install -l git:github.com/egdev6/github-repository-bootstrap@ -``` +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`. 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)