From 2e8ad7449f7b8639d5c6ff92c02afdf21f884cee Mon Sep 17 00:00:00 2001 From: bikmazefe Date: Tue, 6 May 2025 15:38:09 +0300 Subject: [PATCH 1/3] feat(CLI): Add macOS binary signing using Apple Distribution certificate --- clients/cli/build/build.sh | 3 +++ clients/cli/build/sign.sh | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 clients/cli/build/sign.sh diff --git a/clients/cli/build/build.sh b/clients/cli/build/build.sh index eceb57ef3..c37682fed 100755 --- a/clients/cli/build/build.sh +++ b/clients/cli/build/build.sh @@ -15,6 +15,9 @@ cd $DIST_DIR tar --extract --file=build.tar rm -f build.tar + +./sign.sh $SIGNING_CERTIFICATE $CERTIFICATE_PASSWORD $SIGNING_IDENTITY $KEYCHAIN_PASSWORD $DIST_DIR + # Homebrew - binary must be called phrase, because the binary name inside # the tar will be made available system wide for name in phrase_macosx_amd64 phrase_macosx_arm64; do diff --git a/clients/cli/build/sign.sh b/clients/cli/build/sign.sh new file mode 100644 index 000000000..c4f4ac414 --- /dev/null +++ b/clients/cli/build/sign.sh @@ -0,0 +1,36 @@ +set -eo pipefail + +CERTIFICATE_BASE64=$1 +P12_PASSWORD=$2 +IDENTITY=$3 +KEYCHAIN_PASSWORD=$4 +DIST_DIR=$5 + +CERTIFICATE_PATH="./build_certificate.p12" +KEYCHAIN_PATH="./my-signing.keychain-db" + +echo "🔐 Setting up certificate and keychain..." + +# Decode the certificate +echo "$CERTIFICATE_BASE64" | base64 --decode -o "$CERTIFICATE_PATH" + +# Create temporary keychain +security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" +security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" +security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" + +# Import certificate into keychain +security import "$CERTIFICATE_PATH" -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH" +security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" +security list-keychain -d user -s "$KEYCHAIN_PATH" + +# Find and sign all macOS binaries dynamically +echo "🔎 Searching for macOS binaries in $DIST_DIR..." + +find "$DIST_DIR" -type f \( -name "phrase_macosx_*" ! -name "*.tar.gz" \) | while read -r binary; do + echo "🔏 Signing $binary..." + codesign --timestamp --options runtime --sign "$SIGNING_IDENTITY" "$binary" + codesign --verify --verbose=2 "$binary" +done + +echo "✅ All macOS binaries signed successfully." \ No newline at end of file From 589936826df61e892965ccda6d35c6bb2570ab75 Mon Sep 17 00:00:00 2001 From: bikmazefe Date: Tue, 6 May 2025 17:50:09 +0300 Subject: [PATCH 2/3] Run on macos --- clients/cli/.github/workflows/release.yml | 16 +++++++++++++++- clients/cli/build/build.sh | 3 --- clients/cli/build/sign.sh | 11 ++++++----- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/clients/cli/.github/workflows/release.yml b/clients/cli/.github/workflows/release.yml index 396fada69..15045866c 100644 --- a/clients/cli/.github/workflows/release.yml +++ b/clients/cli/.github/workflows/release.yml @@ -32,9 +32,23 @@ jobs: API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} VERSION: ${{ steps.version.outputs.VERSION }} + sign_and_notarize: + runs-on: macos-latest + needs: release + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Sign CLI binaries + run: bash ./build/sign.sh + env: + SIGNING_CERTIFICATE: ${{ secrets.SIGNING_CERTIFICATE }} + CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }} + SIGNING_IDENTITY: ${{ secrets.SIGNING_IDENTITY }} + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + DIST_DIR: "dist" brew: runs-on: ubuntu-latest - needs: release + needs: sign_and_notarize steps: - name: Checkout uses: actions/checkout@v4 diff --git a/clients/cli/build/build.sh b/clients/cli/build/build.sh index c37682fed..eceb57ef3 100755 --- a/clients/cli/build/build.sh +++ b/clients/cli/build/build.sh @@ -15,9 +15,6 @@ cd $DIST_DIR tar --extract --file=build.tar rm -f build.tar - -./sign.sh $SIGNING_CERTIFICATE $CERTIFICATE_PASSWORD $SIGNING_IDENTITY $KEYCHAIN_PASSWORD $DIST_DIR - # Homebrew - binary must be called phrase, because the binary name inside # the tar will be made available system wide for name in phrase_macosx_amd64 phrase_macosx_arm64; do diff --git a/clients/cli/build/sign.sh b/clients/cli/build/sign.sh index c4f4ac414..1236556d9 100644 --- a/clients/cli/build/sign.sh +++ b/clients/cli/build/sign.sh @@ -1,10 +1,11 @@ +#!/bin/bash set -eo pipefail -CERTIFICATE_BASE64=$1 -P12_PASSWORD=$2 -IDENTITY=$3 -KEYCHAIN_PASSWORD=$4 -DIST_DIR=$5 +CERTIFICATE_BASE64="${SIGNING_CERTIFICATE}" +P12_PASSWORD="${CERTIFICATE_PASSWORD}" +SIGNING_IDENTITY="${SIGNING_IDENTITY}" +KEYCHAIN_PASSWORD="${KEYCHAIN_PASSWORD}" +DIST_DIR="${DIST_DIR:-dist}" CERTIFICATE_PATH="./build_certificate.p12" KEYCHAIN_PATH="./my-signing.keychain-db" From c976d2fe530b2d5d78e4c4a0583fadc8b5dd8000 Mon Sep 17 00:00:00 2001 From: bikmazefe Date: Tue, 6 May 2025 18:34:56 +0300 Subject: [PATCH 3/3] Upload files to the release after signing the binaries --- clients/cli/.github/workflows/release.yml | 32 +++++++++++++++ clients/cli/build/release.sh | 50 +---------------------- 2 files changed, 33 insertions(+), 49 deletions(-) diff --git a/clients/cli/.github/workflows/release.yml b/clients/cli/.github/workflows/release.yml index 15045866c..b4a7eb862 100644 --- a/clients/cli/.github/workflows/release.yml +++ b/clients/cli/.github/workflows/release.yml @@ -32,12 +32,31 @@ jobs: API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} VERSION: ${{ steps.version.outputs.VERSION }} + - name: Upload built binaries + uses: actions/upload-artifact@v4 + with: + name: dist + path: dist/ + - name: Create draft GitHub Release + uses: softprops/action-gh-release@v1 + with: + draft: true + name: ${{ github.ref_name }} + tag_name: ${{ github.ref_name }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + sign_and_notarize: runs-on: macos-latest needs: release steps: - name: Checkout uses: actions/checkout@v4 + - name: Download built binaries + uses: actions/download-artifact@v4 + with: + name: dist + path: dist - name: Sign CLI binaries run: bash ./build/sign.sh env: @@ -46,6 +65,19 @@ jobs: SIGNING_IDENTITY: ${{ secrets.SIGNING_IDENTITY }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} DIST_DIR: "dist" + - name: Upload signed binaries to Draft Release + uses: softprops/action-gh-release@v1 + with: + files: dist/* + name: ${{ github.ref_name }} + tag_name: ${{ github.ref_name }} + draft: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Publish GitHub Release + run: gh release edit ${{ github.ref_name }} --draft=false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} brew: runs-on: ubuntu-latest needs: sign_and_notarize diff --git a/clients/cli/build/release.sh b/clients/cli/build/release.sh index e29198c83..c3de46f08 100755 --- a/clients/cli/build/release.sh +++ b/clients/cli/build/release.sh @@ -25,52 +25,4 @@ cp dist/phrase_linux_arm64 dist/linux/arm64 docker buildx build --tag "${IMAGE}" --tag ${IMAGE_LATEST} --platform linux/amd64,linux/arm64 -f ./Dockerfile --push . -# Create release -function create_release_data() -{ - cat < /dev/null - echo Hash: $(sha256sum $file) - fi -done - -echo "Publishing release" -curl \ - --silent \ - -X PATCH \ - -H "Authorization: token ${GITHUB_TOKEN}" \ - -H "Accept: application/vnd.github.v3+json" \ - "https://api.github.com/repos/phrase/phrase-cli/releases/${release_id}" \ - -d '{"draft": false}' > /dev/null - -echo "Release successful" +echo "Artifacts built and ready in dist/ directory. GitHub Release creation handled in GitHub Actions workflow."