Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion clients/cli/.github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,55 @@ 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:
SIGNING_CERTIFICATE: ${{ secrets.SIGNING_CERTIFICATE }}
CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }}
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: release
needs: sign_and_notarize
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down
50 changes: 1 addition & 49 deletions clients/cli/build/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 <<EOF
{
"tag_name": "${VERSION}",
"name": "${VERSION}",
"draft": true,
"prerelease": false,
"body": "https://github.com/phrase/phrase-cli/blob/master/CHANGELOG.md"
}
EOF
}

echo "Create release $VERSION"
api_url="https://api.github.com/repos/phrase/phrase-cli/releases"
response="$(curl -H "Authorization: token ${GITHUB_TOKEN}" --data "$(create_release_data)" ${api_url})"
release_id=$(echo $response | python -c "import sys, json; print(json.load(sys.stdin).get('id', ''))")

if [ -z "$release_id" ]
then
echo "Failed to create GitHub release"
echo $response
exit 1
else
echo "New release created created with id: ${release_id}"
fi

# Upload artifacts
DIST_DIR="./dist"
for file in "$DIST_DIR"/*; do
if [ -f "$file" ]; then
echo "Uploading ${file}"
asset="https://uploads.github.com/repos/phrase/phrase-cli/releases/${release_id}/assets?name=$(basename "$file")"
curl -sS --data-binary @"$file" -H "Authorization: token ${GITHUB_TOKEN}" -H "Content-Type: application/octet-stream" $asset > /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."
37 changes: 37 additions & 0 deletions clients/cli/build/sign.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/bin/bash
set -eo pipefail

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"

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"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need to run this inside a MacOS container to have the commands available?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good and important point 😬 I assumed we were already doing it but confused it with the IOS SDK workflow.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll also need to fix the dist directory though, as we're signing them in a separate action now.

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."
Loading