Skip to content

feat(static/images): Add icon.jpg and logo.jpg. #27

feat(static/images): Add icon.jpg and logo.jpg.

feat(static/images): Add icon.jpg and logo.jpg. #27

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: Build binary (Windows)
if: matrix.os == 'windows-latest'
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
VERSION_NUM: ${{ steps.version-windows.outputs.version }}
shell: pwsh
run: |
go build -ldflags "-X main.version=$env:VERSION_NUM" -o ${{ 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/
cp repository/*.yaml 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}/
mkdir -p dist/rpm/tmp/shelldock-${VERSION}/repository
cp repository/*.yaml 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 Snap Package
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
cat > snap/snapcraft.yaml << 'EOF'
name: shelldock
base: core22
version: '${{ steps.version.outputs.version }}'
summary: A fast, cross-platform shell command repository manager
description: |
ShellDock is a fast, cross-platform tool for managing and executing
saved shell commands from bundled repository or local directory.
grade: stable
confinement: strict
title: ShellDock
license: MIT
contact: https://github.com/OpsGuild/ShellDock
website: https://github.com/OpsGuild/ShellDock
source-code: https://github.com/OpsGuild/ShellDock
apps:
shelldock:
command: usr/bin/shelldock
plugs:
- home
- network
parts:
shelldock:
plugin: dump
source: .
organize:
shelldock-linux-amd64: usr/bin/shelldock
EOF
- name: Build snap
run: |
sudo snap install core22
snapcraft --destructive-mode
- name: Login to Snap Store
env:
SNAP_STORE_CREDENTIALS_B64: ${{ secrets.SNAP_STORE_CREDENTIALS }}
run: |
set +x # Prevent command echoing to avoid exposing credentials
if [ -z "$SNAP_STORE_CREDENTIALS_B64" ]; then
echo "SNAP_STORE_CREDENTIALS not set, skipping Snap Store login"
exit 0
fi
# Decode base64 credentials to temp file
CREDS_FILE=$(mktemp)
echo "$SNAP_STORE_CREDENTIALS_B64" | base64 -d > "$CREDS_FILE" 2>/dev/null
# Unset SNAPCRAFT_STORE_CREDENTIALS before login (snapcraft doesn't allow it set during login)
unset SNAPCRAFT_STORE_CREDENTIALS
# Login using the credentials file directly
snapcraft login --with "$CREDS_FILE" || echo "Login failed or already logged in"
# Securely remove temp file
shred -u "$CREDS_FILE" 2>/dev/null || rm -f "$CREDS_FILE"
continue-on-error: true
- name: Register snap name (if not already registered)
env:
SNAP_STORE_CREDENTIALS_B64: ${{ secrets.SNAP_STORE_CREDENTIALS }}
run: |
set +x # Prevent command echoing
if [ -z "$SNAP_STORE_CREDENTIALS_B64" ]; then
echo "SNAP_STORE_CREDENTIALS not set, skipping registration"
exit 0
fi
# Decode credentials to temp file
CREDS_FILE=$(mktemp)
echo "$SNAP_STORE_CREDENTIALS_B64" | base64 -d > "$CREDS_FILE" 2>/dev/null
# Unset env var and use file for login
unset SNAPCRAFT_STORE_CREDENTIALS
snapcraft login --with "$CREDS_FILE" || echo "Already logged in"
snapcraft register shelldock || echo "Snap name already registered or registration failed"
shred -u "$CREDS_FILE" 2>/dev/null || rm -f "$CREDS_FILE"
continue-on-error: true
- name: Publish to Snap Store
env:
SNAP_STORE_CREDENTIALS_B64: ${{ secrets.SNAP_STORE_CREDENTIALS }}
run: |
set +x # Prevent command echoing to avoid exposing credentials
if [ -z "$SNAP_STORE_CREDENTIALS_B64" ]; then
echo "SNAP_STORE_CREDENTIALS not set, skipping publish"
exit 0
fi
# Decode credentials to temp file
CREDS_FILE=$(mktemp)
echo "$SNAP_STORE_CREDENTIALS_B64" | base64 -d > "$CREDS_FILE" 2>/dev/null
# Unset env var before login (required by snapcraft)
unset SNAPCRAFT_STORE_CREDENTIALS
# Login using credentials file
snapcraft login --with "$CREDS_FILE" || echo "Login failed or already logged in"
SNAP_FILE=$(ls *.snap | head -1)
if [ -n "$SNAP_FILE" ]; then
snapcraft upload "$SNAP_FILE" --release stable || echo "Publish failed (may already be published)"
else
echo "No snap file found to upload"
fi
# Securely remove temp file
shred -u "$CREDS_FILE" 2>/dev/null || rm -f "$CREDS_FILE"
continue-on-error: true
- name: Upload snap
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/
cat > flatpak/com.github.opsguild.shelldock.yml << 'EOF'
app-id: com.github.opsguild.shelldock
runtime: org.freedesktop.Platform
runtime-version: '22.08'
sdk: org.freedesktop.Sdk
command: shelldock
finish-args:
- --share=network
- --filesystem=home
modules:
- name: shelldock
buildsystem: simple
build-commands:
- install -Dm755 shelldock-linux-amd64 /app/bin/shelldock
sources:
- type: file
path: shelldock-linux-amd64
EOF
- 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: Commit and push formula to main repo
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Formula/shelldock.rb
git diff --staged --quiet || git commit -m "Update Homebrew formula to ${{ github.ref_name }}"
git push origin HEAD:main || git push origin HEAD:master
- name: Push to Homebrew tap (if repository exists)
env:
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
run: |
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
# Clone tap repository
git clone https://${HOMEBREW_TAP_TOKEN}@github.com/OpsGuild/homebrew-tap.git homebrew-tap || {
echo "Homebrew tap repository not found. Create it at https://github.com/OpsGuild/homebrew-tap"
exit 0
}
cd homebrew-tap
# 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
git diff --staged --quiet || git commit -m "Update shelldock to ${{ github.ref_name }}"
git push origin main || git push origin master
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
run: |
mkdir -p chocolatey\shelldock\tools
Move-Item shelldock-windows-amd64.exe chocolatey\shelldock\tools\shelldock.exe
# Copy icon if it exists
if (Test-Path "static\images\icon.jpg") {
Copy-Item "static\images\icon.jpg" "chocolatey\shelldock\tools\icon.jpg"
}
# Create LICENSE.txt (MIT License)
$license = @"
MIT License

Check failure on line 760 in .github/workflows/release.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/release.yml

Invalid workflow file

You have an error in your yaml syntax on line 760
Copyright (c) 2024 OpsGuild
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
For the latest license information, visit:
https://github.com/OpsGuild/ShellDock/blob/master/LICENSE
"@
$license | Out-File -Encoding UTF8 chocolatey\shelldock\tools\LICENSE.txt
# Create VERIFICATION.txt
$verification = @"
VERIFICATION
Verification is intended to assist the Chocolatey moderators and community
in verifying that this package's contents are trustworthy.
The software is open source and available at:
https://github.com/OpsGuild/ShellDock
The source code repository is:
https://github.com/OpsGuild/ShellDock
The binary is built from source and published to GitHub Releases:
https://github.com/OpsGuild/ShellDock/releases
You can verify the binary by:
1. Checking the GitHub Releases page for the version
2. Comparing the SHA256 hash with the release notes
3. Reviewing the source code at the repository URL above
The maintainer of this package is the same as the software author (OpsGuild).
"@
$verification | Out-File -Encoding UTF8 chocolatey\shelldock\tools\VERIFICATION.txt
# Create chocolateyUninstall.ps1
$uninstall = @"
`$ErrorActionPreference = 'Stop'
`$toolsDir = "`$(Split-Path -parent `$MyInvocation.MyCommand.Definition)"
Remove-BinFile -Name shelldock
"@
$uninstall | Out-File -Encoding UTF8 chocolatey\shelldock\tools\chocolateyUninstall.ps1
# Create nuspec with all required fields
$nuspec = @"
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
<metadata>
<id>shelldock</id>
<version>${{ steps.version.outputs.version }}</version>
<title>ShellDock</title>
<authors>OpsGuild</authors>
<owners>OpsGuild</owners>
<summary>A fast, cross-platform shell command repository manager. Save, organize, and execute shell commands from bundled repository or local directory with platform-specific support and versioning.</summary>
<description>A fast, cross-platform shell command repository manager. Save, organize, and execute shell commands from bundled repository or local directory with platform-specific support and versioning.</description>
<projectUrl>https://github.com/OpsGuild/ShellDock</projectUrl>
<packageSourceUrl>https://github.com/OpsGuild/ShellDock</packageSourceUrl>
<licenseUrl>https://github.com/OpsGuild/ShellDock/blob/master/LICENSE</licenseUrl>
<releaseNotes>https://github.com/OpsGuild/ShellDock/releases</releaseNotes>
<docsUrl>https://github.com/OpsGuild/ShellDock/blob/master/README.md</docsUrl>
<bugTrackerUrl>https://github.com/OpsGuild/ShellDock/issues</bugTrackerUrl>
<projectSourceUrl>https://github.com/OpsGuild/ShellDock</projectSourceUrl>
<iconUrl>https://raw.githubusercontent.com/OpsGuild/ShellDock/master/static/images/icon.jpg</iconUrl>
<tags>shell commands automation cli tool</tags>
</metadata>
<files>
<file src="tools\**" target="tools" />
<file src="tools\icon.jpg" target="tools" />
</files>
</package>
"@
$nuspec | Out-File -Encoding UTF8 chocolatey\shelldock\shelldock.nuspec
# Create chocolateyInstall.ps1
$install = @"
`$ErrorActionPreference = 'Stop'
`$toolsDir = "`$(Split-Path -parent `$MyInvocation.MyCommand.Definition)"
Install-BinFile -Name shelldock -Path "`$toolsDir\shelldock.exe"
"@
$install | Out-File -Encoding UTF8 chocolatey\shelldock\tools\chocolateyinstall.ps1
- 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: |
cat > packaging/arch/PKGBUILD << EOF
# Maintainer: OpsGuild
pkgname=shelldock
pkgver=${{ steps.version.outputs.version }}
pkgrel=1
pkgdesc="A fast, cross-platform shell command repository manager"
arch=('x86_64' 'aarch64')
url="https://github.com/OpsGuild/ShellDock"
license=('MIT')
source_x86_64=("https://github.com/OpsGuild/ShellDock/releases/download/${{ github.ref_name }}/shelldock-linux-amd64")
source_aarch64=("https://github.com/OpsGuild/ShellDock/releases/download/${{ github.ref_name }}/shelldock-linux-arm64")
sha256sums_x86_64=('${{ steps.sha256.outputs.sha256 }}')
sha256sums_aarch64=('SKIP')
package() {
install -Dm755 "\${srcdir}/shelldock-linux-\${CARCH}" "\${pkgdir}/usr/bin/shelldock"
install -Dm644 "\${srcdir}/README.md" "\${pkgdir}/usr/share/doc/shelldock/README.md"
install -d "\${pkgdir}/usr/share/shelldock/repository"
cp "\${srcdir}/repository"/*.yaml "\${pkgdir}/usr/share/shelldock/repository/" 2>/dev/null || true
}
EOF
- name: Generate .SRCINFO
run: |
cd packaging/arch
# Use Docker with Arch Linux to generate .SRCINFO properly
docker run --rm -v "$(pwd):/pkg" -w /pkg archlinux/base:latest bash -c "
pacman -Sy --noconfirm base-devel
makepkg --printsrcinfo > .SRCINFO
" || {
# Fallback: Generate .SRCINFO manually if Docker fails
source PKGBUILD
{
echo "pkgbase = $pkgname"
echo " pkgdesc = $pkgdesc"
echo " pkgver = $pkgver"
echo " pkgrel = $pkgrel"
echo " url = $url"
echo " arch = ${arch[@]}"
echo " license = ${license[@]}"
for i in "${!source_x86_64[@]}"; do
echo " source_x86_64 = ${source_x86_64[$i]}"
done
for i in "${!source_aarch64[@]}"; do
echo " source_aarch64 = ${source_aarch64[$i]}"
done
for i in "${!sha256sums_x86_64[@]}"; do
echo " sha256sums_x86_64 = ${sha256sums_x86_64[$i]}"
done
for i in "${!sha256sums_aarch64[@]}"; do
echo " sha256sums_aarch64 = ${sha256sums_aarch64[$i]}"
done
} > .SRCINFO
}
- name: Publish to AUR
env:
AUR_SSH_KEY: ${{ secrets.AUR_SSH_KEY }}
run: |
if [ -z "$AUR_SSH_KEY" ]; then
echo "AUR_SSH_KEY not set, skipping AUR publish"
exit 0
fi
# Setup SSH
mkdir -p ~/.ssh
echo "$AUR_SSH_KEY" > ~/.ssh/aur_key
chmod 600 ~/.ssh/aur_key
ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts
# Configure git
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
# Clone AUR repository
GIT_SSH_COMMAND="ssh -i ~/.ssh/aur_key" git clone ssh://aur@aur.archlinux.org/shelldock.git aur-repo || echo "AUR repo may not exist yet"
if [ -d aur-repo ]; then
cd aur-repo
# Copy PKGBUILD and .SRCINFO
cp ../packaging/arch/PKGBUILD .
cp ../packaging/arch/.SRCINFO .
# Commit and push
git add PKGBUILD .SRCINFO
git diff --staged --quiet || (git commit -m "Update to ${{ github.ref_name }}" && GIT_SSH_COMMAND="ssh -i ~/.ssh/aur_key" git push origin master)
fi
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 }}