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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.sh text eol=lf
107 changes: 77 additions & 30 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
name: Release

# Fires on v*.*.* tags (with prerelease suffixes). Version comes from Directory.Build.props.
# Publishes via NuGet Trusted Publishing (OIDC, no long-lived API key). Setup in docs/RELEASING.md.
on:
push:
tags:
- 'v*.*.*'
- 'v[0-9]+.[0-9]+.[0-9]+*'
workflow_dispatch:
inputs:
dry_run:
description: "Pack and validate only — skip nuget push"
type: boolean
default: true

concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false

jobs:
publish:
release:
runs-on: ubuntu-latest
if: github.event.repository.fork == false
environment: release
permissions:
contents: write # for creating the GitHub Release
id-token: write # required for the Trusted Publishing OIDC exchange
env:
PUBLISH: ${{ github.event_name == 'push' || inputs.dry_run == false }}

steps:
- uses: actions/checkout@v4
Expand All @@ -18,46 +36,75 @@ jobs:
with:
dotnet-version: 10.0.x

- name: Extract version from tag
- name: Read version
id: version
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
run: |
v=$(dotnet msbuild src/ShellUI.Native.CLI/ShellUI.Native.CLI.csproj -getProperty:Version)
echo "Directory.Build.props version: $v"
echo "VERSION=$v" >> "$GITHUB_OUTPUT"

- name: Check tag matches version
if: github.event_name == 'push'
run: |
tag="${GITHUB_REF#refs/tags/v}"
if [ "$tag" != "${{ steps.version.outputs.VERSION }}" ]; then
echo "::error::The CLI builds version ${{ steps.version.outputs.VERSION }} but the tag is v$tag. Update Directory.Build.props."
exit 1
fi

- name: Restore dependencies
run: dotnet restore src/
- name: Extract release notes for this version
run: bash scripts/extract-release-notes.sh "${{ steps.version.outputs.VERSION }}" > "$RUNNER_TEMP/release-body.md"

- name: Restore dependencies (src + tests)
run: |
dotnet restore src/ShellUI.Native.CLI/ShellUI.Native.CLI.csproj
dotnet restore tests/ShellUI.Native.Tests/ShellUI.Native.Tests.csproj

- name: Build
run: dotnet build src/ --no-restore --configuration Release
run: |
dotnet build src/ShellUI.Native.CLI/ShellUI.Native.CLI.csproj --no-restore --configuration Release
dotnet build tests/ShellUI.Native.Tests/ShellUI.Native.Tests.csproj --no-restore --configuration Release

- name: Run tests
run: dotnet test tests/ShellUI.Native.Tests/ShellUI.Native.Tests.csproj --no-restore --no-build --configuration Release

# Core and Templates ship inside the CLI tool package; only the CLI is published.
- name: Pack CLI tool
run: dotnet pack src/ShellUI.Native.CLI/ShellUI.Native.CLI.csproj --no-restore --configuration Release -o ./nupkg
run: dotnet pack src/ShellUI.Native.CLI/ShellUI.Native.CLI.csproj --no-build --configuration Release -p:ContinuousIntegrationBuild=true -o ./nupkg

- name: Publish CLI to NuGet
# nuget.org locks a version forever after first publish, and --skip-duplicate would skip it silently.
- name: Verify version is not already published
if: env.PUBLISH == 'true'
run: |
dotnet nuget push ./nupkg/ShellUI.Native.CLI.*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
v="${{ steps.version.outputs.VERSION }}"
existing=$(curl -sf "https://api.nuget.org/v3-flatcontainer/shellui.native.cli/index.json" | grep -oE '"[^"]*"' | tr -d '"' || true)
if echo "$existing" | grep -Fxiq "$v"; then
echo "::error::ShellUI.Native.CLI $v is already on nuget.org. Bump Directory.Build.props and re-tag."
exit 1
fi

# Right before the push: the temporary API key is valid for one hour.
# `user` is the nuget.org profile name (not the email, not the GitHub org), kept as a secret.
- name: Login to NuGet via Trusted Publishing
if: env.PUBLISH == 'true'
id: nuget-login
uses: NuGet/login@v1
with:
user: ${{ secrets.NUGET_USER }}

