Initial commit: claude-skills with wordcraft-mcp and gridcraft-mcp 0.1.0.
This commit is contained in:
commit
cf01e22a1e
50 files changed
+2726
No files matched your search
@@ -0,0 +1,141 @@
|
||||
# Builds the skill ZIP (and .mcpb if extension/) and creates a remote release with those assets.
|
||||
# Auth: same as git push (credential helper), or env RELEASE_TOKEN if set.
|
||||
# The tag <name>/v<version> must exist locally and on the remote. Does not push tags.
|
||||
# Usage: scripts\release.ps1 -Name <skill-name>
|
||||
param([Parameter(Mandatory = $true)][string]$Name)
|
||||
. (Join-Path $PSScriptRoot 'lib.ps1')
|
||||
|
||||
$RepoApi = 'https://git.gundel.dev/api/v1/repos/dg/claude-skills'
|
||||
$RepoHost = 'git.gundel.dev'
|
||||
|
||||
$AuthHeader = $null
|
||||
if ($env:RELEASE_TOKEN) {
|
||||
$AuthHeader = "token $($env:RELEASE_TOKEN)"
|
||||
}
|
||||
else {
|
||||
$credRaw = "protocol=https`nhost=$RepoHost`n`n" | git credential fill 2>$null
|
||||
$user = $null; $pass = $null
|
||||
foreach ($line in $credRaw) {
|
||||
if ($line -match '^username=(.*)$') { $user = $Matches[1] }
|
||||
if ($line -match '^password=(.*)$') { $pass = $Matches[1] }
|
||||
}
|
||||
if ($user -and $pass) {
|
||||
$pair = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("${user}:${pass}"))
|
||||
$AuthHeader = "Basic $pair"
|
||||
}
|
||||
}
|
||||
if (-not $AuthHeader) {
|
||||
Write-Host 'Keine Auth fuer das Release (git credential oder RELEASE_TOKEN).'
|
||||
exit 1
|
||||
}
|
||||
|
||||
$dir = Join-Path $SkillsDir $Name
|
||||
if (-not (Test-Path $dir -PathType Container)) {
|
||||
Write-Host "Ordner skills/$Name existiert nicht."
|
||||
exit 1
|
||||
}
|
||||
|
||||
$ver = Get-SkillVersion $dir
|
||||
if (-not $ver) {
|
||||
Write-Host "CHANGELOG von $Name hat keine Version '## x.y.z (YYYY-MM-DD)'."
|
||||
exit 1
|
||||
}
|
||||
|
||||
$tag = "$Name/v$ver"
|
||||
git -C $Root rev-parse --verify --quiet "refs/tags/$tag" | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "Tag $tag fehlt lokal. Setzen, nicht verschieben: git tag $tag"
|
||||
exit 1
|
||||
}
|
||||
|
||||
& (Join-Path $PSScriptRoot 'package.ps1') -Name $Name
|
||||
if ($LASTEXITCODE -ne 0) { exit 1 }
|
||||
|
||||
$zipName = "$Name-v$ver.zip"
|
||||
$zipPath = Join-Path $DistDir $zipName
|
||||
if (-not (Test-Path $zipPath)) {
|
||||
Write-Host "ZIP fehlt: dist/$zipName"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$on = $false
|
||||
$acc = New-Object System.Collections.Generic.List[string]
|
||||
foreach ($l in ((Read-Text (Join-Path $dir 'CHANGELOG.md')) -split "`n")) {
|
||||
if (-not $on) {
|
||||
if ($l.StartsWith("## $ver ")) { $on = $true }
|
||||
continue
|
||||
}
|
||||
if ($l.StartsWith('## ')) { break }
|
||||
$acc.Add($l)
|
||||
}
|
||||
$notes = (($acc -join "`n").Trim())
|
||||
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
|
||||
function Invoke-ReleaseApi([string]$Method, [string]$Url, [byte[]]$Body, [string]$ContentType) {
|
||||
$req = [Net.HttpWebRequest]::Create($Url)
|
||||
$req.Method = $Method
|
||||
$req.Headers.Add('Authorization', $AuthHeader)
|
||||
$req.Accept = 'application/json'
|
||||
if ($null -ne $Body) {
|
||||
$req.ContentType = $ContentType
|
||||
$req.ContentLength = $Body.LongLength
|
||||
$stream = $req.GetRequestStream()
|
||||
$stream.Write($Body, 0, $Body.Length)
|
||||
$stream.Close()
|
||||
}
|
||||
try {
|
||||
$resp = $req.GetResponse()
|
||||
}
|
||||
catch [System.Net.WebException] {
|
||||
$errResp = $_.Exception.Response
|
||||
$detail = ''
|
||||
if ($errResp) {
|
||||
$reader = New-Object IO.StreamReader($errResp.GetResponseStream())
|
||||
$detail = $reader.ReadToEnd()
|
||||
$reader.Close()
|
||||
}
|
||||
throw "API-Fehler $Url : $detail"
|
||||
}
|
||||
$reader = New-Object IO.StreamReader($resp.GetResponseStream(), $Utf8NoBom)
|
||||
$text = $reader.ReadToEnd()
|
||||
$reader.Close()
|
||||
$resp.Close()
|
||||
return $text
|
||||
}
|
||||
|
||||
$payload = @{
|
||||
tag_name = $tag
|
||||
name = "$Name $ver"
|
||||
body = $notes
|
||||
} | ConvertTo-Json -Compress
|
||||
try {
|
||||
$created = Invoke-ReleaseApi 'POST' "$RepoApi/releases" $Utf8NoBom.GetBytes($payload) 'application/json; charset=utf-8' | ConvertFrom-Json
|
||||
}
|
||||
catch {
|
||||
Write-Host $_
|
||||
Write-Host "Tag auf dem Server? git push origin $tag"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$assetUrl = "$RepoApi/releases/$($created.id)/assets?name=$([Uri]::EscapeDataString($zipName))"
|
||||
$asset = Invoke-ReleaseApi 'POST' $assetUrl ([IO.File]::ReadAllBytes($zipPath)) 'application/octet-stream' | ConvertFrom-Json
|
||||
|
||||
$mcpbName = "$Name-v$ver.mcpb"
|
||||
$mcpbPath = Join-Path $DistDir $mcpbName
|
||||
$mcpbAsset = $null
|
||||
if (Test-Path (Join-Path (Join-Path $dir 'extension') 'manifest.json')) {
|
||||
if (-not (Test-Path $mcpbPath)) {
|
||||
& (Join-Path $PSScriptRoot 'package-mcpb.ps1') -Name $Name
|
||||
if ($LASTEXITCODE -ne 0) { exit 1 }
|
||||
}
|
||||
if (Test-Path $mcpbPath) {
|
||||
$mcpbUrl = "$RepoApi/releases/$($created.id)/assets?name=$([Uri]::EscapeDataString($mcpbName))"
|
||||
$mcpbAsset = Invoke-ReleaseApi 'POST' $mcpbUrl ([IO.File]::ReadAllBytes($mcpbPath)) 'application/octet-stream' | ConvertFrom-Json
|
||||
}
|
||||
}
|
||||
|
||||
if ($created.html_url) { Write-Host $created.html_url }
|
||||
if ($asset.browser_download_url) { Write-Host $asset.browser_download_url }
|
||||
if ($mcpbAsset -and $mcpbAsset.browser_download_url) { Write-Host $mcpbAsset.browser_download_url }
|
||||
Write-Host "Release $tag angelegt."
|
||||
Reference in new issue
Block a user