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

# Rolling prerelease channel. On every code change to main, build the tip of main and replace the
# single `edge` prerelease (a fixed, moving tag). The version comes for free from MinVer
# (e.g. 0.1.0-alpha.0.N) — the `edge` tag does not start with `v`, so MinVer ignores it. Stable
# releases are handled separately by release-please. Install the edge build with:
# scripts/install.sh --channel edge (or install.ps1 -Channel edge)
on:
push:
branches: [main]
paths:
- 'src/**'
- '**/*.csproj'
- 'Directory.Build.props'
- '.github/workflows/edge.yml'

permissions:
contents: write

# Only the newest edge run matters; cancel older in-flight runs so they don't fight over the release.
concurrency:
group: edge
cancel-in-progress: true

jobs:
build:
strategy:
matrix:
include:
- { rid: win-x64, os: windows-latest, ext: .exe }
- { rid: win-arm64, os: windows-latest, ext: .exe }
- { rid: linux-x64, os: ubuntu-latest, ext: '' }
- { rid: osx-arm64, os: macos-latest, ext: '' }
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0 # MinVer needs full history to compute the prerelease version.

- uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5
with:
dotnet-version: '10.0.x'

- name: Publish
run: >
dotnet publish src/Protostar.Cli/Protostar.Cli.csproj
-c Release -r ${{ matrix.rid }} --self-contained true
-p:PublishSingleFile=true -p:EnableCompressionInSingleFile=true
-o publish

# Same raw-binary asset names as the stable release, so install.{ps1,sh} fetch them identically.
- name: Stage asset
shell: bash
run: mv "publish/protostar${{ matrix.ext }}" "protostar-${{ matrix.rid }}${{ matrix.ext }}"

- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: protostar-${{ matrix.rid }}
path: protostar-${{ matrix.rid }}${{ matrix.ext }}

edge-release:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
path: dist
merge-multiple: true

