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
5 changes: 5 additions & 0 deletions .changeset/red-wasps-kick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"varlock": minor
---

add new varlock() function for built-in encryption
37 changes: 37 additions & 0 deletions .github/workflows/binary-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ on:
release:
types: [published]

permissions:
contents: read

concurrency: ${{ github.workflow }}-${{ github.ref }}

jobs:
Expand All @@ -24,10 +27,35 @@ jobs:
run: |
echo "$GITHUB_CONTEXT"

# Build and sign the macOS native binary (cache hit if already built in CI)
build-native-macos:
if: github.event_name == 'workflow_dispatch' || startsWith(github.ref_name, 'varlock@')
uses: ./.github/workflows/build-native-macos.yaml
with:
mode: release
version: ${{ github.event_name == 'workflow_dispatch' && inputs.version || github.ref_name }}
artifact-name: native-bin-macos-signed
secrets:
OP_CI_TOKEN: ${{ secrets.OP_CI_TOKEN }}

# Notarize the signed binary for production distribution
notarize-native-macos:
needs: build-native-macos
if: github.event_name == 'workflow_dispatch' || startsWith(github.ref_name, 'varlock@')
uses: ./.github/workflows/notarize-native-macos.yaml
with:
source-artifact-name: native-bin-macos-signed
artifact-name: native-bin-macos-release
secrets:
OP_CI_TOKEN: ${{ secrets.OP_CI_TOKEN }}

release-binaries:
needs: notarize-native-macos
# was using github.ref.tag_name, but it seems that when publishing multiple tags at once, it was behaving weirdly
if: github.event_name == 'workflow_dispatch' || startsWith(github.ref_name, 'varlock@')
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- name: Setup Bun
Expand Down Expand Up @@ -63,6 +91,15 @@ jobs:
echo "RELEASE_TAG=varlock@${{ inputs.version }}" >> $GITHUB_ENV
echo "RELEASE_VERSION=${{ inputs.version }}" >> $GITHUB_ENV

# Download the signed macOS native binary
- name: Download macOS native binary
uses: actions/download-artifact@v8
with:
name: native-bin-macos-release
path: packages/varlock/native-bins/darwin/VarlockEnclave.app
- name: Restore native binary execute permission
run: chmod +x packages/varlock/native-bins/darwin/VarlockEnclave.app/Contents/MacOS/varlock-local-encrypt

- name: build libs
run: bun run build:libs
env:
Expand Down
142 changes: 142 additions & 0 deletions .github/workflows/build-native-macos.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: Build macOS native binary

# Reusable workflow that compiles, bundles, and Developer ID signs the
# VarlockEnclave Swift binary on a macOS runner.
#
# The Swift .build directory is cached by source hash, so the compile
# step (~minutes) is near-instant on cache hit. The .app bundle wrapping
# (plist, icon, signing) always runs since it varies by mode/version.
#
# Notarization is intentionally NOT included here — it's a separate
# workflow for production releases.

permissions:
contents: read

on:
workflow_call:
inputs:
mode:
description: 'Build mode: dev, preview, or release (affects bundle metadata)'
type: string
default: 'preview'
version:
description: 'Bundle version string (e.g. 1.2.3)'
type: string
default: '0.0.0-preview'
artifact-name:
description: 'Name for the uploaded artifact'
type: string
default: 'native-bin-macos'
secrets:
OP_CI_TOKEN:
required: true

jobs:
build-swift-binary:
runs-on: macos-latest
steps:
- uses: actions/checkout@v6

- name: Setup Bun
uses: oven-sh/setup-bun@v2

# skip bun dep caching since less likely to hit

- name: Install node deps
run: bun install

- name: Enable turborepo build cache
uses: rharkor/caching-for-turbo@v2.3.11

# Cache the Swift .build directory so compilation is fast on unchanged source
- name: Compute Swift source hash
id: swift-hash
run: |
HASH=$(find packages/encryption-binary-swift/swift -type f | sort | xargs shasum -a 256 | shasum -a 256 | cut -d' ' -f1)
echo "hash=$HASH" >> $GITHUB_OUTPUT
echo "Swift source hash: $HASH"

- name: Cache Swift build artifacts
uses: actions/cache@v5
with:
path: packages/encryption-binary-swift/swift/.build
key: varlock-swift-build-${{ steps.swift-hash.outputs.hash }}

# Build varlock JS so we can use it to resolve secrets from 1Password
- name: Build varlock libs
run: bun run build:libs

# Load secrets from 1Password via varlock (scoped to the Swift package)
- name: Load signing secrets
uses: dmno-dev/varlock-action@v1.0.1
with:
working-directory: packages/encryption-binary-swift
env:
OP_CI_TOKEN: ${{ secrets.OP_CI_TOKEN }}

# Import signing certificate into a temporary keychain
- name: Import signing certificate
run: |
KEYCHAIN_PATH=$RUNNER_TEMP/signing.keychain-db
KEYCHAIN_PASSWORD=$(openssl rand -base64 24)

echo "$APPLE_CERTIFICATE_BASE64" | base64 --decode > $RUNNER_TEMP/certificate.p12

