Answers two things: how to install these without a marketplace, and how to keep settings in sync when VS Code's Settings Sync cannot be pointed at Gitea. - build.ps1 packages each extension into dist/ - publish.ps1 creates a release and uploads them, replacing same-named assets so a rolling "latest" tag stays clean - install.ps1 downloads a release's assets and installs them, or -Local from dist/ - settings.ps1 copies User/ between the repo and the machine, and installs the marketplace extensions recorded in extensions.txt - dev-link.ps1 junctions the sources into ~/.vscode/extensions for development - ci-release.sh plus a Gitea Actions workflow do the build and publish on a tag push Settings are copied, not symlinked: an atomic save replaces a symlink with a regular file and the sync stops without looking broken. vsce/ pins vsce and undici so packaging works on Node 18, which current vsce does not support. test/run.ps1 drives the real scripts against a stub of the Gitea release API. It caught the multipart Content-Disposition being unquoted on .NET Framework, and Invoke-WebRequest dropping the Authorization header across a redirect.
113 lines
3.8 KiB
PowerShell
113 lines
3.8 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Uploads dist/*.vsix to a release on Gitea.
|
|
|
|
.DESCRIPTION
|
|
Creates the release for -Tag if it does not exist, then uploads each .vsix as an
|
|
asset. An asset with the same name is deleted first, so re-publishing the same tag
|
|
replaces the packages instead of piling up duplicates -- which is what makes the
|
|
default rolling "latest" tag usable as the thing install.ps1 reads.
|
|
|
|
Needs a token with write:repository scope. See Get-GiteaToken in common.ps1 for
|
|
where it is read from; it is never read from inside this repo.
|
|
|
|
.PARAMETER Tag
|
|
The release tag. Defaults to "latest", a rolling release holding current builds.
|
|
Use a version tag for a snapshot you want to keep.
|
|
|
|
.PARAMETER Build
|
|
Run build.ps1 first.
|
|
|
|
.PARAMETER Notes
|
|
Release body. Defaults to a list of the packages and their versions.
|
|
|
|
.EXAMPLE
|
|
.\scripts\publish.ps1 -Build
|
|
.\scripts\publish.ps1 -Tag v0.1.0 -Notes 'First cut of all three.'
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[string] $Tag = 'latest',
|
|
[string] $Token,
|
|
[string] $Notes,
|
|
[string] $Target,
|
|
[switch] $Build,
|
|
[switch] $Prerelease
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = 'Stop'
|
|
. (Join-Path $PSScriptRoot 'common.ps1')
|
|
|
|
if ($Build) { & (Join-Path $PSScriptRoot 'build.ps1') | Out-Null }
|
|
|
|
$config = Get-SetupConfig
|
|
$Token = Get-GiteaToken -Token $Token
|
|
$dist = Get-DistDir
|
|
$repoPath = "/repos/$($config.gitea.owner)/$($config.gitea.repo)"
|
|
|
|
$packages = @(Get-ChildItem -Path $dist -Filter '*.vsix' | Sort-Object Name)
|
|
if ($packages.Count -eq 0) {
|
|
throw "no .vsix files in $dist. Run build.ps1, or pass -Build."
|
|
}
|
|
|
|
Write-Host "publishing $($packages.Count) package(s) to " -NoNewline
|
|
Write-Host "$($config.gitea.url)/$($config.gitea.owner)/$($config.gitea.repo)@$Tag" -ForegroundColor Cyan
|
|
|
|
$release = Get-GiteaRelease -Tag $Tag -Token $Token
|
|
if ($release) {
|
|
Write-Host "reusing release $($release.id)" -ForegroundColor DarkGray
|
|
} else {
|
|
if (-not $Notes) {
|
|
$lines = $packages | ForEach-Object {
|
|
$name = $_.BaseName
|
|
"- $name"
|
|
}
|
|
$Notes = @(
|
|
'VS Code extensions, packaged as VSIX.',
|
|
'',
|
|
($lines -join "`n"),
|
|
'',
|
|
'Install them with scripts/install.ps1, or by hand:',
|
|
'',
|
|
' code --install-extension <file>.vsix --force'
|
|
) -join "`n"
|
|
}
|
|
|
|
$body = @{
|
|
tag_name = $Tag
|
|
name = "VS Code extensions ($Tag)"
|
|
body = $Notes
|
|
draft = $false
|
|
prerelease = [bool] $Prerelease
|
|
}
|
|
# Omitted means Gitea creates the tag on the default branch.
|
|
if ($Target) { $body.target_commitish = $Target }
|
|
|
|
$release = Invoke-Gitea -Token $Token -Method 'POST' -Path "$repoPath/releases" -Body $body
|
|
Write-Host "created release $($release.id) for tag $Tag" -ForegroundColor DarkGray
|
|
}
|
|
|
|
$existing = @()
|
|
if ($release.PSObject.Properties.Name -contains 'assets' -and $release.assets) {
|
|
$existing = @($release.assets)
|
|
}
|
|
|
|
foreach ($package in $packages) {
|
|
$clash = $existing | Where-Object { $_.name -eq $package.Name }
|
|
foreach ($old in $clash) {
|
|
Write-Host " replacing $($package.Name)" -ForegroundColor DarkGray
|
|
Invoke-Gitea -Token $Token -Method 'DELETE' `
|
|
-Path "$repoPath/releases/$($release.id)/assets/$($old.id)" | Out-Null
|
|
}
|
|
|
|
$size = [math]::Round($package.Length / 1KB, 1)
|
|
Write-Host " uploading $($package.Name) ($size KB)" -NoNewline
|
|
$asset = Send-GiteaAsset -ReleaseId $release.id -FilePath $package.FullName -Token $Token
|
|
Write-Host " ok" -ForegroundColor Green
|
|
Write-Verbose " $($asset.browser_download_url)"
|
|
}
|
|
|
|
Write-Host ''
|
|
Write-Host "done: $($config.gitea.url)/$($config.gitea.owner)/$($config.gitea.repo)/releases/tag/$Tag" -ForegroundColor Cyan
|