# Re-point the moving `edge` tag at this commit and replace its prerelease assets. Delete +
# recreate keeps the download URLs stable (releases/download/edge/<asset>) while moving the tag.
- name: Publish edge release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
shell: bash
run: |
gh release delete edge --cleanup-tag --yes || true
gh release create edge dist/* \
--prerelease \
--target "$GITHUB_SHA" \
--title "Edge (latest main)" \
--notes "Rolling prerelease built from the tip of \`main\` (commit ${GITHUB_SHA:0:7}). Run \`protostar --version\` for the exact version. Install with \`--channel edge\`."
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.0.0"
".": "0.0.1"
}
3 changes: 3 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
-->
<PropertyGroup>
<MinVerTagPrefix>v</MinVerTagPrefix>
<!-- Before the first v0.1.0 tag exists, floor untagged (edge) builds at 0.1.0-alpha.0.N instead
of 0.0.0-alpha, so the edge channel matches the upcoming first stable release. -->
<MinVerMinimumMajorMinor>0.1</MinVerMinimumMajorMinor>
</PropertyGroup>

<ItemGroup>
Expand Down
36 changes: 35 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,25 @@ $ protostar --version
> from a tagged commit reports that tag (e.g. `0.1.0`); a local build from an untagged commit reports
> a pre-release like `0.1.0-alpha.0.4`. See [Releasing](#releasing).

### Channels: stable vs edge

`stable` (the default above) installs the latest tagged release. `edge` installs the rolling
prerelease rebuilt from the tip of `main` on every code change — handy for trying unreleased fixes.

**Linux / macOS**

```bash
curl -fsSL https://raw.githubusercontent.com/voidprojectssoftware/protostar/main/scripts/install.sh | sh -s -- --channel edge
```

**Windows (PowerShell)** — fetch then invoke with `-Channel` (the piped one-liner can't take params):

```powershell
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/voidprojectssoftware/protostar/main/scripts/install.ps1))) -Channel edge
```

Edge binaries report a prerelease version like `0.2.0-alpha.0.7`. Re-run the same command to update.

### Already have the binary?

If you downloaded `protostar` directly, it installs itself:
Expand Down Expand Up @@ -102,6 +121,20 @@ stamps it into the binaries, which the workflow attaches to the release.
> Tags are created by release-please on `main`, so they are always reachable through history — this
> is what makes MinVer reliable regardless of squash/rebase merges. Do not tag manually.

### Two channels

protostar ships on two tracks (see [Channels](#channels-stable-vs-edge) for how to install each):

- **stable** — the release-please flow above. Tagged `vX.Y.Z`, published as a normal GitHub Release
(so it is the `releases/latest` the default installer pulls).
- **edge** — a rolling prerelease. The `edge` workflow rebuilds on every code change to `main` and
replaces a single prerelease under the moving `edge` tag, versioned by MinVer (`0.X.Y-alpha.0.N`).
Because the `edge` tag does not start with `v`, MinVer ignores it, so the two channels never
collide.

While we are pre-1.0, stable releases stay in the `0.x` range (`bump-minor-pre-major` keeps a
breaking change from jumping to `1.0.0`); cutting `1.0.0` will be a deliberate choice.

## Repository layout

```text
Expand All @@ -112,7 +145,8 @@ protostar/
│ ├─ install.ps1 # curl-able release installer (Windows)
│ └─ install.sh # curl-able release installer (Linux/macOS)
├─ .github/workflows/
│ └─ release-please.yml # release-please: Release PR -> tag -> build + attach binaries
│ ├─ release-please.yml # stable: Release PR -> tag -> build + attach binaries
│ └─ edge.yml # edge: rebuild tip of main -> replace rolling `edge` prerelease
├─ release-please-config.json # release-please configuration
├─ .release-please-manifest.json # release-please version tracker
├─ Directory.Build.props # MinVer git-tag versioning
Expand Down
1 change: 1 addition & 0 deletions release-please-config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"include-component-in-tag": false,
"bump-minor-pre-major": true,
"packages": {
".": {
"release-type": "simple",
Expand Down
13 changes: 11 additions & 2 deletions scripts/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,17 @@
irm https://raw.githubusercontent.com/voidprojectssoftware/protostar/main/scripts/install.ps1 | iex

Or download and run directly to pass options (e.g. -Dir), which are forwarded to `protostar install`.

.PARAMETER Channel
Release track: `stable` (default, the latest tagged release) or `edge` (the rolling prerelease
built from the tip of main).
#>
[CmdletBinding()]
param([Parameter(ValueFromRemainingArguments = $true)] [string[]]$InstallArgs)
param(
[ValidateSet('stable', 'edge')]
[string]$Channel = 'stable',
[Parameter(ValueFromRemainingArguments = $true)] [string[]]$InstallArgs
)

$ErrorActionPreference = 'Stop'
$repo = 'voidprojectssoftware/protostar'
Expand All @@ -25,7 +33,8 @@ switch ($arch) {
}

$asset = "protostar-$rid.exe"
$url = "https://github.com/$repo/releases/latest/download/$asset"
$base = if ($Channel -eq 'edge') { "https://github.com/$repo/releases/download/edge" } else { "https://github.com/$repo/releases/latest/download" }
$url = "$base/$asset"

$tmp = Join-Path ([System.IO.Path]::GetTempPath()) ("protostar-download-" + [System.IO.Path]::GetRandomFileName())
New-Item -ItemType Directory -Force -Path $tmp | Out-Null
Expand Down
17 changes: 15 additions & 2 deletions scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,21 @@
#
# curl -fsSL https://raw.githubusercontent.com/voidprojectssoftware/protostar/main/scripts/install.sh | sh
#
# Any extra args are forwarded to `protostar install` (e.g. --dir, --no-modify-path) when the
# Pass --channel stable|edge (default stable) as the first argument to pick the release track:
# stable = the latest tagged release; edge = the rolling prerelease built from the tip of main.
# Any other args are forwarded to `protostar install` (e.g. --dir, --no-modify-path) when the
# script is run directly (not via the piped one-liner).
set -e

repo="voidprojectssoftware/protostar"

# Channel selector (first arg). Everything else is forwarded to `protostar install`.
channel="stable"
case "$1" in
--channel) channel="$2"; shift 2 ;;
--channel=*) channel="${1#*=}"; shift ;;
esac

os=$(uname -s)
arch=$(uname -m)

Expand All @@ -26,7 +35,11 @@ case "$arch" in
esac

asset="protostar-${rid_os}-${rid_arch}"
url="https://github.com/${repo}/releases/latest/download/${asset}"
case "$channel" in
stable) url="https://github.com/${repo}/releases/latest/download/${asset}" ;;
edge) url="https://github.com/${repo}/releases/download/edge/${asset}" ;;
*) echo "Unknown channel: $channel (use 'stable' or 'edge')" >&2; exit 1 ;;
esac

tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
Expand Down
2 changes: 1 addition & 1 deletion version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.0.0
0.0.1