- name: Publish CLI to NuGet
if: env.PUBLISH == 'true'
env:
NUGET_API_KEY: ${{ steps.nuget-login.outputs.NUGET_API_KEY }}
run: dotnet nuget push ./nupkg/ShellUI.Native.CLI.*.nupkg --api-key "$NUGET_API_KEY" --source https://api.nuget.org/v3/index.json --skip-duplicate

- name: Create GitHub Release
uses: softprops/action-gh-release@v1
if: github.event_name == 'push'
uses: softprops/action-gh-release@v2
with:
name: ShellUI Native v${{ steps.version.outputs.VERSION }}
body: |
## ShellUI Native v${{ steps.version.outputs.VERSION }}

### Installation
```bash
dotnet tool install -g ShellUI.Native.CLI
```

### Quick Start
```bash
cd YourMAUIProject
shellui-native init --yes
shellui-native add button input card
```

See the [documentation](https://github.com/shellui-dev/shellui-native) for usage.
body_path: ${{ runner.temp }}/release-body.md
draft: false
prerelease: ${{ contains(github.ref, '-') }}
prerelease: ${{ contains(steps.version.outputs.VERSION, '-') }}
files: |
./nupkg/*.nupkg
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4 changes: 2 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
<Project>
<!-- Centralized ShellUI Native Version - Update this single file to version all components -->
<PropertyGroup>
<ShellUINativeVersion>0.0.1</ShellUINativeVersion>
<ShellUINativeVersionSuffix></ShellUINativeVersionSuffix>
<ShellUINativeVersion>0.1.0</ShellUINativeVersion>
<ShellUINativeVersionSuffix>alpha.1</ShellUINativeVersionSuffix>
</PropertyGroup>

<!-- Common properties for all ShellUI Native projects -->
Expand Down
1 change: 1 addition & 0 deletions assets/brand/shelldocs.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions assets/brand/shellicons.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions assets/brand/shellui.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed assets/icon-dark.png
Binary file not shown.
1 change: 1 addition & 0 deletions assets/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/logo-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/logo-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 10 additions & 2 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,15 @@ Not implemented yet — this illustrates the target shape once Template System v
All packages share a single version defined in `Directory.Build.props`:

```xml
<ShellUINativeVersion>0.0.1</ShellUINativeVersion>
<ShellUINativeVersion>0.1.0</ShellUINativeVersion>
<ShellUINativeVersionSuffix>alpha.1</ShellUINativeVersionSuffix>
```

Component metadata reads this version at runtime, ensuring consistency across all installed components.
The build stamps it into the assemblies, and component metadata reads it from there at runtime,
so `shellui-native.json` records the CLI version each component was installed with.

**Releasing:** set the version in `Directory.Build.props`, add a `# ShellUI Native v<version>`
section to [RELEASE_NOTES.md](./RELEASE_NOTES.md), merge to `main`, then push a `v<version>` tag.
`.github/workflows/release.yml` checks the tag, runs the tests, publishes `ShellUI.Native.CLI`
through NuGet Trusted Publishing and creates the GitHub release. Setup and steps are in
[RELEASING.md](./RELEASING.md).
2 changes: 1 addition & 1 deletion docs/BLAZOR_HYBRID.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ shellui init --yes
shellui add button input card

# Install ShellUI Native (for native MAUI controls)
dotnet tool install -g ShellUI.Native.CLI
dotnet tool install -g ShellUI.Native.CLI --prerelease
shellui-native init --yes
shellui-native add button dialog
```
Expand Down
4 changes: 4 additions & 0 deletions docs/COMPONENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1158,6 +1158,10 @@ shellui-native list --available
Dependencies install automatically. Almost every component depends on `shell` (theme tokens and
core helpers); components that draw icons also depend on `icon`.

Parts of a compositional family (`dialog-trigger`, `accordion-item`, `card-header`, …) find their
parent at runtime, so they only build next to it. Adding a part on its own installs the whole
family: `shellui-native add dialog-trigger` installs `dialog` and all its parts.

| Component | Auto-installs |
|-----------|---------------|
| button | shell, icon, button-variants |
Expand Down
Loading
Loading