Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
gershnik committed Nov 20, 2023
1 parent c687738 commit 63c9363
Show file tree
Hide file tree
Showing 86 changed files with 5,672 additions and 0 deletions.
66 changes: 66 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Publish

on:
workflow_dispatch:
push:
tags:
- 'v*'

jobs:
main:
runs-on: macOS-13
permissions: write-all
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Get Version
shell: bash
run: |
version=`tools/get-version`
echo Version: $version
echo "GH_BUILD_VERSION=$version" >> $GITHUB_ENV
- name: Fetch dependencies
shell: bash
run: ./fetch

- name: Build
shell: bash
env:
CERTIFICATES_P12: ${{ secrets.CERTIFICATES_P12 }}
CERTIFICATES_PWD: ${{ secrets.CERTIFICATES_PWD }}
KEYCHAIN_PWD: ${{ secrets.KEYCHAIN_PWD }}
NOTARIZE_USER: ${{ secrets.NOTARIZE_USER }}
NOTARIZE_PWD: ${{ secrets.NOTARIZE_PWD }}
run: |
tools/set-github-keychain
xcodebuild build \
-workspace Translit.xcworkspace \
-scheme Installer \
-derivedDataPath DerivedData \
TRANSLIT_SIGN_PACKAGE=true \
CODE_SIGN_INJECT_BASE_ENTITLEMENTS=NO
- name: Upload Symbols
shell: bash
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: |
aws s3 cp DerivedData/Build/Products/Release/Translit-${{ env.GH_BUILD_VERSION }}.dSYM.tgz \
s3://translit-symbols/Translit-${{ env.GH_BUILD_VERSION }}.dSYM.tgz
- name: Make release
uses: softprops/action-gh-release@v1
with:
draft: true
prerelease: false
name: ${{ env.GH_BUILD_VERSION }}
body: ...edit me...
files: DerivedData/Build/Products/Release/Translit-${{ env.GH_BUILD_VERSION }}.pkg




64 changes: 64 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Test

on:
push:
branches:
- '*'
- '*/**'
paths-ignore:
- 'README.md'
- 'CHANGELOG.md'
- '.gitignore'
- 'LICENSE'
- '.github/workflows/publish.yml'
- 'tools/create-release'

env:
DEVELOPER_DIR: /Applications/Xcode_15.0.app

jobs:
main:
runs-on: macOS-13

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Get Version
shell: bash
run: |
version=`tools/get-version`
echo Version: $version
echo "GH_BUILD_VERSION=$version" >> $GITHUB_ENV
- name: Fetch dependencies
shell: bash
run: ./fetch

- name: Test
shell: bash
run: xcodebuild test -workspace Translit.xcworkspace -scheme Translit -derivedDataPath DerivedData

- name: Build
shell: bash
env:
CERTIFICATES_P12: ${{ secrets.CERTIFICATES_P12 }}
CERTIFICATES_PWD: ${{ secrets.CERTIFICATES_PWD }}
KEYCHAIN_PWD: ${{ secrets.KEYCHAIN_PWD }}
NOTARIZE_USER: ${{ secrets.NOTARIZE_USER }}
NOTARIZE_PWD: ${{ secrets.NOTARIZE_PWD }}
run: |
tools/set-github-keychain
xcodebuild build \
-workspace Translit.xcworkspace \
-scheme Installer \
-derivedDataPath DerivedData \
TRANSLIT_SIGN_PACKAGE=true CODE_SIGN_INJECT_BASE_ENTITLEMENTS=NO
- name: 'Upload Artifact'
uses: actions/upload-artifact@v3
with:
name: Translit-${{ env.GH_BUILD_VERSION }}.pkg
path: DerivedData/Build/Products/Release/Translit-${{ env.GH_BUILD_VERSION }}.pkg
retention-days: 3

7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.DS_Store
xcuserdata/
DerivedData
External
Local.xcconfig
Translit/generated

10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Changelog
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## Unreleased

### Added

