Skip to content

chore(release): bump version to 1.17.0 #38

chore(release): bump version to 1.17.0

chore(release): bump version to 1.17.0 #38

Workflow file for this run

name: Release
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-*' # prerelease タグ(v1.5.0-beta.1 等)
env:
CARGO_TERM_COLOR: always
# GitHub Release への書き込み権限 + SLSA Provenance 生成(attestations)
permissions:
contents: write
id-token: write # OIDC トークン(attest-build-provenance に必須)
attestations: write # SLSA Provenance アテステーション
jobs:
# ── Step 1: Release ページを先に作成する ──────────────────────────
create-release:
name: Create GitHub Release
runs-on: ubuntu-latest
outputs:
tag: ${{ github.ref_name }}
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Create Release
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
with:
generate_release_notes: true
draft: false
# タグ名に `-` が含まれていれば prerelease として扱う(v1.5.0-beta.1 等)
prerelease: ${{ contains(github.ref_name, '-') }}
# ── Step 2: 各プラットフォームのバイナリをビルドして添付する ──────
build:
name: Build (${{ matrix.name }})
needs: create-release
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
# Linux x86_64
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
name: linux-x86_64
archive_ext: tar.gz
# macOS Apple Silicon (M1/M2/M3)
- os: macos-latest
target: aarch64-apple-darwin
name: macos-arm64
archive_ext: tar.gz
# macOS Intel
- os: macos-latest
target: x86_64-apple-darwin
name: macos-x86_64
archive_ext: tar.gz
# Windows x86_64
- os: windows-latest
target: x86_64-pc-windows-msvc
name: windows-x86_64
archive_ext: zip
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Set up Rust toolchain
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
targets: ${{ matrix.target }}
- name: Cache Cargo artifacts
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
- name: Install Linux system dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
libx11-dev libxkbcommon-dev libwayland-dev \
libasound2-dev libpulse-dev \
libudev-dev \
libfuse2
- name: Build release binaries
# nexterm-client-gpu は v0.9.3 でバイナリ名を nexterm に変更し、
# サーバーを内部起動するシングルバイナリとなった。旧 nexterm-launcher は
# 役目を終え v1.4.0 で削除済み。
# NEXTERM_MINISIGN_PUBLIC_KEY (Sprint 3-4): 設定されている場合は signature_verify
# モジュールに公開鍵が埋め込まれ、自動更新時の minisign 検証が有効化される。
env:
NEXTERM_MINISIGN_PUBLIC_KEY: ${{ vars.NEXTERM_MINISIGN_PUBLIC_KEY }}
run: >
cargo build --release --target ${{ matrix.target }}
-p nexterm-server
-p nexterm-client-gpu
-p nexterm-client-tui
-p nexterm-ctl
# ── macOS: .app バンドル作成 ──
- name: Create macOS .app bundle
if: runner.os == 'macOS'
run: |
APP=dist/Nexterm.app
mkdir -p "$APP/Contents/MacOS"
# 全バイナリを .app バンドル内に配置
for bin in nexterm nexterm-server nexterm-client-tui nexterm-ctl; do
BIN_PATH="target/${{ matrix.target }}/release/$bin"
if [ -f "$BIN_PATH" ]; then
cp "$BIN_PATH" "$APP/Contents/MacOS/"
fi
done
# Info.plist のバージョンを置換して配置
VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*= "\(.*\)"/\1/')
sed "s/BUNDLE_VERSION/${VERSION}/g" macos/Info.plist > "$APP/Contents/Info.plist"
# ── macOS: ad-hoc コード署名(Gatekeeper の quarantine 除去後に起動可能にする)──
- name: Ad-hoc code sign (macOS)
if: runner.os == 'macOS'
run: |
# --deep でバンドル内の全バイナリを再帰的に一括署名する
# (個別署名後にバンドルを署名すると subcomponent エラーになるため)
codesign --force --deep --sign - dist/Nexterm.app
# ── Unix 向けパッケージング ──
- name: Package (Unix)
if: runner.os != 'Windows'
run: |
mkdir -p dist
# 個別バイナリも dist/ に配置(CLI 利用・Homebrew 向け)
for bin in nexterm nexterm-server nexterm-client-tui nexterm-ctl; do
BIN_PATH="target/${{ matrix.target }}/release/$bin"
if [ -f "$BIN_PATH" ]; then
cp "$BIN_PATH" dist/
fi
done
# Linux のみ: .desktop ファイルとインストールスクリプトを同梱
if [ "${{ runner.os }}" = "Linux" ]; then
cp linux/nexterm.desktop dist/
cp linux/install.sh dist/
fi
tar -czf nexterm-${{ github.ref_name }}-${{ matrix.name }}.tar.gz -C dist .
# ── Linux AppImage ビルド ──
- name: Build AppImage (Linux)
if: runner.os == 'Linux'
run: |
# appimagetool をダウンロードする
APPIMAGETOOL_URL="https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
curl -sSL "$APPIMAGETOOL_URL" -o /tmp/appimagetool
chmod +x /tmp/appimagetool
# AppDir を組み立てる
APPDIR=/tmp/Nexterm.AppDir
mkdir -p "${APPDIR}/usr/bin"
# バイナリを配置する
for bin in nexterm nexterm-server nexterm-client-tui nexterm-ctl; do
BIN_PATH="target/${{ matrix.target }}/release/$bin"
if [ -f "$BIN_PATH" ]; then
cp "$BIN_PATH" "${APPDIR}/usr/bin/"
fi
done
# AppRun スクリプト(エントリーポイント)
cp linux/AppRun "${APPDIR}/AppRun"
chmod +x "${APPDIR}/AppRun"
# .desktop ファイルを AppDir にコピーし、Icon= を "nexterm" に書き換える
# (appimagetool は AppDir 内の <Icon>.png を探すため、Icon 名とファイル名を一致させる)
sed 's/^Icon=.*/Icon=nexterm/' linux/nexterm.desktop > "${APPDIR}/nexterm.desktop"
# アイコンを nexterm.png として配置する
if [ -f "assets/icon.png" ]; then
cp assets/icon.png "${APPDIR}/nexterm.png"
else
# ダミーアイコン(1x1 透過 PNG)を生成する
printf '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\nIDATx\x9cc\x00\x01\x00\x00\x05\x00\x01\r\n-\xb4\x00\x00\x00\x00IEND\xaeB`\x82' > "${APPDIR}/nexterm.png"
fi
# appimagetool でパッケージ化(libfuse2 が入っているので直接実行可能)
ARCH=x86_64 /tmp/appimagetool \
"${APPDIR}" \
"nexterm-${{ github.ref_name }}-${{ matrix.name }}.AppImage"
- name: Upload AppImage to GitHub Release
if: runner.os == 'Linux'
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
with:
files: nexterm-${{ github.ref_name }}-${{ matrix.name }}.AppImage
# ── Windows 向けパッケージング(ZIP)──
- name: Package (Windows ZIP)
if: runner.os == 'Windows'
shell: pwsh
run: |
New-Item -ItemType Directory -Path dist | Out-Null
# nexterm.exe = GPU クライアント + サーバー統合バイナリ(v0.9.3〜)
Copy-Item target/${{ matrix.target }}/release/nexterm.exe dist/
Copy-Item target/${{ matrix.target }}/release/nexterm-server.exe dist/
Copy-Item target/${{ matrix.target }}/release/nexterm-client-tui.exe dist/
Copy-Item target/${{ matrix.target }}/release/nexterm-ctl.exe dist/
Copy-Item scripts/install-service.ps1 dist/
Copy-Item scripts/uninstall-service.ps1 dist/
Compress-Archive -Path dist/* -DestinationPath nexterm-${{ github.ref_name }}-${{ matrix.name }}.zip
# ── Windows コード署名(証明書が Secrets に設定されている場合のみ)──
- name: Sign binaries (Windows)
if: runner.os == 'Windows' && env.WINDOWS_CERTIFICATE != ''
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
shell: pwsh
run: |
# Base64 エンコードされた PFX 証明書をデコードしてファイルに保存
$certBytes = [System.Convert]::FromBase64String($env:WINDOWS_CERTIFICATE)
$certPath = Join-Path $env:RUNNER_TEMP "nexterm-sign.pfx"
[System.IO.File]::WriteAllBytes($certPath, $certBytes)
# signtool.exe でバイナリを署名
$signtool = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\signtool.exe"
$targets = @(
"dist\nexterm.exe",
"dist\nexterm-server.exe",
"dist\nexterm-client-tui.exe",
"dist\nexterm-ctl.exe"
)
foreach ($t in $targets) {
& $signtool sign `
/f $certPath `
/p $env:WINDOWS_CERTIFICATE_PASSWORD `
/tr http://timestamp.digicert.com `
/td sha256 /fd sha256 `
$t
}
# 証明書ファイルを削除
Remove-Item $certPath -Force
# ── Windows MSI インストーラービルド ──
- name: Build MSI installer (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
# WiX Toolset v3 のインストール(未インストールの場合のみ)
if (-not (Get-Command candle.exe -ErrorAction SilentlyContinue)) {
choco install wixtoolset -y --no-progress
}
$wixInstalled = Get-ChildItem "C:\Program Files (x86)\WiX Toolset*" -Directory -ErrorAction SilentlyContinue |
Sort-Object Name -Descending | Select-Object -First 1
if (-not $wixInstalled) { throw "WiX Toolset not found" }
$env:Path += ";$($wixInstalled.FullName)\bin"
# MSI のバージョンを Cargo.toml から取得
$matchResult = Select-String -Path Cargo.toml -Pattern '^version\s*=\s*"([^"]+)"' |
Select-Object -First 1
$version = $matchResult.Matches[0].Groups[1].Value
if ([string]::IsNullOrEmpty($version)) { throw "Cannot extract version from Cargo.toml" }
# WiX v3 の Product/Version 属性は a.b.c.d 数値形式のみ許容するため、
# prerelease suffix(例: "1.5.0-beta.1" → "1.5.0")を除去する。
# GitHub Release のタイトル(${{ github.ref_name }})には beta.1 が残る。
if ($version -match '^([0-9]+\.[0-9]+\.[0-9]+)') {
$version = $Matches[1]
}
Write-Host "MSI version: $version"
# candle.exe + light.exe でMSIをビルド(-d フラグでバージョンをプリプロセッサ変数として渡す)
$wixDir = "$($wixInstalled.FullName)\bin"
$wixPath = "wix\main.wxs"
New-Item -ItemType Directory -Path build -Force | Out-Null
& "$wixDir\candle.exe" -arch x64 "-dVersion=$version" -out "build\" $wixPath
if ($LASTEXITCODE -ne 0) { throw "candle.exe failed" }
& "$wixDir\light.exe" `
-out "nexterm-${{ github.ref_name }}-${{ matrix.name }}.msi" `
"build\main.wixobj"
if ($LASTEXITCODE -ne 0) { throw "light.exe failed" }
# ── MSI 署名(証明書が設定されている場合)──
- name: Sign MSI (Windows)
if: runner.os == 'Windows' && env.WINDOWS_CERTIFICATE != ''
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
shell: pwsh
run: |
$certBytes = [System.Convert]::FromBase64String($env:WINDOWS_CERTIFICATE)
$certPath = Join-Path $env:RUNNER_TEMP "nexterm-sign.pfx"
[System.IO.File]::WriteAllBytes($certPath, $certBytes)
$signtool = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\signtool.exe"
& $signtool sign `
/f $certPath `
/p $env:WINDOWS_CERTIFICATE_PASSWORD `
/tr http://timestamp.digicert.com `
/td sha256 /fd sha256 `
"nexterm-${{ github.ref_name }}-${{ matrix.name }}.msi"
Remove-Item $certPath -Force
# ── Sprint 3-4: minisign 署名(秘密鍵が Secrets に設定されている場合のみ)──
# MINISIGN_SECRET_KEY: minisign -G で生成した秘密鍵ファイルの内容(複数行)
# MINISIGN_PASSWORD: 秘密鍵のパスワード(鍵生成時に設定したもの)
- name: Set up minisign (Linux)
if: runner.os == 'Linux' && env.MINISIGN_SECRET_KEY != ''
env:
MINISIGN_SECRET_KEY: ${{ secrets.MINISIGN_SECRET_KEY }}
run: |
sudo apt-get install -y minisign
- name: Set up minisign (macOS)
if: runner.os == 'macOS' && env.MINISIGN_SECRET_KEY != ''
env:
MINISIGN_SECRET_KEY: ${{ secrets.MINISIGN_SECRET_KEY }}
run: |
brew install minisign
- name: Set up minisign (Windows)
if: runner.os == 'Windows' && env.MINISIGN_SECRET_KEY != ''
env:
MINISIGN_SECRET_KEY: ${{ secrets.MINISIGN_SECRET_KEY }}
shell: pwsh
run: |
choco install minisign -y --no-progress
- name: Sign release archives with minisign (Unix)
if: runner.os != 'Windows' && env.MINISIGN_SECRET_KEY != ''
env:
MINISIGN_SECRET_KEY: ${{ secrets.MINISIGN_SECRET_KEY }}
MINISIGN_PASSWORD: ${{ secrets.MINISIGN_PASSWORD }}
run: |
# 秘密鍵を一時ファイルに書き出す
KEY_FILE="$RUNNER_TEMP/nexterm-minisign.key"
printf '%s' "$MINISIGN_SECRET_KEY" > "$KEY_FILE"
chmod 600 "$KEY_FILE"
# tar.gz および AppImage(Linux のみ)を署名
for archive in \
"nexterm-${{ github.ref_name }}-${{ matrix.name }}.tar.gz" \
"nexterm-${{ github.ref_name }}-${{ matrix.name }}.AppImage"; do
if [ -f "$archive" ]; then
echo "$MINISIGN_PASSWORD" | minisign -S -s "$KEY_FILE" -m "$archive"
echo "Signed: $archive -> $archive.minisig"
fi
done
# 秘密鍵を削除
rm -f "$KEY_FILE"
- name: Sign release archives with minisign (Windows)
if: runner.os == 'Windows' && env.MINISIGN_SECRET_KEY != ''
env:
MINISIGN_SECRET_KEY: ${{ secrets.MINISIGN_SECRET_KEY }}
MINISIGN_PASSWORD: ${{ secrets.MINISIGN_PASSWORD }}
shell: pwsh
run: |
$keyFile = Join-Path $env:RUNNER_TEMP "nexterm-minisign.key"
[System.IO.File]::WriteAllText($keyFile, $env:MINISIGN_SECRET_KEY)
$targets = @(
"nexterm-${{ github.ref_name }}-${{ matrix.name }}.zip",
"nexterm-${{ github.ref_name }}-${{ matrix.name }}.msi"
)
foreach ($archive in $targets) {
if (Test-Path $archive) {
$env:MINISIGN_PASSWORD | minisign -S -s $keyFile -m $archive
Write-Host "Signed: $archive -> $archive.minisig"
}
}
Remove-Item $keyFile -Force
# ── Sprint 3-4: SLSA Build Provenance(全リリースアーティファクト)──
# 検証コマンド: gh attestation verify <archive> -R mizu-jun/Nexterm
- name: Generate SLSA Provenance
uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0
with:
subject-path: |
nexterm-${{ github.ref_name }}-${{ matrix.name }}.${{ matrix.archive_ext }}
- name: Generate SLSA Provenance (MSI)
if: runner.os == 'Windows'
uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0
with:
subject-path: nexterm-${{ github.ref_name }}-${{ matrix.name }}.msi
- name: Generate SLSA Provenance (AppImage)
if: runner.os == 'Linux'
uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0
with:
subject-path: nexterm-${{ github.ref_name }}-${{ matrix.name }}.AppImage
# ── GitHub Release にアーカイブを添付 ──
- name: Upload ZIP to GitHub Release
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
with:
files: |
nexterm-${{ github.ref_name }}-${{ matrix.name }}.${{ matrix.archive_ext }}
nexterm-${{ github.ref_name }}-${{ matrix.name }}.${{ matrix.archive_ext }}.minisig
- name: Upload MSI to GitHub Release
if: runner.os == 'Windows'
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
with:
files: |
nexterm-${{ github.ref_name }}-${{ matrix.name }}.msi
nexterm-${{ github.ref_name }}-${{ matrix.name }}.msi.minisig
- name: Upload AppImage minisig to GitHub Release
if: runner.os == 'Linux'
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
with:
files: nexterm-${{ github.ref_name }}-${{ matrix.name }}.AppImage.minisig