Beta channel scaffold
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
<!--
|
||||
Helper project so `dotnet pack` can build a .nupkg straight from a .nuspec.
|
||||
It produces no assemblies; all package contents come from the nuspec passed
|
||||
in via -p:NuspecFile / -p:NuspecBasePath (see pack.ps1).
|
||||
-->
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<IncludeBuildOutput>false</IncludeBuildOutput>
|
||||
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
|
||||
<EnableDefaultItems>false</EnableDefaultItems>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<NoWarn>NU5128;NU5048;NU5125</NoWarn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,85 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Packs Q-SYS plugin folders into .nupkg files.
|
||||
|
||||
.DESCRIPTION
|
||||
For each plugin folder under plugins/ (or a single one via -Plugin):
|
||||
1. Loads the plugin's .nuspec
|
||||
2. Replaces the <description> element with the contents of
|
||||
description.md, if that file exists next to the nuspec
|
||||
3. Packs it into a .nupkg using `dotnet pack` (no Visual Studio needed)
|
||||
|
||||
Output lands in -OutputDir (default: dist/).
|
||||
|
||||
.EXAMPLE
|
||||
./tools/pack.ps1 # pack every plugin
|
||||
./tools/pack.ps1 -Plugin ExamplePlugin # pack one plugin
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$Plugin,
|
||||
[string]$OutputDir = "dist"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$repoRoot = Split-Path -Parent $PSScriptRoot
|
||||
$pluginsDir = Join-Path $repoRoot "plugins"
|
||||
$packProj = Join-Path $PSScriptRoot "pack.csproj"
|
||||
$OutputDir = [System.IO.Path]::GetFullPath((Join-Path $repoRoot $OutputDir))
|
||||
New-Item -ItemType Directory -Force -Path $OutputDir | Out-Null
|
||||
|
||||
# Which plugin folders to pack?
|
||||
$targets = if ($Plugin) {
|
||||
$dir = Join-Path $pluginsDir $Plugin
|
||||
if (-not (Test-Path $dir)) { throw "Plugin folder not found: $dir" }
|
||||
Get-Item $dir
|
||||
} else {
|
||||
Get-ChildItem $pluginsDir -Directory
|
||||
}
|
||||
|
||||
$packed = @()
|
||||
foreach ($dir in $targets) {
|
||||
$nuspec = Get-ChildItem $dir.FullName -Filter *.nuspec | Select-Object -First 1
|
||||
if (-not $nuspec) {
|
||||
Write-Warning "Skipping $($dir.Name): no .nuspec found"
|
||||
continue
|
||||
}
|
||||
|
||||
# Load nuspec and inject description.md if present
|
||||
[xml]$xml = Get-Content $nuspec.FullName -Raw
|
||||
$descFile = Join-Path $dir.FullName "description.md"
|
||||
if (Test-Path $descFile) {
|
||||
$desc = (Get-Content $descFile -Raw).Trim()
|
||||
# NuGet caps description at 4000 chars
|
||||
if ($desc.Length -gt 4000) { $desc = $desc.Substring(0, 4000) }
|
||||
$node = $xml.package.metadata.GetElementsByTagName("description")[0]
|
||||
if (-not $node) {
|
||||
$node = $xml.CreateElement("description", $xml.package.NamespaceURI)
|
||||
$xml.package.metadata.AppendChild($node) | Out-Null
|
||||
}
|
||||
$node.InnerText = $desc # InnerText handles XML escaping
|
||||
Write-Host " [$($dir.Name)] description injected from description.md"
|
||||
}
|
||||
|
||||
$id = $xml.package.metadata.id
|
||||
$version = $xml.package.metadata.version
|
||||
|
||||
# Write the effective nuspec to a temp file (source nuspec stays untouched)
|
||||
$tmpNuspec = Join-Path ([System.IO.Path]::GetTempPath()) "$id.$version.nuspec"
|
||||
$xml.Save($tmpNuspec)
|
||||
|
||||
Write-Host " [$($dir.Name)] packing $id $version ..."
|
||||
dotnet pack $packProj `
|
||||
-p:NuspecFile=$tmpNuspec `
|
||||
-p:NuspecBasePath=$($dir.FullName) `
|
||||
-o $OutputDir --nologo -v quiet
|
||||
if ($LASTEXITCODE -ne 0) { throw "dotnet pack failed for $($dir.Name)" }
|
||||
|
||||
Remove-Item $tmpNuspec -ErrorAction SilentlyContinue
|
||||
$pkg = Join-Path $OutputDir "$id.$version.nupkg"
|
||||
$packed += $pkg
|
||||
Write-Host " [$($dir.Name)] -> $pkg" -ForegroundColor Green
|
||||
}
|
||||
|
||||
if ($packed.Count -eq 0) { throw "Nothing was packed." }
|
||||
Write-Host "`nPacked $($packed.Count) package(s) into $OutputDir"
|
||||
@@ -0,0 +1,90 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
List and delete package versions in the Gitea NuGet registry.
|
||||
|
||||
.DESCRIPTION
|
||||
Listing without -Token uses the anonymous NuGet v3 search endpoint - the
|
||||
same view Q-SYS Designer gets, so it doubles as a feed health check.
|
||||
Listing with -Token uses Gitea's management API and adds publish dates.
|
||||
Deleting always requires -Token (package write scope).
|
||||
|
||||
.EXAMPLE
|
||||
./tools/packages.ps1 -List -Owner jodamaster
|
||||
./tools/packages.ps1 -List -Owner jodamaster -Id ExamplePlugin -Token $env:GITEA_TOKEN
|
||||
./tools/packages.ps1 -Delete -Owner jodamaster -Id ExamplePlugin -Version 1.0.0 -Token $env:GITEA_TOKEN
|
||||
#>
|
||||
[CmdletBinding(DefaultParameterSetName = "List")]
|
||||
param(
|
||||
[Parameter(ParameterSetName = "List")] [switch]$List,
|
||||
[Parameter(ParameterSetName = "Delete", Mandatory)] [switch]$Delete,
|
||||
|
||||
[string]$GiteaUrl = "https://3f4dzl.gitea.cloud",
|
||||
[Parameter(Mandatory)] [string]$Owner,
|
||||
|
||||
[Parameter(ParameterSetName = "List")]
|
||||
[Parameter(ParameterSetName = "Delete", Mandatory)]
|
||||
[string]$Id,
|
||||
|
||||
[Parameter(ParameterSetName = "Delete", Mandatory)] [string]$Version,
|
||||
[string]$Token, # required for -Delete; optional for -List (adds publish dates)
|
||||
[switch]$Force # skip the delete confirmation prompt
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$base = $GiteaUrl.TrimEnd('/')
|
||||
$headers = @{}
|
||||
if ($Token) { $headers["Authorization"] = "token $Token" }
|
||||
|
||||
# ---------------- Delete ----------------
|
||||
if ($PSCmdlet.ParameterSetName -eq "Delete") {
|
||||
if (-not $Token) { throw "Deleting requires -Token (package write scope)." }
|
||||
if (-not $Force) {
|
||||
$answer = Read-Host "Delete $Id $Version from $Owner's registry? This is immediate and permanent. [y/N]"
|
||||
if ($answer -notmatch '^[Yy]') { Write-Host "Aborted."; exit 0 }
|
||||
}
|
||||
$uri = "$base/api/packages/$Owner/nuget/$Id/$Version"
|
||||
Invoke-RestMethod -Uri $uri -Headers $headers -Method Delete | Out-Null
|
||||
Write-Host "Deleted $Id $Version." -ForegroundColor Green
|
||||
Write-Host "Note: Q-SYS expects strictly ascending versions - prefer publishing a higher"
|
||||
Write-Host "version over deleting and re-using a version number (clients may have cached it)."
|
||||
exit 0
|
||||
}
|
||||
|
||||
# ---------------- List ----------------
|
||||
if ($Token) {
|
||||
# Management API: full info including publish dates (requires sign-in on Gitea Cloud)
|
||||
$all = @(); $page = 1
|
||||
while ($true) {
|
||||
$uri = "$base/api/v1/packages/$($Owner)?type=nuget&limit=50&page=$page"
|
||||
$batch = Invoke-RestMethod -Uri $uri -Headers $headers -Method Get
|
||||
if (-not $batch -or $batch.Count -eq 0) { break }
|
||||
$all += $batch
|
||||
if ($batch.Count -lt 50) { break }
|
||||
$page++
|
||||
}
|
||||
if ($Id) { $all = $all | Where-Object { $_.name -ieq $Id } }
|
||||
if (-not $all -or $all.Count -eq 0) { Write-Host "No packages found."; exit 0 }
|
||||
$all | Sort-Object name, created_at | Group-Object name | ForEach-Object {
|
||||
Write-Host "`n$($_.Name)" -ForegroundColor Cyan
|
||||
$_.Group | ForEach-Object {
|
||||
$created = ([datetime]$_.created_at).ToLocalTime().ToString("yyyy-MM-dd HH:mm")
|
||||
Write-Host (" {0,-20} published {1}" -f $_.version, $created)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# Anonymous NuGet v3 search - exactly what Q-SYS Designer sees
|
||||
$q = if ($Id) { $Id } else { "" }
|
||||
$uri = "$base/api/packages/$Owner/nuget/query?q=$q&skip=0&take=100"
|
||||
$result = Invoke-RestMethod -Uri $uri -Method Get
|
||||
$items = $result.data
|
||||
if ($Id) { $items = $items | Where-Object { $_.id -ieq $Id } }
|
||||
if (-not $items -or $items.Count -eq 0) { Write-Host "No packages visible in the anonymous feed for '$Owner'."; exit 0 }
|
||||
foreach ($pkg in $items) {
|
||||
Write-Host "`n$($pkg.id) (latest: $($pkg.version))" -ForegroundColor Cyan
|
||||
foreach ($v in $pkg.versions) { Write-Host " $($v.version)" }
|
||||
Write-Host " Designer 'Add Personal Package' URL:" -ForegroundColor DarkGray
|
||||
Write-Host " $base/api/packages/$Owner/nuget/registration/$($pkg.id)/index.json" -ForegroundColor Yellow
|
||||
}
|
||||
Write-Host "`n(Anonymous view = what Q-SYS Designer sees. Add -Token for publish dates.)"
|
||||
}
|
||||
Write-Host ""
|
||||
@@ -0,0 +1,49 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Packs and pushes Q-SYS plugin packages to a Gitea NuGet registry.
|
||||
|
||||
.DESCRIPTION
|
||||
Runs pack.ps1, then pushes every .nupkg in dist/ to your Gitea instance.
|
||||
Already-published versions are skipped (--skip-duplicate), so it is safe
|
||||
to run repeatedly - only new version numbers actually upload.
|
||||
|
||||
.EXAMPLE
|
||||
./tools/publish.ps1 -GiteaUrl https://gitea.example.com -Owner qsys-plugins -Token $env:GITEA_TOKEN
|
||||
./tools/publish.ps1 -GiteaUrl https://gitea.example.com -Owner qsys-plugins -Token xxxx -Plugin ExamplePlugin
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$GiteaUrl = "https://3f4dzl.gitea.cloud",
|
||||
[Parameter(Mandatory)] [string]$Owner, # Gitea user or org that owns the packages
|
||||
[Parameter(Mandatory)] [string]$Token, # Gitea personal access token (package write scope)
|
||||
[string]$Plugin,
|
||||
[string]$OutputDir = "dist"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$repoRoot = Split-Path -Parent $PSScriptRoot
|
||||
|
||||
# 1. Pack
|
||||
& (Join-Path $PSScriptRoot "pack.ps1") -Plugin $Plugin -OutputDir $OutputDir
|
||||
|
||||
# 2. Push - Gitea needs a NAMED source with basic-auth credentials;
|
||||
# pushing straight to the URL with --api-key fails (go-gitea/gitea#20717).
|
||||
$feed = "$($GiteaUrl.TrimEnd('/'))/api/packages/$Owner/nuget/index.json"
|
||||
$dist = Join-Path $repoRoot $OutputDir
|
||||
Write-Host "`nPushing to $feed"
|
||||
|
||||
dotnet nuget remove source gitea-publish 2>$null | Out-Null
|
||||
dotnet nuget add source $feed --name gitea-publish `
|
||||
--username publisher --password $Token --store-password-in-clear-text | Out-Null
|
||||
|
||||
try {
|
||||
Get-ChildItem $dist -Filter *.nupkg | ForEach-Object {
|
||||
Write-Host " pushing $($_.Name) ..."
|
||||
dotnet nuget push $_.FullName --source gitea-publish --skip-duplicate
|
||||
if ($LASTEXITCODE -ne 0) { throw "Push failed for $($_.Name)" }
|
||||
}
|
||||
} finally {
|
||||
dotnet nuget remove source gitea-publish 2>$null | Out-Null
|
||||
}
|
||||
|
||||
Write-Host "`nDone. Feed URL for Q-SYS Designer users: $feed" -ForegroundColor Green
|
||||
Reference in New Issue
Block a user