- Initial version
132 changes: 132 additions & 0 deletions Installer/build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#! /usr/bin/env -S python3 -u

# Copyright (c) 2023, Eugene Gershnik
# SPDX-License-Identifier: GPL-3.0-or-later

import sys
import os
import subprocess
import shutil
import plistlib
import re
import argparse
from pathlib import Path

def copyTemplated(src, dst, map):
dstdir = dst.parent
dstdir.mkdir(parents=True, exist_ok=True)
dst.write_text(src.read_text().format_map(map))

def uploadResults(installer, symfile, version):

subprocess.run(['gh', 'release', 'upload', f'{version}', installer], check=True)


parser = argparse.ArgumentParser()

parser.add_argument('builddir', type=Path)
parser.add_argument('tempdir', type=Path)
parser.add_argument('--sign', dest='sign', action='store_true', required=False)
parser.add_argument('--upload-results', dest='uploadResults', action='store_true', required=False)

args = parser.parse_args()

mydir = Path(__file__).parent
builddir: Path = args.builddir
tempdir: Path = args.tempdir
shouldSign: bool = args.sign or os.environ.get('TRANSLIT_SIGN_PACKAGE', "false") == "true"


with open(builddir / "Translit.app/Contents/Info.plist", "rb") as src:
appPlist = plistlib.load(src, fmt=plistlib.FMT_XML)

VERSION: str = appPlist['CFBundleShortVersionString']
IDENTIFIER: str = appPlist['CFBundleIdentifier']

workdir = tempdir / 'stage'
rootdir = workdir / f'root'
shutil.rmtree(workdir, ignore_errors=True)
rootdir.mkdir(parents=True)

inputMethodsDir = rootdir / "Library/Input Methods"
inputMethodsDir.mkdir(parents=True)

ignoreCrap = shutil.ignore_patterns('.DS_Store')
shutil.copytree(builddir / "Translit.app", inputMethodsDir / "Translit.app", ignore=ignoreCrap)
subprocess.run(['/usr/bin/strip', '-no_code_signature_warning', '-u', '-r',
inputMethodsDir / "Translit.app/Contents/MacOS/Translit"],
check=True)

copyTemplated(mydir / 'distribution.xml', workdir / 'distribution.xml', {
'IDENTIFIER':IDENTIFIER,
'VERSION': VERSION
})

if shouldSign:
subprocess.run(['codesign', '--force', '--sign', 'Developer ID Application', '-o', 'runtime', '--timestamp',
'--preserve-metadata=entitlements',
inputMethodsDir / "Translit.app"], check=True)
else:
subprocess.run(['codesign', '--force', '--sign', '-', '-o', 'runtime', '--timestamp=none',
'--preserve-metadata=entitlements',
inputMethodsDir / "Translit.app"], check=True)


packagesdir = workdir / 'packages'
packagesdir.mkdir()

subprocess.run(['pkgbuild',
'--analyze',
'--root', str(rootdir),
str(packagesdir/'component.plist')
], check=True)
with open(packagesdir/'component.plist', "rb") as src:
components = plistlib.load(src, fmt=plistlib.FMT_XML)
for component in components:
component['BundleIsRelocatable'] = False
with open(packagesdir/'component.plist', "wb") as dest:
plistlib.dump(components, dest, fmt=plistlib.FMT_XML)
subprocess.run(['pkgbuild',
'--root', str(rootdir),
'--component-plist', str(packagesdir/'component.plist'),
'--scripts', str(mydir / 'scripts'),
'--identifier', IDENTIFIER,
'--version', VERSION,
'--ownership', 'recommended',
str(packagesdir/'output.pkg')
], check=True)

subprocess.run(['productbuild',
'--distribution', workdir / 'distribution.xml',
'--package-path', str(packagesdir),
'--resources', str(mydir / 'html'),
'--version', VERSION,
str(builddir/'Translit.pkg')
], check=True)

installer = builddir / f'Translit-{VERSION}.pkg'

