Merge branch 'release/1.1.0' #29
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: build-and-release | |
env: | |
APP_NAME: "patrick" | |
MODULE: "github.com/acanewby/patrick" | |
APP_ID: "org.intellicon.patrick" | |
GO_VER: "1.20" | |
OS_MAC: "darwin" | |
OS_LINUX: "linux" | |
OS_WINDOWS: "windows" | |
ARCH_INTEL: "amd64" | |
ARCH_ARM: "arm64" | |
BUILD_DIR: "./dist" | |
PKG_DIR: "./pkg" | |
MACOS_INSTALL_DIR: "usr/local/bin" | |
LINUX_BUILD_PKGS: "zip" | |
on: | |
push: | |
tags: | |
- "*.*.*" | |
# Enable the clause below if you want to trigger the build on push to branch | |
# (but without a tag, there will not be a release) | |
# branches: | |
# - your-branch-here | |
jobs: | |
package: | |
strategy: | |
matrix: | |
platform: [macos-latest, ubuntu-latest] | |
runs-on: ${{ matrix.platform }} | |
outputs: | |
version: ${{ steps.version.outputs.version }} | |
revision: ${{ steps.version.outputs.revision }} | |
steps: | |
- uses: actions/checkout@v3 | |
with: | |
# we need the whole thing so we can count commits. | |
fetch-depth: '0' | |
- name: Install Go | |
uses: actions/setup-go@v4 | |
with: | |
go-version: ${{ env.GO_VER }} | |
- name: Inject Version Info | |
id: version | |
run: | | |
VERSION=$(git describe --abbrev=0 --tags $(git rev-list --tags --max-count=1) | tr -d v) | |
[ "$VERSION" != "" ] || VERSION=0.0.0 | |
REVISION=$(git rev-list --count --all || echo 0) | |
COMMIT=$(echo "${{github.sha}}" | head -c 7) | |
VERSION_LDFLAGS="-X \"golift.io/version.Branch=${{github.ref_name}} (${COMMIT})\" \ | |
-X \"golift.io/version.BuildDate=$(date -u +%Y-%m-%dT%H:%M:00Z)\" \ | |
-X \"golift.io/version.BuildUser=$(whoami || echo "unknown")\" \ | |
-X \"golift.io/version.Revision=${REVISION}\" \ | |
-X \"golift.io/version.Version=${VERSION}\" \ | |
-X \"${{ env.MODULE }}/cmd/${{ env.APP_NAME }}.version=${VERSION}\"" | |
echo "VERSION_LDFLAGS=${VERSION_LDFLAGS}" >> $GITHUB_ENV | |
echo "VERSION=${VERSION}" >> $GITHUB_ENV | |
echo "REVISION=${REVISION}" >> $GITHUB_ENV | |
echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
echo "revision=${REVISION}" >> $GITHUB_OUTPUT | |
- name: Build app (macOS) | |
if: matrix.platform == 'macos-latest' | |
run: | | |
echo "-----------------------" | |
echo "Build ${{ env.OS_MAC }}/${{ env.ARCH_INTEL }}" | |
echo "-----------------------" | |
env GOOS=${{ env.OS_MAC }} GOARCH=${{ env.ARCH_INTEL }} go build -o ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}-${{ env.ARCH_INTEL }} -ldflags='${{ env.VERSION_LDFLAGS }}' main.go | |
echo "-----------------------" | |
echo "Build ${{ env.OS_MAC }}/${{ env.ARCH_ARM }}" | |
echo "-----------------------" | |
env GOOS=${{ env.OS_MAC }} GOARCH=${{ env.ARCH_ARM }} go build -o ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}-${{ env.ARCH_ARM }} -ldflags='${{ env.VERSION_LDFLAGS }}' main.go | |
echo "-----------------------" | |
echo "Create universal binary" | |
echo "-----------------------" | |
lipo -create -output ${{ env.BUILD_DIR }}/${{ env.APP_NAME }} ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}-${{ env.ARCH_ARM }} ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}-${{ env.ARCH_INTEL }} | |
rm ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}-${{ env.ARCH_INTEL }} | |
rm ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}-${{ env.ARCH_ARM }} | |
- name: Create keychain (macOS) | |
if: matrix.platform == 'macos-latest' | |
# Extract the secrets we defined earlier as environment variables | |
env: | |
# These are for PKG (installer) signing | |
MACOS_CERTIFICATE: ${{ secrets.PROD_MACOS_CERTIFICATE }} | |
MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }} | |
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }} | |
# These are for APP (executable) signing | |
MACOS_CODE_CERTIFICATE: ${{ secrets.PROD_MACOS_CODE_CERTIFICATE }} | |
MACOS_CODE_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CODE_CERTIFICATE_PWD }} | |
MACOS_CODE_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CODE_CERTIFICATE_NAME }} | |
# This is to secure the keychain | |
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }} | |
run: | | |
echo "-----------------------" | |
echo "Environment" | |
echo "-----------------------" | |
echo "Cert: $MACOS_CERTIFICATE" | |
echo "Name: $MACOS_CERTIFICATE_NAME" | |
# Turn our base64-encoded certificates back to regular .p12 files | |
echo "-----------------------" | |
echo "Convert cert .base64 -> .p12" | |
echo "-----------------------" | |
echo $MACOS_CERTIFICATE | base64 --decode > installer-certificate.p12 | |
echo $MACOS_CODE_CERTIFICATE | base64 --decode > code-certificate.p12 | |
# We need to create a new keychain, otherwise using the certificate will prompt | |
# with a UI dialog asking for the certificate password, which we can't | |
# use in a headless CI environment | |
echo "-----------------------" | |
echo "Create keychain" | |
echo "-----------------------" | |
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain | |
security default-keychain -s build.keychain | |
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain | |
security import code-certificate.p12 -k build.keychain -P "$MACOS_CODE_CERTIFICATE_PWD" -T /usr/bin/codesign | |
security import installer-certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/productsign | |
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" build.keychain | |
- name: Codesign app and PKG (macOS) | |
if: matrix.platform == 'macos-latest' | |
# Extract the secrets we defined earlier as environment variables | |
env: | |
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }} | |
MACOS_CODE_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CODE_CERTIFICATE_NAME }} | |
run: | | |
echo "-----------------------" | |
echo "Sign app" | |
echo "-----------------------" | |
/usr/bin/codesign --timestamp --force -s "$MACOS_CODE_CERTIFICATE_NAME" --options runtime -v ${{ env.BUILD_DIR }}/${{ env.APP_NAME }} | |
echo "-----------------------" | |
echo "Create PKG structure" | |
echo "-----------------------" | |
mkdir -p ${{ env.PKG_DIR }}/${{ env.MACOS_INSTALL_DIR }} | |
cp ${{ env.BUILD_DIR }}/${{ env.APP_NAME }} ${{ env.PKG_DIR }}/${{ env.MACOS_INSTALL_DIR }} | |
find ${{ env.PKG_DIR }} | |
echo "-----------------------" | |
echo "Build PKG" | |
echo "-----------------------" | |
echo "Root: ${{ env.PKG_DIR }}" | |
echo "Id : ${{ env.APP_ID }}" | |
echo "Ver : ${{ env.VERSION }}" | |
echo "Sign: ${{ env.MACOS_CERTIFICATE_NAME }}" | |
echo "Pkg : ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}-${{ env.VERSION }}-unsigned.pkg" | |
/usr/bin/pkgbuild --root ${{ env.PKG_DIR }} --identifier ${{ env.APP_ID }} --version ${{ env.VERSION }} --install-location "/" ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}-${{ env.VERSION }}-${{ env.OS_MAC }}-unsigned.pkg | |
echo "-----------------------" | |
echo "Sign PKG" | |
echo "-----------------------" | |
echo "Pkg : ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}-${{ env.VERSION }}.pkg" | |
/usr/bin/productsign --timestamp --sign "$MACOS_CERTIFICATE_NAME" ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}-${{ env.VERSION }}-${{ env.OS_MAC }}-unsigned.pkg ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}-${{ env.VERSION }}-${{ env.OS_MAC }}.pkg | |
# Don't need the unsigned version any more | |
rm ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}-${{ env.VERSION }}-${{ env.OS_MAC }}-unsigned.pkg | |
- name: Notarize and staple PKG (macOS) | |
if: matrix.platform == 'macos-latest' | |
# Extract the secrets we defined earlier as environment variables | |
env: | |
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }} | |
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }} | |
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }} | |
run: | | |
# Store the notarization credentials so that we can prevent a UI password dialog | |
# from blocking the CI | |
echo "-----------------------" | |
echo "Create notary profile" | |
echo "-----------------------" | |
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD" | |
# Here we send the notarization request to the Apple's Notarization service, waiting for the result. | |
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App | |
# characteristics. Visit the Notarization docs for more information and strategies on how to optimize it if | |
# you're curious | |
echo "-----------------------" | |
echo "Notarize PKG" | |
echo "-----------------------" | |
xcrun notarytool submit ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}-${{ env.VERSION }}-${{ env.OS_MAC }}.pkg --keychain-profile "notarytool-profile" --wait | |
echo "-----------------------" | |
echo "Staple PKG" | |
echo "-----------------------" | |
xcrun stapler staple ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}-${{ env.VERSION }}-${{ env.OS_MAC }}.pkg | |
echo "-----------------------" | |
echo "Validate PKG" | |
echo "-----------------------" | |
/usr/sbin/spctl --assess -vv --type install ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}-${{ env.VERSION }}-${{ env.OS_MAC }}.pkg | |
- name: Build app (Windows and Linux) | |
if: matrix.platform == 'ubuntu-latest' | |
run: | | |
echo "-----------------------" | |
echo "General setup" | |
echo "-----------------------" | |
sudo apt update | |
sudo apt install -y ${{ env.LINUX_BUILD_PKGS }} | |
go mod vendor | |
echo "-----------------------" | |
echo "Build ${{ env.OS_LINUX }}" | |
echo "-----------------------" | |
env GOOS=${{ env.OS_LINUX }} GOARCH=${{ env.ARCH_INTEL }} go build -o ${{ env.BUILD_DIR }}/${{ env.APP_NAME }} -ldflags='${{ env.VERSION_LDFLAGS }}' main.go | |
echo "-----------------------" | |
echo "Build ${{ env.OS_WINDOWS }}" | |
echo "-----------------------" | |
env GOOS=${{ env.OS_WINDOWS }} GOARCH=${{ env.ARCH_INTEL }} go build -o ${{ env.BUILD_DIR }}/${{ env.APP_NAME }}.exe -ldflags='${{ env.VERSION_LDFLAGS }}' main.go | |
- name: Package app (Windows and Linux) | |
if: matrix.platform == 'ubuntu-latest' | |
run: | | |
pushd ${{ env.BUILD_DIR }} | |
echo "-----------------------" | |
echo "Package ${{ env.OS_LINUX }}" | |
echo "-----------------------" | |
tar -cvzf ./${{ env.APP_NAME }}-${{ env.VERSION }}-${{ env.OS_LINUX }}-${{ env.ARCH_INTEL }}.tar.gz ./${{ env.APP_NAME }} | |
echo "-----------------------" | |
echo "Build ${{ env.OS_WINDOWS }}" | |
echo "-----------------------" | |
zip -9j ./${{ env.APP_NAME }}-${{ env.VERSION }}-${{ env.OS_WINDOWS}}-${{ env.ARCH_INTEL }}.zip ./${{ env.APP_NAME }}.exe | |
popd | |
- name: List artifacts | |
run: find ${{ env.BUILD_DIR }} | |
- name: Upload Artifacts | |
uses: actions/upload-artifact@v3 | |
with: | |
name: ${{ env.APP_NAME }}-${{ matrix.platform }} | |
path: ${{ env.BUILD_DIR }}/* | |
deploy-github-release: | |
# description: uploads all the built release assets to the GitHub Release. | |
if: startsWith(github.ref, 'refs/tags/') | |
permissions: | |
contents: write | |
needs: package | |
strategy: | |
matrix: | |
# Can't use env vars here ... :( | |
files: [patrick-macos-latest, patrick-ubuntu-latest] | |
name: Deploy GitHub Release | |
runs-on: ubuntu-latest | |
steps: | |
- name: Download ${{ matrix.files }} Files | |
uses: actions/download-artifact@v3 | |
with: | |
name: ${{ matrix.files }} | |
- name: Publish ${{ matrix.files }} artifacts to github | |
uses: softprops/action-gh-release@v1 | |
with: | |
files: | | |
*.rpm | |
*.deb | |
*.zip | |
*.dmg | |
*.pkg | |
*.gz | |
*.txt |