security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"

security import $RUNNER_TEMP/certificate.p12 \
-P "$APPLE_CERTIFICATE_PASSWORD" \
-A -t cert -f pkcs12 \
-k "$KEYCHAIN_PATH"

security set-key-partition-list -S apple-tool:,apple:,codesign: \
-s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"

security list-keychains -d user -s "$KEYCHAIN_PATH" login.keychain-db

echo "APPLE_SIGNING_IDENTITY=$APPLE_SIGNING_IDENTITY" >> $GITHUB_ENV

# Compile (cached), bundle with mode-specific metadata, and sign
- name: Build, bundle, and sign
run: |
bun run --filter @varlock/encryption-binary-swift build:swift \
-- --mode ${{ inputs.mode }} --version ${{ inputs.version }} --sign "$APPLE_SIGNING_IDENTITY"

- name: Verify binary
run: |
APP_PATH="packages/varlock/native-bins/darwin/VarlockEnclave.app"
echo "=== App bundle contents ==="
ls -la "$APP_PATH/Contents/MacOS/"
echo "=== Binary architectures ==="
lipo -info "$APP_PATH/Contents/MacOS/varlock-local-encrypt"
echo "=== Code signature ==="
codesign -dvv "$APP_PATH" 2>&1 || true
echo "=== Info.plist ==="
cat "$APP_PATH/Contents/Info.plist"

- name: Upload native binary artifact
uses: actions/upload-artifact@v7
with:
name: ${{ inputs.artifact-name }}
path: packages/varlock/native-bins/darwin/VarlockEnclave.app
retention-days: 7

# Cache the signed .app so other jobs (e.g. release-preview) can restore
# it on a Linux runner without needing a macOS build
- name: Cache signed .app bundle
uses: actions/cache/save@v5
with:
path: packages/varlock/native-bins/darwin/VarlockEnclave.app
key: native-bin-macos-signed-${{ hashFiles('packages/encryption-binary-swift/swift/**') }}

- name: Cleanup signing keychain
if: always()
run: |
KEYCHAIN_PATH=$RUNNER_TEMP/signing.keychain-db
if [ -f "$KEYCHAIN_PATH" ]; then
security delete-keychain "$KEYCHAIN_PATH" || true
fi
rm -f $RUNNER_TEMP/certificate.p12
91 changes: 91 additions & 0 deletions .github/workflows/notarize-native-macos.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Notarize macOS native binary

# Reusable workflow that takes an already-signed .app bundle artifact,
# submits it to Apple for notarization, and staples the ticket.
# Requires a macOS runner for xcrun.

permissions:
contents: read

on:
workflow_call:
inputs:
source-artifact-name:
description: 'Name of the signed .app artifact to notarize'
type: string
required: true
artifact-name:
description: 'Name for the notarized artifact'
type: string
default: 'native-bin-macos-notarized'
secrets:
OP_CI_TOKEN:
required: true

jobs:
notarize:
runs-on: macos-latest
steps:
- uses: actions/checkout@v6

- name: Setup Bun
uses: oven-sh/setup-bun@v2

# skip bun dep caching since less likely to hit

- name: Install node deps
run: bun install

- name: Enable turborepo build cache
uses: rharkor/caching-for-turbo@v2.3.11

- name: Build varlock libs
run: bun run build:libs

- name: Download signed .app bundle
uses: actions/download-artifact@v8
with:
name: ${{ inputs.source-artifact-name }}
path: VarlockEnclave.app

# Load secrets from 1Password via varlock (scoped to the Swift package)
- name: Load signing secrets
uses: dmno-dev/varlock-action@v1.0.1
with:
working-directory: packages/encryption-binary-swift
env:
OP_CI_TOKEN: ${{ secrets.OP_CI_TOKEN }}

- name: Notarize and staple
working-directory: packages/encryption-binary-swift
run: |
APP_PATH="$GITHUB_WORKSPACE/VarlockEnclave.app"
# Create a zip for notarization submission
ditto -c -k --keepParent "$APP_PATH" $RUNNER_TEMP/VarlockEnclave.zip
# Submit for notarization and wait
xcrun notarytool submit $RUNNER_TEMP/VarlockEnclave.zip \
--apple-id "$APPLE_ID" \
--password "$APPLE_APP_PASSWORD" \
--team-id "$APPLE_TEAM_ID" \
--wait
# Staple the notarization ticket to the app bundle
xcrun stapler staple "$APP_PATH"
env:
OP_CI_TOKEN: ${{ secrets.OP_CI_TOKEN }}

- name: Verify notarization
run: |
echo "=== Code signature ==="
codesign -dvv VarlockEnclave.app 2>&1 || true
echo "=== Notarization staple ==="
xcrun stapler validate VarlockEnclave.app
- name: Upload notarized artifact
uses: actions/upload-artifact@v7
with:
name: ${{ inputs.artifact-name }}
path: VarlockEnclave.app
retention-days: 7
46 changes: 0 additions & 46 deletions .github/workflows/release-preview.yaml

This file was deleted.

Loading
Loading