subprocess.run(['tar', '-C', builddir, '-czf', builddir.absolute() / f'Translit-{VERSION}.dSYM.tgz', 'Translit.app.dSYM'], check=True)

if shouldSign:
subprocess.run(['productsign', '--sign', 'Developer ID Installer', builddir / 'Translit.pkg', installer], check=True)
pattern = re.compile(r'^\s*1. Developer ID Installer: .*\(([0-9A-Z]{10})\)$')
teamId = None
for line in subprocess.run(['pkgutil', '--check-signature', installer],
check=True, stdout=subprocess.PIPE).stdout.decode('utf-8').splitlines():
m = pattern.match(line)
if m:
teamId = m.group(1)
break
if teamId is None:
print('Unable to find team ID from signature', file=sys.stderr)
sys.exit(1)
subprocess.run([mydir / 'notarize', '--user', os.environ['NOTARIZE_USER'], '--password', os.environ['NOTARIZE_PWD'],
'--team', teamId, installer], check=True)
print('Signature Info')
res1 = subprocess.run(['pkgutil', '--check-signature', installer])
print('\nAssesment')
res2 = subprocess.run(['spctl', '--assess', '-vvv', '--type', 'install', installer])
if res1.returncode != 0 or res2.returncode != 0:
sys.exit(1)

41 changes: 41 additions & 0 deletions Installer/distribution.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!--
Copyright (c) 2023, Eugene Gershnik
SPDX-License-Identifier: GPL-3.0-or-later
-->
<installer-gui-script minSpecVersion="2">
<title>Translit Input Method</title>
<organization>io.github.gershnik</organization>
<volume-check script="true">
<allowed-os-versions>
<os-version min="10.13"/>
</allowed-os-versions>
</volume-check>
<domains enable_localSystem="true" enable_currentUserHome="true"/>
<options customize="never" require-scripts="false" rootVolumeOnly="true" hostArchitectures="arm64,x86_64" />
<!-- Define documents displayed at various steps -->
<welcome file="welcome.html" mime-type="text/html" />
<license file="license.html" mime-type="text/html" />
<conclusion file="conclusion.html" mime-type="text/html" />
<!-- List all component packages -->
<pkg-ref id="{IDENTIFIER}" version="{VERSION}">output.pkg</pkg-ref>
<pkg-ref id="{IDENTIFIER}">
<must-close>
<app id="{IDENTIFIER}"/>
<app id="com.apple.systempreferences"/>
</must-close>
</pkg-ref>
<!-- List them again here. They can now be organized as a hierarchy if you want. -->
<choices-outline>
<line choice="{IDENTIFIER}"/>
</choices-outline>
<!-- Define each choice above -->
<choice
id="{IDENTIFIER}"
visible="false"
title="Translit Input Method"
description="Translit Input Method"
start_selected="true">
<pkg-ref id="{IDENTIFIER}"/>
</choice>
</installer-gui-script>
34 changes: 34 additions & 0 deletions Installer/html/conclusion.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<!--
Copyright (c) 2023, Eugene Gershnik
SPDX-License-Identifier: GPL-3.0-or-later
-->
<html>
<head>
<meta name = "viewport" content = "width = device-width">
<meta charset="utf-8"/>
<style>
body {
margin: 0;
font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', sans-serif;
}
</style>
</head>
<body>
<h2>The installation was successful</h2>
<p>
<a href="x-apple.systempreferences:com.apple.preference.keyboard">Click here</a> to launch keyboard
preferences and add <code>Russian Translit</code> and/or <code>Hebrew Translit</code> in the <code>Input Sources</code> section
</p>
<p>
<span style="font-weight:bold">If Translit sources do not appear
in the list of available sources, please logout and log back in (or restart).</span>
</p>
<p>
This is due to various macOS bugs that Apple so far feels no urgency to fix 😡
</p>
<p>
For more detailed instructions and information visit <a href="https://github.com/gershnik/Translit">this Github page</a>.
</p>
</body>
</html>
Loading

0 comments on commit 63c9363

Please sign in to comment.