Skip to content

docs: Improved SSH connection instructions for Windows users #36

docs: Improved SSH connection instructions for Windows users

docs: Improved SSH connection instructions for Windows users #36

Workflow file for this run

name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g., 1.0.0)'
required: true
env:
VERSION: ${{ github.ref_name == '' && github.event.inputs.version || github.ref_name }}
GO_VERSION: '1.21'
# Skip variables - set to 'true' to skip specific deployments
SKIP_SNAP: ${{ vars.SKIP_SNAP || '' }}
SKIP_FLATPAK: ${{ vars.SKIP_FLATPAK || '' }}
SKIP_CHOCOLATEY: ${{ vars.SKIP_CHOCOLATEY || '' }}
SKIP_HOMEBREW: ${{ vars.SKIP_HOMEBREW || '' }}
SKIP_AUR: ${{ vars.SKIP_AUR || '' }}
SKIP_PACKAGES: ${{ vars.SKIP_PACKAGES || '' }}
# Require tests to pass before release
jobs:
test:
name: Run Tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Run tests
run: go test -v -race ./...
build:
name: Build Binaries
needs: test
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
goos: linux
goarch: amd64
binary_name: shelldock-linux-amd64
- os: ubuntu-latest
goos: linux
goarch: arm64
binary_name: shelldock-linux-arm64
- os: macos-latest
goos: darwin
goarch: amd64
binary_name: shelldock-darwin-amd64
- os: macos-latest
goos: darwin
goarch: arm64
binary_name: shelldock-darwin-arm64
- os: windows-latest
goos: windows
goarch: amd64
binary_name: shelldock-windows-amd64.exe
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Extract version (Linux/macOS)
if: matrix.os != 'windows-latest'
id: version
shell: bash
run: |
if [ "${{ github.ref_type }}" = "tag" ]; then
VERSION="${{ github.ref_name }}"
else
VERSION="v${{ github.event.inputs.version }}"
fi
echo "version=${VERSION#v}" >> $GITHUB_OUTPUT
echo "VERSION=${VERSION}" >> $GITHUB_ENV
- name: Extract version (Windows)
if: matrix.os == 'windows-latest'
id: version-windows
shell: pwsh
run: |
if ("${{ github.ref_type }}" -eq "tag") {
$VERSION = "${{ github.ref_name }}"
} else {
$VERSION = "v${{ github.event.inputs.version }}"
}
$VERSION_NUM = $VERSION -replace '^v', ''
echo "version=$VERSION_NUM" >> $env:GITHUB_OUTPUT
echo "VERSION=$VERSION" >> $env:GITHUB_ENV
- name: Build binary (Linux/macOS)
if: matrix.os != 'windows-latest'
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
run: |
VERSION_NUM="${VERSION#v}"
go build -ldflags "-X main.version=${VERSION_NUM}" -o ${{ matrix.binary_name }} .
- name: Install goversioninfo (Windows)
if: matrix.os == 'windows-latest'
shell: pwsh
run: go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@latest
- name: Build binary (Windows)
if: matrix.os == 'windows-latest'
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
shell: pwsh
run: |
.\scripts\build-windows.ps1 -Version "${{ steps.version-windows.outputs.version }}" -OutputName "${{ matrix.binary_name }}"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.binary_name }}
path: ${{ matrix.binary_name }}
packages:
name: Build Packages
needs: [test, build]
runs-on: ubuntu-latest
if: ${{ vars.SKIP_PACKAGES != 'true' && (needs.test.result == 'success' && needs.build.result == 'success') }}
strategy:
matrix:
include:
- distro: debian
package_type: deb
- distro: fedora
package_type: rpm
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Extract version
id: version
run: |
if [ "${{ github.ref_type }}" = "tag" ]; then
VERSION="${{ github.ref_name }}"
else
VERSION="v${{ github.event.inputs.version }}"
fi
echo "version=${VERSION#v}" >> $GITHUB_OUTPUT
echo "VERSION=${VERSION}" >> $GITHUB_ENV
- name: Download Linux binary
uses: actions/download-artifact@v4
with:
name: shelldock-linux-amd64
path: ./build/
- name: Make binary executable
run: chmod +x ./build/shelldock-linux-amd64
- name: Build DEB package
if: matrix.package_type == 'deb'
run: |
mkdir -p dist/deb/DEBIAN
mkdir -p dist/deb/usr/local/bin
mkdir -p dist/deb/usr/share/doc/shelldock
mkdir -p dist/deb/usr/share/shelldock/repository
cp ./build/shelldock-linux-amd64 dist/deb/usr/local/bin/shelldock
cp README.md dist/deb/usr/share/doc/shelldock/
# Copy repository with all subdirectories
cp -r repository/. dist/deb/usr/share/shelldock/repository/ 2>/dev/null || true
sed "s/VERSION/${{ steps.version.outputs.version }}/g" packaging/deb/control > dist/deb/DEBIAN/control
cp packaging/deb/postinst dist/deb/DEBIAN/postinst
chmod +x dist/deb/DEBIAN/postinst
dpkg-deb --build dist/deb dist/shelldock_${{ steps.version.outputs.version }}_amd64.deb
- name: Build RPM package
if: matrix.package_type == 'rpm'
run: |
sudo apt-get update
sudo apt-get install -y rpm
mkdir -p dist/rpm/BUILD dist/rpm/BUILDROOT dist/rpm/RPMS dist/rpm/SOURCES dist/rpm/SPECS
# Create source tarball structure
VERSION="${{ steps.version.outputs.version }}"
mkdir -p dist/rpm/tmp/shelldock-${VERSION}
cp ./build/shelldock-linux-amd64 dist/rpm/tmp/shelldock-${VERSION}/shelldock
cp README.md dist/rpm/tmp/shelldock-${VERSION}/
# Copy repository with all subdirectories
cp -r repository/. dist/rpm/tmp/shelldock-${VERSION}/repository/ 2>/dev/null || true
# Create tarball
cd dist/rpm/tmp
tar czf ../SOURCES/shelldock-${VERSION}.tar.gz shelldock-${VERSION}
cd ../../..
# Create spec file with proper date and architecture
CHANGELOG_DATE=$(date +"%a %b %d %Y")
sed -e "s/VERSION/${VERSION}/g" -e "s/Wed Jan 01 2024/${CHANGELOG_DATE}/g" -e "s/BuildArch: noarch/BuildArch: x86_64/g" packaging/rpm/shelldock.spec > dist/rpm/SPECS/shelldock.spec
rpmbuild --define "_topdir $(pwd)/dist/rpm" -bb dist/rpm/SPECS/shelldock.spec
- name: Upload package
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.package_type }}-package
path: |
dist/*.${{ matrix.package_type }}
dist/rpm/RPMS/*/*.rpm
apt-repo:
name: Create APT Repository
needs: [test, build, packages]
runs-on: ubuntu-latest
if: ${{ vars.SKIP_PACKAGES != 'true' && (needs.test.result == 'success' && needs.build.result == 'success') }}
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Extract version
id: version
run: |
if [ "${{ github.ref_type }}" = "tag" ]; then
VERSION="${{ github.ref_name }}"
else
VERSION="v${{ github.event.inputs.version }}"
fi
echo "version=${VERSION#v}" >> $GITHUB_OUTPUT
- name: Download DEB packages
uses: actions/download-artifact@v4
with:
name: deb-package
path: ./apt-repo/pool/main/s/shelldock
- name: Setup APT repository tools
run: |
sudo apt-get update
sudo apt-get install -y dpkg-dev apt-utils gnupg2
- name: Import GPG key
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
if [ -z "$GPG_PRIVATE_KEY" ]; then
echo "GPG_PRIVATE_KEY not set, skipping GPG signing"
exit 0
fi
echo "$GPG_PRIVATE_KEY" | gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" --import
gpg --list-secret-keys --keyid-format LONG
continue-on-error: true
- name: Create APT repository structure
run: |
mkdir -p apt-repo/dists/stable/main/binary-amd64
mkdir -p apt-repo/dists/stable/main/binary-arm64
# Move .deb files to pool
find apt-repo/pool -name "*.deb" -exec mv {} apt-repo/pool/main/s/shelldock/ \;
# Generate Packages file for amd64
cd apt-repo
dpkg-scanpackages --arch amd64 pool/main > dists/stable/main/binary-amd64/Packages 2>/dev/null || true
gzip -k dists/stable/main/binary-amd64/Packages
# Generate Packages file for arm64 (if available)
dpkg-scanpackages --arch arm64 pool/main > dists/stable/main/binary-arm64/Packages 2>/dev/null || true
gzip -k dists/stable/main/binary-arm64/Packages 2>/dev/null || true
- name: Generate Release file
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
if [ -z "$GPG_PRIVATE_KEY" ]; then
echo "GPG_PRIVATE_KEY not set, creating unsigned Release"
cd apt-repo/dists/stable
cat > Release << EOF
Origin: ShellDock
Label: ShellDock
Suite: stable
Codename: stable
Version: ${{ steps.version.outputs.version }}
Architectures: amd64 arm64
Components: main
Description: ShellDock APT Repository
EOF
exit 0
fi
cd apt-repo/dists/stable
cat > Release << EOF
Origin: ShellDock
Label: ShellDock
Suite: stable
Codename: stable
Version: ${{ steps.version.outputs.version }}
Architectures: amd64 arm64
Components: main
Description: ShellDock APT Repository
EOF
# Add file hashes
find main -type f | while read file; do
echo " $(md5sum "$file" | cut -d' ' -f1) $(stat -c%s "$file") $file" >> Release
echo " $(sha256sum "$file" | cut -d' ' -f1) $(stat -c%s "$file") $file" >> Release
done
- name: Sign Release file
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
if [ -z "$GPG_PRIVATE_KEY" ]; then
echo "GPG_PRIVATE_KEY not set, skipping signing"
exit 0
fi
cd apt-repo/dists/stable
echo "$GPG_PASSPHRASE" | gpg --batch --yes --pinentry-mode loopback --passphrase-fd 0 --clearsign -o InRelease Release
echo "$GPG_PASSPHRASE" | gpg --batch --yes --pinentry-mode loopback --passphrase-fd 0 --detach-sign -o Release.gpg Release
continue-on-error: true
- name: Export GPG public key
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
if [ -z "$GPG_PRIVATE_KEY" ]; then
echo "GPG_PRIVATE_KEY not set, skipping key export"
exit 0
fi
mkdir -p apt-repo
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" --export --armor > apt-repo/gpg.key || true
continue-on-error: true
- name: Upload APT repository
uses: actions/upload-artifact@v4
with:
name: apt-repository
path: apt-repo/
snap:
name: Build and Publish Snap
needs: [test, build]
runs-on: ubuntu-latest
if: ${{ vars.SKIP_SNAP != 'true' && (needs.test.result == 'success' && needs.build.result == 'success') }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Extract version
id: version
run: |
if [ "${{ github.ref_type }}" = "tag" ]; then
VERSION="${{ github.ref_name }}"
else
VERSION="v${{ github.event.inputs.version }}"
fi
echo "version=${VERSION#v}" >> $GITHUB_OUTPUT
- name: Download Linux binary
uses: actions/download-artifact@v4
with:
name: shelldock-linux-amd64
path: ./
- name: Make binary executable
run: chmod +x shelldock-linux-amd64
- name: Setup Snapcraft
run: |
sudo snap install snapcraft --classic
- name: Create snapcraft.yaml
run: |
mkdir -p snap
sed "s/VERSION_PLACEHOLDER/${{ steps.version.outputs.version }}/g" \
packaging/snap/snapcraft.yaml.template > snap/snapcraft.yaml
echo "Generated snapcraft.yaml:"
cat snap/snapcraft.yaml
# Verify repository directory exists for snap
if [ ! -d "repository" ]; then
echo "⚠️ Warning: repository directory not found"
else
echo "✅ Repository directory found, will be included in snap"
fi
- name: Build snap
run: |
sudo snap install core22
snapcraft --destructive-mode
- name: Publish to Snap Store
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_CREDENTIALS }}
run: |
chmod +x scripts/publish-snap.sh
./scripts/publish-snap.sh
continue-on-error: true
- name: Upload snap artifact
uses: actions/upload-artifact@v4
with:
name: snap-package
path: "*.snap"
flatpak:
name: Build Flatpak Package
needs: [test, build]
runs-on: ubuntu-latest
if: ${{ vars.SKIP_FLATPAK != 'true' && (needs.test.result == 'success' && needs.build.result == 'success') }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Extract version
id: version
run: |
if [ "${{ github.ref_type }}" = "tag" ]; then
VERSION="${{ github.ref_name }}"
else
VERSION="v${{ github.event.inputs.version }}"
fi
echo "version=${VERSION#v}" >> $GITHUB_OUTPUT
- name: Download Linux binary
uses: actions/download-artifact@v4
with:
name: shelldock-linux-amd64
path: ./
- name: Setup Flatpak
run: |
sudo apt-get update
sudo apt-get install -y flatpak flatpak-builder
sudo flatpak remote-add --if-not-exists --system flathub https://flathub.org/repo/flathub.flatpakrepo
sudo flatpak install -y --system flathub org.freedesktop.Platform//22.08 org.freedesktop.Sdk//22.08
- name: Create flatpak manifest
run: |
mkdir -p flatpak
cp shelldock-linux-amd64 flatpak/
# Copy repository with all subdirectories to flatpak directory
# flatpak-builder looks for sources relative to the manifest file location
cp -r repository flatpak/ 2>/dev/null || (echo "Warning: repository directory not found" && mkdir -p flatpak/repository)
cp packaging/flatpak/com.github.opsguild.shelldock.yml flatpak/
# Verify repository was copied
if [ -d "flatpak/repository" ]; then
echo "✅ Repository directory copied to flatpak/"
ls -la flatpak/repository/ | head -10
else
echo "⚠️ Warning: Repository directory not found in flatpak/"
fi
- name: Build flatpak
run: |
flatpak-builder --force-clean build flatpak/com.github.opsguild.shelldock.yml --repo=repo
flatpak build-bundle repo shelldock-${{ steps.version.outputs.version }}.flatpak com.github.opsguild.shelldock
- name: Publish to Flathub (if configured)
env:
FLATHUB_SSH_KEY: ${{ secrets.FLATHUB_SSH_KEY }}
run: |
if [ -z "$FLATHUB_SSH_KEY" ]; then
echo "FLATHUB_SSH_KEY not set, skipping Flathub publish"
exit 0
fi
# Setup SSH
mkdir -p ~/.ssh
echo "$FLATHUB_SSH_KEY" > ~/.ssh/flathub_key
chmod 600 ~/.ssh/flathub_key
ssh-keyscan github.com >> ~/.ssh/known_hosts
# Clone Flathub repository
git clone git@github.com:flathub/com.github.opsguild.shelldock.git flathub-repo || \
git clone https://github.com/flathub/com.github.opsguild.shelldock.git flathub-repo || \
echo "Flathub repository not found. You may need to submit to Flathub first."
if [ -d flathub-repo ]; then
cd flathub-repo
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
# Update manifest with new version
FLATPAK_FILE=$(ls ../*.flatpak | head -1)
# Extract and update version in manifest if needed
# This is a simplified version - you may need to adjust based on your Flathub manifest structure
git add .
git diff --staged --quiet || git commit -m "Update to ${{ github.ref_name }}"
git push origin master || git push origin main || echo "Push failed"
fi
continue-on-error: true
- name: Upload flatpak
uses: actions/upload-artifact@v4
with:
name: flatpak-package
path: "*.flatpak"
homebrew:
name: Update Homebrew Formula
needs: [test, build]
runs-on: ubuntu-latest
if: ${{ vars.SKIP_HOMEBREW != 'true' && (needs.test.result == 'success' && needs.build.result == 'success') && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version
id: version
run: |
VERSION="${{ github.ref_name }}"
echo "version=${VERSION#v}" >> $GITHUB_OUTPUT
- name: Download macOS binaries
uses: actions/download-artifact@v4
with:
name: shelldock-darwin-amd64
path: ./build/
continue-on-error: true
- name: Download macOS ARM64 binary
uses: actions/download-artifact@v4
with:
name: shelldock-darwin-arm64
path: ./build/
continue-on-error: true
- name: Calculate SHA256 for amd64
id: sha256_amd64
run: |
if [ -f build/shelldock-darwin-amd64 ]; then
SHA256=$(sha256sum build/shelldock-darwin-amd64 | cut -d' ' -f1)
echo "sha256=$SHA256" >> $GITHUB_OUTPUT
fi
- name: Calculate SHA256 for arm64
id: sha256_arm64
run: |
if [ -f build/shelldock-darwin-arm64 ]; then
SHA256=$(sha256sum build/shelldock-darwin-arm64 | cut -d' ' -f1)
echo "sha256=$SHA256" >> $GITHUB_OUTPUT
fi
- name: Create Homebrew formula
run: |
mkdir -p Formula
cat > Formula/shelldock.rb << EOF
class Shelldock < Formula
desc "A fast, cross-platform shell command repository manager"
homepage "https://github.com/OpsGuild/ShellDock"
url "https://github.com/OpsGuild/ShellDock/archive/${{ github.ref_name }}.tar.gz"
version "${{ steps.version.outputs.version }}"
sha256 "${{ steps.sha256_amd64.outputs.sha256 }}"
on_macos do
if Hardware::CPU.intel?
url "https://github.com/OpsGuild/ShellDock/releases/download/${{ github.ref_name }}/shelldock-darwin-amd64"
sha256 "${{ steps.sha256_amd64.outputs.sha256 }}"
else
url "https://github.com/OpsGuild/ShellDock/releases/download/${{ github.ref_name }}/shelldock-darwin-arm64"
sha256 "${{ steps.sha256_arm64.outputs.sha256 }}"
end
end
def install
if OS.mac?
bin.install "shelldock-darwin-#{Hardware::CPU.arch == "arm64" ? "arm64" : "amd64"}" => "shelldock"
end
end
test do
system "#{bin}/shelldock", "--version"
end
end
EOF
- name: Push to Homebrew tap
env:
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
run: |
set +x # Prevent token from being logged
if [ -z "$HOMEBREW_TAP_TOKEN" ]; then
echo "HOMEBREW_TAP_TOKEN not set, skipping tap push"
echo "To enable Homebrew tap, create https://github.com/OpsGuild/homebrew-tap and add HOMEBREW_TAP_TOKEN"
exit 0
fi
# Verify token format (fine-grained tokens start with github_pat_)
if [[ "$HOMEBREW_TAP_TOKEN" != github_pat_* ]]; then
echo "⚠️ Warning: Token doesn't appear to be a fine-grained token (should start with 'github_pat_')"
echo "If using a classic token, ensure it has 'repo' scope"
fi
# Clone tap repository with token
echo "Cloning homebrew-tap repository..."
if ! git clone https://${HOMEBREW_TAP_TOKEN}@github.com/OpsGuild/homebrew-tap.git homebrew-tap; then
echo "❌ Failed to clone homebrew-tap repository"
echo "Verify:"
echo " 1. Repository exists at https://github.com/OpsGuild/homebrew-tap"
echo " 2. Token has 'Contents: Read and write' permission for the repository"
echo " 3. If organization has SSO, token must be authorized for SSO"
exit 1
fi
cd homebrew-tap
# Determine the default branch
DEFAULT_BRANCH=$(git remote show origin | grep "HEAD branch" | awk '{print $3}' || echo "main")
echo "Using branch: $DEFAULT_BRANCH"
# Checkout the default branch
git checkout $DEFAULT_BRANCH 2>/dev/null || git checkout -b $DEFAULT_BRANCH
# Update remote URL to include token for push operations
git remote set-url origin https://${HOMEBREW_TAP_TOKEN}@github.com/OpsGuild/homebrew-tap.git
# Copy formula
mkdir -p Formula
cp ../Formula/shelldock.rb Formula/
# Commit and push
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Formula/shelldock.rb
if ! git diff --staged --quiet; then
git commit -m "Update shelldock to ${{ github.ref_name }}"
echo "Pushing to homebrew-tap..."
# Push with token explicitly in URL
if ! git push https://${HOMEBREW_TAP_TOKEN}@github.com/OpsGuild/homebrew-tap.git refs/heads/$DEFAULT_BRANCH:refs/heads/$DEFAULT_BRANCH; then
echo "❌ Failed to push to homebrew-tap"
echo "Verify:"
echo " 1. Token has 'Contents: Read and write' permission"
echo " 2. Token is authorized for SSO (if organization uses SSO)"
echo " 3. Repository exists and is accessible"
exit 1
fi
echo "✅ Successfully pushed to homebrew-tap"
else
echo "No changes to commit"
fi
continue-on-error: true
chocolatey:
name: Build and Publish Chocolatey Package
needs: [test, build]
runs-on: windows-latest
if: ${{ vars.SKIP_CHOCOLATEY != 'true' && (needs.test.result == 'success' && needs.build.result == 'success') }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Extract version
id: version
run: |
if ("${{ github.ref_type }}" -eq "tag") {
$VERSION = "${{ github.ref_name }}"
} else {
$VERSION = "v${{ github.event.inputs.version }}"
}
# Remove 'v' prefix if present
$VERSION_NUM = $VERSION -replace '^v', ''
Write-Host "Extracted version: $VERSION_NUM from $VERSION"
echo "version=$VERSION_NUM" >> $env:GITHUB_OUTPUT
- name: Download Windows binary
uses: actions/download-artifact@v4
with:
name: shelldock-windows-amd64.exe
path: ./
- name: Create Chocolatey package
shell: pwsh
run: |
mkdir -p chocolatey\shelldock\tools
Move-Item shelldock-windows-amd64.exe chocolatey\shelldock\tools\shelldock.exe
# Copy repository with all subdirectories
if (Test-Path "repository") {
New-Item -ItemType Directory -Path "chocolatey\shelldock\tools\repository" -Force | Out-Null
Copy-Item -Path "repository\*" -Destination "chocolatey\shelldock\tools\repository\" -Recurse -Force
Write-Host "✅ Repository files copied to Chocolatey package"
} else {
Write-Warning "Repository directory not found"
}
# Copy icon if it exists
if (Test-Path "static\images\icon.jpg") {
Copy-Item "static\images\icon.jpg" "chocolatey\shelldock\tools\icon.jpg"
}
# Copy LICENSE.txt from root LICENSE file
if (Test-Path "LICENSE") {
Copy-Item "LICENSE" "chocolatey\shelldock\tools\LICENSE.txt"
} else {
Write-Warning "LICENSE file not found, creating default MIT license"
"MIT License`n`nCopyright (c) 2024 OpsGuild" | Out-File -Encoding UTF8 chocolatey\shelldock\tools\LICENSE.txt
}
# Copy VERIFICATION.txt from packaging directory
if (Test-Path "packaging\chocolatey\VERIFICATION.txt") {
Copy-Item "packaging\chocolatey\VERIFICATION.txt" "chocolatey\shelldock\tools\VERIFICATION.txt"
} else {
Write-Warning "VERIFICATION.txt not found, creating default"
"VERIFICATION`n`nThe software is open source and available at:`nhttps://github.com/OpsGuild/ShellDock" | Out-File -Encoding UTF8 chocolatey\shelldock\tools\VERIFICATION.txt
}
# Copy chocolateyUninstall.ps1 from packaging directory
if (Test-Path "packaging\chocolatey\chocolateyUninstall.ps1") {
Copy-Item "packaging\chocolatey\chocolateyUninstall.ps1" "chocolatey\shelldock\tools\chocolateyUninstall.ps1"
} else {
Write-Warning "chocolateyUninstall.ps1 not found"
}
# Copy chocolateyInstall.ps1 from packaging directory
if (Test-Path "packaging\chocolatey\chocolateyInstall.ps1") {
Copy-Item "packaging\chocolatey\chocolateyInstall.ps1" "chocolatey\shelldock\tools\chocolateyinstall.ps1"
} else {
Write-Warning "chocolateyInstall.ps1 not found"
}
# Create nuspec with dynamic version from template
$VERSION = "${{ steps.version.outputs.version }}"
$nuspec = Get-Content "packaging\chocolatey\shelldock.nuspec.template" -Raw -ErrorAction SilentlyContinue
if (-not $nuspec) {
Write-Error "nuspec template not found at packaging\chocolatey\shelldock.nuspec.template"
exit 1
}
$nuspec = $nuspec -replace 'VERSION_PLACEHOLDER', $VERSION
$nuspec | Out-File -Encoding UTF8 chocolatey\shelldock\shelldock.nuspec
- name: Install Chocolatey
run: |
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
- name: Build Chocolatey package
run: |
choco pack chocolatey\shelldock\shelldock.nuspec --output-directory chocolatey
- name: Set Chocolatey API key
env:
CHOCOLATEY_API_KEY: ${{ secrets.CHOCOLATEY_API_KEY }}
shell: pwsh
run: |
if ([string]::IsNullOrEmpty($env:CHOCOLATEY_API_KEY)) {
Write-Host "CHOCOLATEY_API_KEY not set, skipping API key setup"
exit 0
}
choco apikey --key "$env:CHOCOLATEY_API_KEY" --source https://push.chocolatey.org/
- name: Publish to Chocolatey
env:
CHOCOLATEY_API_KEY: ${{ secrets.CHOCOLATEY_API_KEY }}
shell: pwsh
run: |
if ([string]::IsNullOrEmpty($env:CHOCOLATEY_API_KEY)) {
Write-Host "CHOCOLATEY_API_KEY not set, skipping publish"
exit 0
}
$package = Get-ChildItem chocolatey\*.nupkg | Select-Object -First 1
choco push $package.FullName --source https://push.chocolatey.org/ --force
continue-on-error: true
- name: Upload Chocolatey package
uses: actions/upload-artifact@v4
with:
name: chocolatey-package
path: "chocolatey/*.nupkg"
aur:
name: Update AUR Package
needs: [test, build]
runs-on: ubuntu-latest
if: ${{ vars.SKIP_AUR != 'true' && (needs.test.result == 'success' && needs.build.result == 'success') && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Extract version
id: version
run: |
VERSION="${{ github.ref_name }}"
echo "version=${VERSION#v}" >> $GITHUB_OUTPUT
- name: Download Linux binary
uses: actions/download-artifact@v4
with:
name: shelldock-linux-amd64
path: ./
- name: Calculate SHA256
id: sha256
run: |
SHA256=$(sha256sum shelldock-linux-amd64 | cut -d' ' -f1)
echo "sha256=$SHA256" >> $GITHUB_OUTPUT
- name: Update PKGBUILD
run: |
# Generate PKGBUILD from template
sed -e "s/VERSION_PLACEHOLDER/${{ steps.version.outputs.version }}/g" \
-e "s/SHA256_PLACEHOLDER/${{ steps.sha256.outputs.sha256 }}/g" \
packaging/arch/PKGBUILD.template > packaging/arch/PKGBUILD
echo "Generated PKGBUILD:"
cat packaging/arch/PKGBUILD
- name: Generate .SRCINFO
run: |
chmod +x scripts/generate-srcinfo.sh
./scripts/generate-srcinfo.sh "${{ steps.version.outputs.version }}" "${{ steps.sha256.outputs.sha256 }}"
- name: Publish to AUR
env:
AUR_SSH_KEY: ${{ secrets.AUR_SSH_KEY }}
run: |
chmod +x scripts/publish-aur.sh
./scripts/publish-aur.sh "${{ steps.version.outputs.version }}"
continue-on-error: true
- name: Upload PKGBUILD
uses: actions/upload-artifact@v4
with:
name: aur-package
path: packaging/arch/PKGBUILD
gpg-sign:
name: GPG Sign Packages
needs: [build, packages, snap, flatpak, chocolatey]
runs-on: ubuntu-latest
if: always() && needs.build.result == 'success'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Import GPG key
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
if [ -z "$GPG_PRIVATE_KEY" ]; then
echo "GPG_PRIVATE_KEY not set, skipping GPG signing"
exit 0
fi
echo "$GPG_PRIVATE_KEY" | gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" --import
gpg --list-secret-keys --keyid-format LONG
continue-on-error: true
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: ./artifacts
- name: Sign binaries
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
if [ -z "$GPG_PRIVATE_KEY" ]; then
echo "GPG_PRIVATE_KEY not set, skipping signing"
exit 0
fi
for file in $(find artifacts -type f \( -name "shelldock-*" -o -name "*.deb" -o -name "*.rpm" -o -name "*.snap" -o -name "*.flatpak" -o -name "*.nupkg" \)); do
echo "$GPG_PASSPHRASE" | gpg --batch --yes --pinentry-mode loopback --passphrase-fd 0 --detach-sign --armor "$file"
done
continue-on-error: true
- name: Upload signatures
uses: actions/upload-artifact@v4
with:
name: gpg-signatures
path: "artifacts/*.asc"
release:
name: Create Release
needs: [test, build, packages, snap, flatpak, chocolatey, homebrew, aur, gpg-sign, apt-repo]
runs-on: ubuntu-latest
if: always() && needs.test.result == 'success' && needs.build.result == 'success'
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Extract version
id: version
run: |
if [ "${{ github.ref_type }}" = "tag" ]; then
VERSION="${{ github.ref_name }}"
else
VERSION="v${{ github.event.inputs.version }}"
fi
echo "version=${VERSION#v}" >> $GITHUB_OUTPUT
echo "VERSION=${VERSION}" >> $GITHUB_ENV
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: ./release-assets
- name: Prepare release files
run: |
# Create a clean release directory
mkdir -p release-files
# Copy unique files (avoid duplicates)
find release-assets -name "*.deb" -type f | head -1 | xargs -I {} cp {} release-files/ 2>/dev/null || true
find release-assets -name "*.rpm" -type f | head -1 | xargs -I {} cp {} release-files/ 2>/dev/null || true
find release-assets -name "*.snap" -type f | head -1 | xargs -I {} cp {} release-files/ 2>/dev/null || true
find release-assets -name "*.flatpak" -type f | head -1 | xargs -I {} cp {} release-files/ 2>/dev/null || true
find release-assets -name "*.nupkg" -type f | head -1 | xargs -I {} cp {} release-files/ 2>/dev/null || true
find release-assets -name "*.exe" -type f | head -1 | xargs -I {} cp {} release-files/ 2>/dev/null || true
find release-assets -name "PKGBUILD" -type f | head -1 | xargs -I {} cp {} release-files/ 2>/dev/null || true
# Copy binaries (shelldock-* but not .deb/.rpm/etc)
find release-assets -name "shelldock-*" -type f ! -name "*.deb" ! -name "*.rpm" ! -name "*.snap" ! -name "*.flatpak" ! -name "*.nupkg" ! -name "*.exe" -exec cp {} release-files/ \; 2>/dev/null || true
# Extract GPG key if it exists
if [ -f release-assets/apt-repository/apt-repo/gpg.key ]; then
cp release-assets/apt-repository/apt-repo/gpg.key release-files/gpg.key
fi
# List files to be uploaded
echo "Files to upload:"
ls -lh release-files/ || true
- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: release-files/*
draft: false
prerelease: false
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}