Skip to content

Commit

Permalink
feat: mas (#2692)
Browse files Browse the repository at this point in the history
* feat: build pkg for mas

* fix: mas build script

* chore: manual mas build

* chore: optional tag_version

* fix: mas build input

* chore: debug

* feat: pkg keychain

* feat: remove pkg maker

* Revert "feat: remove pkg maker"

This reverts commit 0fef700.

* feat: disable dmg maker for mas

* feat: update version to match mas' requirement

* feat: mas arch

* fix: mas build

* chore: update version

* feat: login and account deletion for mas

* feat: dynamic build version

* feat: recover version

* feat: add BUILD_CERTIFICATE_MASPKG_BASE64
  • Loading branch information
DIYgod authored Feb 8, 2025
1 parent a986953 commit e03f38a
Show file tree
Hide file tree
Showing 9 changed files with 237 additions and 77 deletions.
57 changes: 49 additions & 8 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@ on:
workflow_dispatch:
inputs:
tag_version:
type: boolean
description: "Tag Version"
required: true
mas:
type: boolean
description: "Build for Mac App Store"
build_version:
type: string
description: "Build Version, only available when mas is true"

# https://docs.github.com/en/enterprise-cloud@latest/actions/writing-workflows/choosing-what-your-workflow-does/control-the-concurrency-of-workflows-and-jobs
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-build
Expand All @@ -32,6 +39,9 @@ jobs:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
exclude:
- os: ${{ github.event.inputs.mas == 'true' && 'ubuntu-latest' }}
- os: ${{ github.event.inputs.mas == 'true' && 'windows-latest' }}

permissions:
id-token: write
Expand All @@ -41,13 +51,13 @@ jobs:
steps:
- name: Check out Git repository Fully
uses: actions/checkout@v4
if: github.event.inputs.tag_version != '' || github.ref_type == 'tag'
if: github.event.inputs.tag_version == 'true' || github.ref_type == 'tag'
with:
fetch-depth: 0
lfs: true
- name: Check out Git repository
uses: actions/checkout@v4
if: github.event.inputs.tag_version == '' && github.ref_type != 'tag'
if: github.event.inputs.tag_version != 'true' && github.ref_type != 'tag'
with:
fetch-depth: 1
lfs: true
Expand All @@ -73,17 +83,23 @@ jobs:
if: runner.os == 'macOS'
env:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
BUILD_CERTIFICATE_MAS_BASE64: ${{ secrets.BUILD_CERTIFICATE_MAS_BASE64 }}
BUILD_CERTIFICATE_MASPKG_BASE64: ${{ secrets.BUILD_CERTIFICATE_MASPKG_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
CERTIFICATE_MAS_PATH=$RUNNER_TEMP/build_certificate_mas.p12
CERTIFICATE_MASPKG_PATH=$RUNNER_TEMP/build_certificate_maspkg.p12
PP_PATH=$RUNNER_TEMP/build_pp.provisionprofile
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
# import certificate and provisioning profile from secrets
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
echo -n "$BUILD_CERTIFICATE_MAS_BASE64" | base64 --decode -o $CERTIFICATE_MAS_PATH
echo -n "$BUILD_CERTIFICATE_MASPKG_BASE64" | base64 --decode -o $CERTIFICATE_MASPKG_PATH
echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH
# create temporary keychain
Expand All @@ -93,8 +109,11 @@ jobs:
# import certificate to keychain
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security import $CERTIFICATE_MAS_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security import $CERTIFICATE_MASPKG_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
security find-identity $KEYCHAIN_PATH
# apply provisioning profile
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
Expand All @@ -111,14 +130,24 @@ jobs:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}

- name: Build (macOS)
if: matrix.os == 'macos-latest'
if: matrix.os == 'macos-latest' && github.event.inputs.mas != 'true'
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
KEYCHAIN_PATH: ${{ runner.temp }}/app-signing.keychain-db
OSX_SIGN_KEYCHAIN_PATH: ${{ runner.temp }}/app-signing.keychain-db
OSX_SIGN_IDENTITY: ${{ secrets.OSX_SIGN_IDENTITY }}
run: npm exec turbo run //#build:macos

- name: Build (Mac App Store)
if: matrix.os == 'macos-latest' && github.event.inputs.mas == 'true'
env:
OSX_SIGN_KEYCHAIN_PATH: ${{ runner.temp }}/app-signing.keychain-db
OSX_SIGN_IDENTITY: ${{ secrets.OSX_SIGN_IDENTITY_MAS }}
OSX_SIGN_PROVISIONING_PROFILE_PATH: ${{ runner.temp }}/build_pp.provisionprofile
BUILD_VERSION: ${{ github.event.inputs.build_version }}
run: npm exec turbo run //#build:mas

- name: Build Renderer
if: matrix.os == 'ubuntu-latest'
run: pnpm build:render
Expand All @@ -138,6 +167,7 @@ jobs:
out/make/**/*.exe
out/make/**/*.AppImage
out/make/**/*.yml
out/make/**/*.pkg
dist/manifest.yml
dist/*.tar.gz
retention-days: 90
Expand All @@ -153,8 +183,19 @@ jobs:
out/make/**/*arm64.dmg
retention-days: 90

- name: Upload file (pkg)
uses: actions/upload-artifact@v4
if: matrix.os == 'macos-latest'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
name: mas-pkg
path: |
out/make/**/*.pkg
retention-days: 90

- name: Generate artifact attestation
if: github.ref_type == 'tag' || github.event.inputs.tag_version != ''
if: github.ref_type == 'tag' || github.event.inputs.tag_version == 'true'
continue-on-error: true
uses: actions/attest-build-provenance@v1
with:
Expand All @@ -168,7 +209,7 @@ jobs:
dist/*.tar.gz
- run: npx changelogithub
if: github.ref_type == 'tag' || github.event.inputs.tag_version != ''
if: github.ref_type == 'tag' || github.event.inputs.tag_version == 'true'
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -178,7 +219,7 @@ jobs:
uses: ./.github/actions/setup-version

- name: Create Release Draft
if: github.ref_type == 'tag' || github.event.inputs.tag_version != ''
if: github.ref_type == 'tag' || github.event.inputs.tag_version == 'true'
uses: softprops/action-gh-release@v2
with:
name: v${{ steps.version.outputs.APP_VERSION }}
Expand Down
78 changes: 41 additions & 37 deletions apps/renderer/src/modules/auth/LoginModalContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,43 +45,47 @@ export const LoginModalContent = (props: LoginModalContentProps) => {
</div>

<LoginWithPassword runtime={runtime} />
<div className="my-3 w-full space-y-2">
<div className="flex items-center justify-center">
<Divider className="flex-1" />
<p className="px-4 text-center text-sm text-muted-foreground">{t("login.or")}</p>
<Divider className="flex-1" />
</div>
</div>
<div className="mb-3 flex items-center justify-center gap-4">
{Object.entries(authProviders || [])
.filter(([key]) => key !== "credential")
.map(([key, provider]) => (
<Tooltip key={key} delayDuration={0}>
<TooltipTrigger>
<MotionButtonBase
onClick={() => {
loginHandler(key, "app")
}}
>
<div
className="center inline-flex rounded-full border p-2.5 duration-200 hover:bg-muted [&_svg]:size-6"
dangerouslySetInnerHTML={{
__html: provider.icon,
}}
style={{
color: provider.color,
}}
/>
</MotionButtonBase>
</TooltipTrigger>
<TooltipPortal>
<TooltipContent>
{t("login.continueWith", { provider: provider.name })}
</TooltipContent>
</TooltipPortal>
</Tooltip>
))}
</div>
{!process.mas && (
<>
<div className="my-3 w-full space-y-2">
<div className="flex items-center justify-center">
<Divider className="flex-1" />
<p className="px-4 text-center text-sm text-muted-foreground">{t("login.or")}</p>
<Divider className="flex-1" />
</div>
</div>
<div className="mb-3 flex items-center justify-center gap-4">
{Object.entries(authProviders || [])
.filter(([key]) => key !== "credential")
.map(([key, provider]) => (
<Tooltip key={key} delayDuration={0}>
<TooltipTrigger>
<MotionButtonBase
onClick={() => {
loginHandler(key, "app")
}}
>
<div
className="center inline-flex rounded-full border p-2.5 duration-200 hover:bg-muted [&_svg]:size-6"
dangerouslySetInnerHTML={{
__html: provider.icon,
}}
style={{
color: provider.color,
}}
/>
</MotionButtonBase>
</TooltipTrigger>
<TooltipPortal>
<TooltipContent>
{t("login.continueWith", { provider: provider.name })}
</TooltipContent>
</TooltipPortal>
</Tooltip>
))}
</div>
</>
)}
</>
)
if (isMobile) {
Expand Down
38 changes: 38 additions & 0 deletions apps/renderer/src/pages/settings/(settings)/profile.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { Button } from "@follow/components/ui/button/index.js"
import { Divider } from "@follow/components/ui/divider/Divider.js"
import { Label } from "@follow/components/ui/label/index.js"
import { signOut } from "@follow/shared/auth"

import { useModalStack } from "~/components/ui/modal/stacked/hooks"
import { AccountManagement } from "~/modules/profile/account-management"
import { EmailManagement } from "~/modules/profile/email-management"
import { ProfileSettingForm } from "~/modules/profile/profile-setting-form"
Expand All @@ -17,6 +21,7 @@ export const loader = defineSettingPageData({
})

export function Component() {
const { present } = useModalStack()
return (
<>
<SettingsTitle />
Expand All @@ -30,6 +35,39 @@ export function Component() {
<AccountManagement />
<UpdatePasswordForm />
<TwoFactor />
{/* TODO: Temporary fake account deletion feature */}
{process.mas && (
<div className="flex items-center justify-between">
<Label>Delete Account</Label>
<Button
variant="outline"
onClick={() => {
present({
title: "Delete Account",
content: () => (
<div className="max-w-96">
<p className="mb-4 text-sm text-zinc-500">
Are you sure you want to delete your account? This action is irreversible
and may take up to two days to take effect.
</p>
<Button
variant="outline"
onClick={async () => {
await signOut()
window.location.reload()
}}
>
Delete
</Button>
</div>
),
})
}}
>
Delete
</Button>
</div>
)}
</div>
</section>
</>
Expand Down
10 changes: 10 additions & 0 deletions build/entitlements.mas.child.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.inherit</key>
<true/>
</dict>
</plist>
16 changes: 16 additions & 0 deletions build/entitlements.mas.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.files.bookmarks.app-scope</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
</dict>
</plist>
Loading

0 comments on commit e03f38a

Please sign in to comment.