Compare commits

..

79 Commits

Author SHA1 Message Date
2e80b79110 chore(deps): update build-emacs-for-macos to 0.6.33 2022-04-30 19:45:08 +01:00
88bfa2e603 chore(build): run "brew update" before installing brew deps 2022-04-30 19:45:08 +01:00
9934f47937 docs(readme): minor tweak to stable homebrew cask description 2022-04-07 00:28:26 +01:00
Alec
13e8c9cc9e docs(readme): emacs-app now includes native-comp 2022-04-06 07:44:06 -04:00
4204855346 chore(deps): update build-emacs-for-macos to 0.6.31 2022-02-25 10:35:14 +00:00
11b4492488 chore(deps): update build-emacs-for-macos to 0.6.30 2022-02-08 03:08:35 +00:00
a39895e8f6 docs(readme): add details about pretest builds 2022-02-07 23:17:46 +00:00
27b104d7b7 chore(deps): update build-emacs-for-macos to 0.6.29 2022-02-07 23:17:25 +00:00
0af73aaee1 chore(deps): update build-emacs-for-macos to 0.6.28 2022-01-15 23:21:36 +00:00
16087a80d0 chore(deps): update build-emacs-for-macos to 0.6.27 2021-12-05 13:09:44 +00:00
5835cd9712 docs(readme): update requirements list after gcc fix, minor tweaks 2021-11-30 23:15:36 +00:00
fe10ed4c34 chore(build): remove --no-relink-eln-files option from manual build workflow 2021-11-27 05:07:00 +00:00
9615ab20a6 chore(deps): update build-emacs-for-macos to 0.6.25
Relinking *.eln files has also been fixed, so there's no need to disable
that anymore.
2021-11-27 05:04:46 +00:00
cad73f3555 fix(release): dmg artifact output result check 2021-11-27 03:16:15 +00:00
30f92f734d fix(release): improve handling of no new commit since last build 2021-11-27 01:37:02 +00:00
83b08dc596 feat(build): allow customizing --relink-eln-files arg on custom builds 2021-11-26 02:10:30 +00:00
f3213d9f5a chore(deps): update build-emacs-for-macos to 0.6.25 2021-11-25 23:40:30 +00:00
b40f9e29c8 update build-emacs-for-macos to 0.6.24 2021-11-24 21:54:44 +00:00
e552de3cac fix(builds): use correct path for emacs source tarball artifact upload 2021-11-24 21:54:13 +00:00
9c731dac34 fix(builds/emacs-28): disable posix-patch, it's now in the emacs-28 branch 2021-11-14 02:48:07 +00:00
bf358f42d5 docs(readme): tweak formatting of badges 2021-11-12 13:34:42 +00:00
646d8775fb chore(metadata): run update-metadata workflow every 12 hours
Once an hour was overkill.
2021-11-12 13:31:27 +00:00
7e4ba5a9b8 fix(builds): only use posix-spawn patch on emacs-28 builds
The posix-spawn patch has been added to the master branch, but not the
emacs-28 branch yet.
2021-11-12 13:26:24 +00:00
f82d299015 docs(readme): fix total downloads badge
The release downloads badge from shields.io only checks the first 100
most recent GitHub Releases to calculate the download totals. This
obviously yields invalid values if a repository has more than 100
releases.

Hence we're switching the badge to source it's data from a custom JSON
file in the meta branch, which is updated once an hour but a scheduled
GitHub Actions workflow which runs a Go file that checks all releases
from all pages for downloads counts.
2021-11-11 01:40:51 +00:00
fe0972217f chore(metadata): add update-metadata GitHub Actions Workflow 2021-11-11 01:36:10 +00:00
a61807dea3 feat(builds): enable new posix-spawn patch 2021-11-10 22:24:19 +00:00
d1e14bb59b chore(deps): update build-emacs-for-macos to 0.6.23 2021-11-10 22:24:09 +00:00
06c6c2dbf2 chore(deps): update build-emacs-for-macos to 0.6.22 2021-11-10 02:04:23 +00:00
4561c9d4ce feat(workflows): add builder args option for Build workflow 2021-11-10 02:03:15 +00:00
ebc4626270 chore(deps): update build-emacs-for-macos to 0.6.21 2021-10-27 21:48:18 +01:00
1e45868817 chore(deps): update build-emacs-for-macos to 0.6.20 2021-10-23 20:36:11 +01:00
8e6aa813f9 docs(readme): fix links in badges 2021-10-23 17:38:31 +01:00
f8bf0870a7 docs(readme): add badge for emacs-28 nightly builds 2021-10-23 17:36:08 +01:00
b84115f251 chore(deps): update build-emacs-for-macos to 0.6.19
Fixes an issue with patches for Emacs 29.x.
2021-10-23 17:30:13 +01:00
ffd1f41e19 docs(readme): add mention of emacs-app-nightly-28 Homebrew Cask 2021-10-23 16:39:15 +01:00
195a5f9775 chore(build): upload emacs source tarball as build artifact 2021-10-23 16:32:12 +01:00
31172c47c3 chore(deps): update build-emacs-for-macos to 0.6.18 2021-10-23 16:25:22 +01:00
482bde4c00 fix(workflows): use correct artifact name for build-plan
Also rename build-plan artifact from "build-plan.yml" to "build-plan".
2021-10-11 02:25:50 +01:00
aab02b7454 chore(workflows): tweak re-usable workflow names, again 2021-10-11 00:20:45 +01:00
a8d3b9d473 fix(workflows): remove left-over debug push event from nightly workflows 2021-10-11 00:18:18 +01:00
82353b98c5 chore(workflows): tweak names of re-usable workflows 2021-10-11 00:17:58 +01:00
5b48a4ac70 feat(nightly): add nightly builds for the emacs-28 release branch 2021-10-11 00:06:04 +01:00
2c06f2c0c8 refactor(workflows): switch to re-usable GitHub Actions workflows
This makes the workflow setup more flexible, and less copy/pasting
between workflows. And also makes the process of adding nightly builds
for non-master branches easier too.
2021-10-11 00:03:33 +01:00
1f67047d8d fix(build): add missing --no-archive flag to build script 2021-08-05 10:36:18 +01:00
9809dd349e fix(test-build): build plan is needed by package job 2021-08-05 10:35:55 +01:00
a4b07f609d chore(deps): update build-emacs-for-macos to 0.6.15 2021-08-05 02:39:18 +01:00
1049006024 chore(deps): update build-emacs-for-macos to 0.6.14 2021-08-05 01:22:09 +01:00
1ba8aaecfd chore(test-build): fix builder sha lookup, remove caching
The caching idea is somewhat flawed, as there's a lot of things that
cane effect the outcome, and they're difficult to boil down into a
single unique key.
2021-08-05 01:21:02 +01:00
6561dc4a02 chore(test-build): cache unsigned app based on builder git sha and build-plan.yml hash 2021-08-05 00:44:40 +01:00
dae8939b35 fix(build): disable relinking shared libs in *.eln files
Relinking the libgcc shared lib within bundled *.eln files seems to
prevent code signing from having enough space to add a signature to the
files. So for now it looks like we have to disable it.
2021-08-05 00:11:17 +01:00
baea14c975 chore(deps): update build-emacs-for-macos to 0.6.13 2021-08-05 00:08:00 +01:00
ee9e58b873 chore(deps): update build-emacs-for-macos to 0.6.12
Should resolve code signing issue which has been preventing new nightly
builds.
2021-08-03 00:20:40 +01:00
04d20d42a4 chore(deps): update build-emacs-for-macos to 0.6.11
Fixes issue with code signing *.eln files.
2021-07-17 13:10:18 +01:00
259b0ac92b chore(deps): update build-emacs-for-macos to 0.6.9
Fixes:

- native-comp: *.eln files were not being found during shared lib
  embedding
2021-07-17 00:27:58 +01:00
162f9ad529 docs(readme): update requirements to mention M1-based macs 2021-07-13 21:36:42 +01:00
a6324b58c9 docs(readme): add link to homebrew tap 2021-07-10 21:21:11 +01:00
9be0607ee5 chore(deps): update build-emacs-for-macos to 0.6.9 2021-07-04 23:29:43 +01:00
18f753e476 docs(readme): update version badges 2021-07-04 18:32:28 +01:00
9e71a079a9 docs(readme): fix typo 2021-07-03 02:55:49 +01:00
8e92655b4b docs(readme): add information about stable builds 2021-07-03 02:54:32 +01:00
1782d42a7d docs(readme): add stable/nightly badges 2021-07-03 02:11:51 +01:00
ac5ff5d3c2 docs(readme): update nightly badge to include pre-releases 2021-07-03 00:37:46 +01:00
13410e3977 feat(builds): add support for building stable Emacs releases
As of build-emacs-for-macos v0.6.8, the emacs-builder tool supports
handling stable Emacs release differently, so we can easily separate
them from the regular nightly builds.
2021-07-03 00:21:55 +01:00
88f47746e4 fix(cask): trigger cask update in homebrew tap after publishing release 2021-07-02 00:13:17 +01:00
4ffe25022c chore(deps): update build-emacs-for-macos to 0.6.5 2021-07-01 23:42:20 +01:00
00094c131c docs(readme): improve formatting of Installation section 2021-06-29 02:58:04 +01:00
26b12fac27 docs(readme): update readme about homebrew cask installation method 2021-06-29 02:42:02 +01:00
25e2a41b22 chore(deps): update build-emacs-for-macos to 0.6.2
Should fix startup error about missing *.eln files.
2021-06-29 01:31:51 +01:00
1b2cc6e676 feat(cask): add workflow to trigger homebrew cask formula update on new release
This triggers the update formulas workflow in the
jimeh/homebrew-emacs-builds repo whenever a release or pre-release is
created in jimeh/emacs-builds.

This allows the cask formulas to automatically stay up to date with
latest nightly builds.
2021-06-29 00:28:47 +01:00
376125273b chore(deps): update build-emacs-for-macos to 0.6.1 2021-06-29 00:28:32 +01:00
832a6ffe75 ci(github): cache god modules to speed up emacs-builder compile time 2021-06-29 00:27:38 +01:00
72fc6962a7 chore(deps): update build-emacs-for-macos to 0.5.2
Should fix the recent build and signing issues with nightly builds.
2021-06-27 12:35:32 +01:00
d2d9494a44 chore(deps): update build-emacs-for-macos to 0.5.1 2021-06-27 02:36:42 +01:00
8d84df095a docs(readme): update with info about signing and notarization 2021-06-22 03:10:47 +01:00
6883fd0f12 Merge pull request #10 from jimeh/sign-and-notarize
feat(signing)!: sign, notarize and staple Emacs.app and disk image
2021-06-22 00:57:23 +01:00
ca4e7e2c44 feat(signing)!: sign, notarize and staple Emacs.app and disk image
Update the build-emacs-for-macos to v0.5.0, which includes a new
emacs-builder CLI tool written in Go, which handles signing, dmg
packaging, notarizing and stapling of Emacs builds. The main build
process is still handled by the old Ruby script for now however.

emacs-builder also includes plan and release commands, negating the need
for the our custom github-release CLI tool.

BREAKING CHANGE: Release assets are now signed *.dmg files instead
of *.tbz archives.
2021-06-22 00:55:31 +01:00
ffad4f21d2 docs(readme): update CLI usage section 2021-06-20 18:37:18 +01:00
b94cb495ae chore(deps): update build-emacs-for-macos to 0.4.16
- fix(compiling): improve portability of builds
- fix(native_comp): crash on launch when gcc homebrew package was not
  installed
2021-06-07 23:45:49 +01:00
d6fb7efc3a chore(deps): update build-emacs-for-macos to 0.4.15
Makes build script itself perform authenticated GitHub API calls when
GITHUB_TOKEN environment variable is set.
2021-05-31 23:27:59 +01:00
18 changed files with 641 additions and 860 deletions

247
.github/workflows/_build.yml vendored Normal file
View File

@@ -0,0 +1,247 @@
---
# Requires _prepare.yml re-usable workflow to have run.
name: _build
on:
workflow_call:
inputs:
artifact_prefix:
description: Artifact prefix
type: string
required: false
os:
description: GitHub Actions runner OS
type: string
required: true
git_ref:
description: Git ref to build
type: string
required: true
git_sha:
description: Override git SHA to build
type: string
required: false
build_args:
description: Custom arguments passed to build script
type: string
required: false
test_build_name:
description: "Test build name"
type: string
required: false
test_release_type:
description: "prerelease or draft"
type: string
required: false
default: "prerelease"
secrets:
APPLE_DEVELOPER_CERTIFICATE_P12_BASE64:
description: Base64 encoded Apple Developer Certificate
required: true
APPLE_DEVELOPER_CERTIFICATE_PASSWORD:
description: Password for Apple Developer Certificate
required: true
KEYCHAIN_PASSWORD:
description: Password to use for temporary local keychain on runner
required: true
AC_USERNAME:
description: Apple Connect Username
required: true
AC_PASSWORD:
description: Apple Connect Password
required: true
AC_PROVIDER:
description: Apple Connect Provider
required: true
AC_SIGN_IDENTITY:
description: Apple Connect Signing Identify
required: true
TAP_REPO_TOKEN:
description: Homebrew Tap Token
required: true
jobs:
prepare:
runs-on: ${{ inputs.os }}
outputs:
builder_sha: ${{ steps.builder_sha.outputs.sha }}
emacs_sha_override: ${{ steps.emacs_sha.outputs.sha }}
test_plan_args: ${{ steps.test_plan_args.outputs.args }}
steps:
- name: Download emacs-builder git SHA artifact
uses: actions/download-artifact@v2
with:
name: emacs-builder-git-sha
path: ./
- name: Store builder Git SHA
id: builder_sha
run: >-
echo "::set-output name=sha::$(cat emacs-builder-git-sha.txt)"
- name: Prepare plan test args
id: test_plan_args
if: ${{ inputs.test_build_name != '' }}
run: >-
echo "::set-output name=args::--test-build '${{ inputs.test_build_name }}' --test-release-type '${{ inputs.test_release_type }}'"
- name: Set git SHA override
id: emacs_sha
if: ${{ inputs.git_sha != '' }}
run: >-
echo "::set-output name=sha::--sha '${{ inputs.git_sha }}'"
plan:
needs: [prepare]
runs-on: ${{ inputs.os }}
outputs:
check: ${{ steps.check.outputs.result }}
steps:
- name: Download pre-built emacs-builder artifact
uses: actions/download-artifact@v2
with:
name: emacs-builder
path: bin
- name: Ensure emacs-builder is executable
run: chmod +x bin/emacs-builder
- name: Plan build
run: >-
bin/emacs-builder -l debug plan --output build-plan.yml
--output-dir '${{ github.workspace }}/builds'
${{ needs.prepare.outputs.test_plan_args }}
${{ needs.prepare.outputs.emacs_sha_override }}
'${{ inputs.git_ref }}'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Show plan
run: cat build-plan.yml
- name: Upload build-plan artifact
uses: actions/upload-artifact@v2
with:
name: ${{ inputs.artifact_prefix }}build-plan
path: build-plan.yml
if-no-files-found: error
- name: Check if planned release and asset already exist
id: check
continue-on-error: true
run: |
RESULT="$((bin/emacs-builder -l debug release --plan build-plan.yml check && echo 'ok') || echo 'fail')"
echo "::set-output name=result::$RESULT"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: echo 'Planned release already seems to exist.'
if: ${{ steps.check.outputs.result == 'fail' }}
build:
runs-on: ${{ inputs.os }}
needs: [prepare, plan]
# Only run if check for existing release and asset failed.
if: ${{ needs.plan.outputs.check == 'fail' }}
steps:
- name: Checkout build-emacs-for-macos repo
uses: actions/checkout@v2
with:
repository: jimeh/build-emacs-for-macos
ref: ${{ needs.prepare.outputs.builder_sha }}
path: builder
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7
- name: Update homebrew
run: brew update
- name: Install dependencies
run: make bootstrap-ci
working-directory: builder
- name: Download build-plan artifact
uses: actions/download-artifact@v2
with:
name: ${{ inputs.artifact_prefix }}build-plan
path: ./
- name: Build Emacs
run: >-
./builder/build-emacs-for-macos --plan build-plan.yml
--native-full-aot
${{ inputs.build_args }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload unsigned app artifact
uses: actions/upload-artifact@v2
with:
name: ${{ inputs.artifact_prefix }}unsigned-app
path: builds/*.tbz
if-no-files-found: error
- name: Upload Emacs source artifact
uses: actions/upload-artifact@v2
with:
name: ${{ inputs.artifact_prefix }}emacs-source
path: builder/tarballs/*.tgz
package:
runs-on: ${{ inputs.os }}
needs: [prepare, plan, build]
# Only run if check for existing release and asset failed.
steps:
- name: Install dependencies
run: |
brew install python
$(command -v pip3 || command -v pip) install --upgrade dmgbuild
- name: Download pre-built emacs-builder artifact
uses: actions/download-artifact@v2
with:
name: emacs-builder
path: bin
- name: Ensure emacs-builder is executable
run: chmod +x bin/emacs-builder
- name: Download build-plan artifact
uses: actions/download-artifact@v2
with:
name: ${{ inputs.artifact_prefix }}build-plan
path: ./
- name: Download unsigned app artifact
uses: actions/download-artifact@v2
with:
name: ${{ inputs.artifact_prefix }}unsigned-app
path: builds
- name: Extract unsigned app archive
run: |
find * -name '*.tbz' -exec tar xvjf "{}" \;
working-directory: builds
- name: Install the Apple signing certificate
run: |
# create variables
CERTIFICATE_PATH="$RUNNER_TEMP/build_certificate.p12"
KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db"
# import certificate and provisioning profile from secrets
echo -n "$CERT_BASE64" | base64 --decode --output "$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 to keychain
security import "$CERTIFICATE_PATH" -P "$CERT_PASSWORD" -A \
-t cert -f pkcs12 -k "$KEYCHAIN_PATH"
security list-keychain -d user -s "$KEYCHAIN_PATH"
env:
CERT_BASE64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }}
CERT_PASSWORD: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
- name: Sign, package and notarize build
run: >-
bin/emacs-builder -l debug package -v --plan build-plan.yml
--sign --remove-source-dir
env:
AC_USERNAME: ${{ secrets.AC_USERNAME }}
AC_PASSWORD: ${{ secrets.AC_PASSWORD }}
AC_PROVIDER: ${{ secrets.AC_PROVIDER }}
AC_SIGN_IDENTITY: ${{ secrets.AC_SIGN_IDENTITY }}
- name: Upload disk image artifacts
uses: actions/upload-artifact@v2
with:
name: dmg
path: |
builds/*.dmg
builds/*.sha*
if-no-files-found: error
- name: Clean up keychain used for signing certificate
if: ${{ always() }}
run: |
security delete-keychain "$RUNNER_TEMP/app-signing.keychain-db"

54
.github/workflows/_prepare.yml vendored Normal file
View File

@@ -0,0 +1,54 @@
---
name: _prepare
on:
workflow_call:
inputs:
builder_ref:
description: Git ref to checkout of build-emacs-for-macos
required: false
type: string
default: "v0.6.33"
secrets:
TAP_REPO_TOKEN:
description: Personal Access Token for Homebrew Tap repo
required: true
jobs:
emacs-builder:
# Use oldest version of macOS to ensure emacs-bulder binary is compatible
# with later versions of macOS.
runs-on: macos-10.15
steps:
- name: Checkout build-emacs-for-macos repo
uses: actions/checkout@v2
with:
repository: jimeh/build-emacs-for-macos
ref: ${{ inputs.builder_ref }}
path: builder
- name: Store builder Git SHA
run: |
git rev-parse HEAD > emacs-builder-git-sha.txt
working-directory: builder
- name: Upload builder git SHA artifact
uses: actions/upload-artifact@v2
with:
name: emacs-builder-git-sha
path: builder/emacs-builder-git-sha.txt
if-no-files-found: error
- uses: actions/setup-go@v2
with:
go-version: 1.16
- uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('builder/**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
- name: Build emacs-builder tool
run: make build
working-directory: builder
- name: Upload emacs-builder artifact
uses: actions/upload-artifact@v2
with:
name: emacs-builder
path: builder/bin/emacs-builder
if-no-files-found: error

57
.github/workflows/_release.yml vendored Normal file
View File

@@ -0,0 +1,57 @@
---
# Requires _prepare.yml and _build.yml re-usable workflows to have run.
name: _release
on:
workflow_call:
inputs:
plan_artifact:
description: Name of artifact containing a emacs-builder plan yaml file
type: string
required: true
dmg_artifact:
description: Name of artifact containing a *.dmg files to release
type: string
required: true
secrets:
TAP_REPO_TOKEN:
description: Personal Access Token for Homebrew Tap repo
required: true
jobs:
github:
runs-on: macos-11
steps:
- name: Download pre-built emacs-builder artifact
uses: actions/download-artifact@v2
with:
name: emacs-builder
path: bin
- name: Ensure emacs-builder is executable
run: chmod +x bin/emacs-builder
- name: Download build-plan.yml artifact
uses: actions/download-artifact@v2
with:
name: ${{ inputs.plan_artifact }}
path: ./
- name: Download disk image artifacts
id: dmg
continue-on-error: true
uses: actions/download-artifact@v2
with:
name: ${{ inputs.dmg_artifact }}
path: builds
- name: Publish disk images to a GitHub Release
if: ${{ steps.dmg.outputs.result != 'fail' }}
run: >-
bin/emacs-builder -l debug release --plan build-plan.yml publish
$(find builds -name '*.dmg' -or -name '*.sha256')
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Trigger update casks workflow in homebrew tap
if: ${{ steps.dmg.outputs.result != 'fail' && inputs.testBuildName == '' }}
run: >-
gh workflow run --repo jimeh/homebrew-emacs-builds update-casks.yml
env:
GITHUB_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}
- run: echo 'No DMG artifact available, was there a new commit to build?'
if: ${{ steps.dmg.outputs.result == 'fail' }}

View File

@@ -1,84 +1,72 @@
---
name: Build
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
inputs:
gitRef:
description: "Emacs git ref to build"
git_ref:
description: Emacs git ref to build
required: true
default: "master"
extraPlanArgs:
Description: "Extra plan args"
git_sha:
description: Override Emacs git commit SHA to build
required: false
builder_ref:
description: "Git ref to checkout of build-emacs-for-macos"
required: true
default: "master"
builder_args:
description: Custom arguments passed to build script
required: false
default: ""
extraBuildArgs:
Description: "Extra build args"
os:
description: 'Runner OS ("macos-10.15" or "macos-11")'
required: true
default: "macos-10.15"
test_build_name:
description: "Test build name"
required: false
default: ""
extraReleaseArgs:
Description: "Extra release args"
test_release_type:
description: "prerelease or draft"
required: false
default: ""
jobs:
build-and-publish:
runs-on: macos-10.15
steps:
- name: Checkout emacs-builds repo
uses: actions/checkout@v2
with:
path: releaser
- name: Checkout build-emacs-for-macos repo
uses: actions/checkout@v2
with:
repository: jimeh/build-emacs-for-macos
ref: "0.4.14"
path: builder
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7
- uses: actions/setup-go@v2
with:
go-version: 1.16
- name: Compile github-release tool
run: >-
go build -o ./github-release ./cmd/github-release
working-directory: releaser
- name: Plan build
run: >-
./releaser/github-release --plan plan.yml plan
--work-dir '${{ github.workspace }}'
${{ github.event.inputs.extraPlanArgs }}
${{ github.event.inputs.gitRef }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Show plan
run: >-
cat plan.yml
- name: Check if planned release and asset already exist
id: check
continue-on-error: true
run: >-
./releaser/github-release --plan plan.yml check
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
if: steps.check.outcome == 'failure'
run: >-
brew bundle --file=builder/Brewfile
- name: Build Emacs
if: steps.check.outcome == 'failure'
run: >-
./builder/build-emacs-for-macos --plan=plan.yml
--work-dir '${{ github.workspace }}'
--native-full-aot
${{ github.event.inputs.extraReleaseArgs }}
- name: Publish release
if: steps.check.outcome == 'failure'
run: >-
./releaser/github-release --plan plan.yml publish
${{ github.event.inputs.extraReleaseArgs }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
prepare:
name: Prepare
uses: jimeh/emacs-builds/.github/workflows/_prepare.yml@main
with:
builder_ref: ${{ github.event.inputs.builder_ref }}
secrets:
TAP_REPO_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}
build:
name: Build
needs: [prepare]
uses: jimeh/emacs-builds/.github/workflows/_build.yml@main
with:
os: macos-10.15
git_ref: ${{ github.event.inputs.git_ref }}
git_sha: ${{ github.event.inputs.git_sha }}
build_args: ${{ github.event.inputs.builder_args }}
test_build_name: ${{ github.event.inputs.test_build_name }}
test_release_type: ${{ github.event.inputs.test_release_type }}
secrets:
APPLE_DEVELOPER_CERTIFICATE_P12_BASE64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }}
APPLE_DEVELOPER_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
AC_USERNAME: ${{ secrets.AC_USERNAME }}
AC_PASSWORD: ${{ secrets.AC_PASSWORD }}
AC_PROVIDER: ${{ secrets.AC_PROVIDER }}
AC_SIGN_IDENTITY: ${{ secrets.AC_SIGN_IDENTITY }}
TAP_REPO_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}
release:
name: Release
needs: [build]
uses: jimeh/emacs-builds/.github/workflows/_release.yml@main
with:
plan_artifact: build-plan
dmg_artifact: dmg
secrets:
TAP_REPO_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}

45
.github/workflows/nightly-emacs-28.yml vendored Normal file
View File

@@ -0,0 +1,45 @@
---
name: Nightly (emacs-28)
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
inputs:
git_sha:
description: Override Emacs git commit SHA to build
required: false
jobs:
prepare:
name: Prepare
uses: jimeh/emacs-builds/.github/workflows/_prepare.yml@main
secrets:
TAP_REPO_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}
build:
name: Build
needs: [prepare]
uses: jimeh/emacs-builds/.github/workflows/_build.yml@main
with:
os: macos-10.15
git_ref: emacs-28
git_sha: ${{ github.event.inputs.git_sha }}
secrets:
APPLE_DEVELOPER_CERTIFICATE_P12_BASE64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }}
APPLE_DEVELOPER_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
AC_USERNAME: ${{ secrets.AC_USERNAME }}
AC_PASSWORD: ${{ secrets.AC_PASSWORD }}
AC_PROVIDER: ${{ secrets.AC_PROVIDER }}
AC_SIGN_IDENTITY: ${{ secrets.AC_SIGN_IDENTITY }}
TAP_REPO_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}
release:
name: Release
needs: [build]
uses: jimeh/emacs-builds/.github/workflows/_release.yml@main
with:
plan_artifact: build-plan
dmg_artifact: dmg
secrets:
TAP_REPO_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}

45
.github/workflows/nightly-master.yml vendored Normal file
View File

@@ -0,0 +1,45 @@
---
name: Nightly (master)
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
inputs:
git_sha:
description: Override Emacs git commit SHA to build
required: false
jobs:
prepare:
name: Prepare
uses: jimeh/emacs-builds/.github/workflows/_prepare.yml@main
secrets:
TAP_REPO_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}
build:
name: Build
needs: [prepare]
uses: jimeh/emacs-builds/.github/workflows/_build.yml@main
with:
os: macos-10.15
git_ref: master
git_sha: ${{ github.event.inputs.git_sha }}
secrets:
APPLE_DEVELOPER_CERTIFICATE_P12_BASE64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }}
APPLE_DEVELOPER_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
AC_USERNAME: ${{ secrets.AC_USERNAME }}
AC_PASSWORD: ${{ secrets.AC_PASSWORD }}
AC_PROVIDER: ${{ secrets.AC_PROVIDER }}
AC_SIGN_IDENTITY: ${{ secrets.AC_SIGN_IDENTITY }}
TAP_REPO_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}
release:
name: Release
needs: [build]
uses: jimeh/emacs-builds/.github/workflows/_release.yml@main
with:
plan_artifact: build-plan
dmg_artifact: dmg
secrets:
TAP_REPO_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}

View File

@@ -1,103 +0,0 @@
---
name: Test Build
on:
workflow_dispatch:
inputs:
gitRef:
description: "Emacs git ref to build"
required: true
default: "master"
releaseToolGitRef:
description: "Git ref to checkout of emacs-builds (github-release)"
required: true
default: "main"
buildScriptGitRef:
description: "Git ref to checkout of build-emacs-for-macos"
required: true
default: "master"
testBuildName:
description: "Test build name"
required: false
default: ""
testReleaseType:
description: "prerelease or draft"
required: true
default: "prerelease"
extraPlanArgs:
Description: "Extra plan args"
required: false
default: ""
extraBuildArgs:
Description: "Extra build args"
required: false
default: ""
extraReleaseArgs:
Description: "Extra release args"
required: false
default: ""
jobs:
build-and-publish:
runs-on: macos-10.15
steps:
- name: Checkout emacs-builds repo
uses: actions/checkout@v2
with:
ref: ${{ github.event.inputs.releaseToolGitRef }}
path: releaser
- name: Checkout build-emacs-for-macos repo
uses: actions/checkout@v2
with:
repository: jimeh/build-emacs-for-macos
ref: ${{ github.event.inputs.buildScriptGitRef }}
path: builder
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7
- uses: actions/setup-go@v2
with:
go-version: 1.16
- name: Compile github-release tool
run: >-
go build -o ./github-release ./cmd/github-release
working-directory: releaser
- name: Plan build
run: >-
./releaser/github-release --plan plan.yml plan
--work-dir '${{ github.workspace }}'
--test-build
--test-build-name="${{ github.event.inputs.testBuildName }}"
--test-release-type="${{ github.event.inputs.testReleaseType }}"
${{ github.event.inputs.extraPlanArgs }}
${{ github.event.inputs.gitRef }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Show plan
run: >-
cat plan.yml
- name: Check if planned release and asset already exist
id: check
continue-on-error: true
run: >-
./releaser/github-release --plan plan.yml check
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
if: steps.check.outcome == 'failure'
run: >-
brew bundle --file=builder/Brewfile
- name: Build Emacs
if: steps.check.outcome == 'failure'
run: >-
./builder/build-emacs-for-macos --plan=plan.yml
--work-dir '${{ github.workspace }}'
--native-full-aot
${{ github.event.inputs.extraReleaseArgs }}
- name: Publish release
if: steps.check.outcome == 'failure'
run: >-
./releaser/github-release --plan plan.yml publish
--release-sha="${{ github.event.inputs.releaseToolGitRef }}"
${{ github.event.inputs.extraReleaseArgs }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

35
.github/workflows/update-metadata.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
---
name: Update Metadata
concurrency: jimeh/emacs-builds/update-metadata
on:
schedule:
- cron: "0 0,12 * * *"
workflow_dispatch:
jobs:
update-metadata:
runs-on: ubuntu-latest
steps:
- name: Checkout tap repository main branch
uses: actions/checkout@v2
with:
ref: meta
- uses: actions/setup-go@v2
with:
go-version: 1.17
- uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('builder/**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
- name: update total downloads shield JSON
run: go run . badges downloads -o total-downloads/shield.json
- name: commit and push changes to meta branch
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "chore(meta): update metadata files"
commit_user_name: github-actions[bot]
commit_user_email: github-actions[bot]@users.noreply.github.com
commit_author: >-
github-actions[bot] <github-actions[bot]@users.noreply.github.com>
skip_dirty_check: false

153
README.md
View File

@@ -7,31 +7,26 @@
</h1>
<p align="center">
<a href="https://github.com/jimeh/emacs-builds/releases/latest">
<img alt="GitHub release (latest)" src="https://img.shields.io/github/v/release/jimeh/emacs-builds?style=flat&label=nightly&color=%237F5AB6&logo=GNU%20Emacs&logoColor=white">
</a>
<a href="https://github.com/jimeh/emacs-builds/issues">
<img alt="GitHub issues" src="https://img.shields.io/github/issues-raw/jimeh/emacs-builds?style=flat&logo=github&colorColor=white">
</a>
<a href="https://github.com/jimeh/emacs-builds/pulls">
<img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr-raw/jimeh/emacs-builds?style=flat&logo=github&colorColor=white">
</a>
<a href="https://github.com/jimeh/emacs-builds/releases">
<img alt="GitHub all releases" src="https://img.shields.io/github/downloads/jimeh/emacs-builds/total?style=flat&logoColor=white&logo=data%3Aimage%2Fpng%3Bbase64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAEsmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjE0IgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iMTQiCiAgIGV4aWY6Q29sb3JTcGFjZT0iMSIKICAgdGlmZjpJbWFnZVdpZHRoPSIxNCIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMTQiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249IjcyLjAiCiAgIHRpZmY6WVJlc29sdXRpb249IjcyLjAiCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgeG1wOk1vZGlmeURhdGU9IjIwMjEtMDUtMThUMDE6MjU6NTQrMDE6MDAiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMDUtMThUMDE6MjU6NTQrMDE6MDAiPgogICA8eG1wTU06SGlzdG9yeT4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgc3RFdnQ6YWN0aW9uPSJwcm9kdWNlZCIKICAgICAgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWZmaW5pdHkgRGVzaWduZXIgMS45LjMiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMDUtMThUMDE6MjU6NTQrMDE6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI%2FPnP7qIwAAAGBaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRzytEURTHP2aIGBEWFhaThtWM%2FKiJjTLSUJM0RhlsZp55M2rezOu9N2myVbaKEhu%2FFvwFbJW1UkRKdsqa2KDnPKNGMud27vnc773ndO%2B54IplFc2s7gUtZxnRcMg7G5%2Fz1j5SQwvQzEBCMfWRqakIFe3thionXgWcWpXP%2FWsNiylTgao64WFFNyzhceHIsqU7vCncpmQSi8LHwn5DLih87ejJEj85nC7xh8NGLDoKrmZhb%2FoXJ3%2BxkjE0YXk5Pi1bUH7u47zEk8rNTEvsFO%2FAJEqYEF4mGGOUIH0MyRwkQD89sqJCfu93%2FiR5yVVk1ilisESaDBZ%2BUQtSPSVRFT0lI0vR6f%2FfvprqQH%2BpuicENQ%2B2%2FdIFtRvwuW7b7%2Fu2%2FXkA7ns4y5Xz83sw%2BCr6elnz7ULTKpycl7XkFpyuQfudnjAS35Jb3KWq8HwEjXFovYT6%2BVLPfvY5vIXYinzVBWzvQLecb1r4AjtZZ9JRQIRfAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAhUlEQVQokb3QsQnDMBRF0Y9J6QGylCt7GI%2BRPdJ4BIMXyA4pM0KKk0YCYawogZAHH4Tuvw%2BhiEowY67xarBirfHu68afijjXFvesK8AQEXeMB9KU2HDU2GPDE2P%2BHEzpbkNfe04pP9K8lw7knLa0k69pPpP%2BFyzaWfL%2BqXAvEXFr9K%2F58AJFIbDLRt48DAAAAABJRU5ErkJggg%3D%3D&color=blue&label=total%20downloads">
</a>
<a href="https://github.com/jimeh/emacs-builds/releases/latest"><img alt="GitHub release (stable)" src="https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjimeh%2Fhomebrew-emacs-builds%2Fmeta%2FCasks%2Femacs-app%2Fshield.json"></a>
<a href="https://github.com/jimeh/emacs-builds/releases?q=pretest&expanded=true"><img alt="GitHub release (pretest)" src="https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjimeh%2Fhomebrew-emacs-builds%2Fmeta%2FCasks%2Femacs-app-pretest%2Fshield.json"></a>
<a href="https://github.com/jimeh/emacs-builds/releases?q=master&expanded=true"><img alt="GitHub release (nightly)" src="https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjimeh%2Fhomebrew-emacs-builds%2Fmeta%2FCasks%2Femacs-app-nightly%2Fshield.json"></a>
<a href="https://github.com/jimeh/emacs-builds/releases?q=emacs-28&expanded=true"><img alt="GitHub release (nightly@emacs-28)" src="https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjimeh%2Fhomebrew-emacs-builds%2Fmeta%2FCasks%2Femacs-app-nightly-28%2Fshield.json"></a>
<a href="https://github.com/jimeh/emacs-builds/issues/7"><img alt="GitHub release (known good nightly)" src="https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjimeh%2Fhomebrew-emacs-builds%2Fmeta%2FCasks%2Femacs-app-good%2Fshield.json"></a>
<a href="https://github.com/jimeh/emacs-builds/issues"><img alt="GitHub issues" src="https://img.shields.io/github/issues-raw/jimeh/emacs-builds?style=flat&logo=github&logoColor=white"></a>
<a href="https://github.com/jimeh/emacs-builds/pulls"><img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr-raw/jimeh/emacs-builds?style=flat&logo=github&logoColor=white"></a>
<a href="https://github.com/jimeh/emacs-builds/releases"><img alt="GitHub all releases" src="https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjimeh%2Femacs-builds%2Fmeta%2Ftotal-downloads%2Fshield.json"></a>
</p>
<p align="center">
<strong>
Nightly binary builds of Emacs for macOS as a self-contained Emacs.app,
with native-compilation.
Self-contained Emacs.app builds for macOS, with native-compilation support.
</strong>
</p>
## Features
- Self-contained Emacs.app application bundle, with no external dependencies.
- Native-compilation ([gccemacs][]).
- Native compilation ([gccemacs][]), only in Emacs 28.x and later builds.
- Native JSON parsing via libjansson.
- SVG rendering via librsvg.
- Various image formats are supported via macOS native image APIs.
@@ -44,8 +39,8 @@
- Emacs source is fetched from the [emacs-mirror/emacs][] GitHub repository.
- Build creation is transparent and public through the use of GitHub Actions,
allowing anyone to inspect git commit SHAs, full source code, and exact
commands used to produce a build. This is especially important right now as
builds are not yet signed and notarized.
commands used to produce a build.
- Emacs.app is signed with a developer certificate and notarized by Apple.
- Uses [build-emacs-for-macos][] to build the self-contained application bundle.
[build-emacs-for-macos]: https://github.com/jimeh/build-emacs-for-macos
@@ -59,60 +54,95 @@
## System Requirements
- Intel-based Mac running macOS 10.15.x or later.
- macOS 10.15.x or later (uses Rosetta2 on Apple Silicon machines).
- Xcode Command Line Tools for native compilation (Emacs 28.x and later).
## Downloads
## Installation
See the [Releases][] page to download latest builds.
### Manual Download
Nightly builds of Emacs are for the part just fine, but if you don't like living
too close to the edge, see issue [#7 Known Good Nightly Builds][7] for a list of
recent nightly builds which have been actively used by a living being without
any issues.
See the [Releases][] page to download latest builds, or [here](latest) for the
latest stable release.
Nightly builds of Emacs are for the most part just fine, but if you don't like
living too close to the edge, see issue [#7 Known Good Nightly Builds][7] for a
list of recent nightly builds which have been actively used by a living being
for a day or two without any obvious issues.
[releases]: https://github.com/jimeh/emacs-builds/releases
[latest]: https://github.com/jimeh/emacs-builds/releases/latest
[7]: https://github.com/jimeh/emacs-builds/issues/7
## Untrusted Application
### Homebrew Cask
Currently builds are not signed or notarized, meaning macOS cannot verify
Emacs.app came from a trusted developer, and by default you are not given an
option to trust the app and open it.
1. Install the
[`jimeh/emacs-builds`](https://github.com/jimeh/homebrew-emacs-builds)
Homebrew tap:
```
brew tap jimeh/emacs-builds
```
2. Install one of the available casks:
- `emacs-app` for the latest stable release of Emacs (includes native-comp
since v28.1):
```
brew install --cask emacs-app
```
- `emacs-app-pretest` for the latest pretest build from Emacs:
```
brew install --cask emacs-app-pretest
```
- `emacs-app-nightly` for the latest nightly build from Emacs' `master`
branch:
```
brew install --cask emacs-app-nightly
```
- `emacs-app-good` for the latest known good nightly build listed on [#7][7]:
```
brew install --cask emacs-app-good
```
- `emacs-app-nightly-28` for the latest Emacs 28.x nightly build from the
`emacs-28` branch:
```
brew install --cask emacs-app-nightly-28
```
Simplest way around this is to right-click (or control-click) on the Emacs app
in Finder and select "Open". You will then be given the same warning as before,
but with a "Open" button now available to trust and open the app. After that you
can open the application like normal without any warnings.
Builds will soon be signed and notarized, progress is tracked in [Issue #1][1].
[1]: https://github.com/jimeh/emacs-builds/issues/1
[7]: https://github.com/jimeh/emacs-builds/issues/7
## Use Emacs.app as `emacs` CLI Tool
As the application bundle is self-contained, the main executable needs to be run
from within the application bundle. This means a simple symlink to
`Emacs.app/Contents/MacOS/Emacs` will not work. Instead the best approach is to
create a shell alias called `emacs` pointing to the right place.
### Installed via Homebrew Cask
For example, this will expose both `emacs` and `emacsclient`:
The cask installation method sets up CLI usage automatically by exposing a
`emacs` command. However it will launch Emacs into GUI mode. To instead have
`emacs` in your terminal open a terminal instance of Emacs, add the following
alias to your shell setup:
```bash
if [ -f "/Applications/Emacs.app/Contents/MacOS/Emacs" ]; then
export EMACS="/Applications/Emacs.app/Contents/MacOS/Emacs"
alias emacs="$EMACS -nw"
fi
alias emacs="emacs -nw"
```
if [ -f "/Applications/Emacs.app/Contents/MacOS/bin/emacsclient" ]; then
alias emacsclient="/Applications/Emacs.app/Contents/MacOS/bin/emacsclient"
### Installed Manually
Builds come with a custom `emacs` shell script launcher for use from the command
line, located next to `emacsclient` in `Emacs.app/Contents/MacOS/bin`.
The custom `emacs` script makes sure to use the main
`Emacs.app/Contents/MacOS/Emacs` executable from the correct path, ensuring it
finds all the relevant dependencies within the Emacs.app bundle, regardless of
if it's exposed via `PATH` or symlinked from elsewhere.
To use it, simply add `Emacs.app/Contents/MacOS/bin` to your `PATH`. For
example, if you place Emacs.app in `/Applications`:
```bash
if [ -d "/Applications/Emacs.app/Contents/MacOS/bin" ]; then
export PATH="/Applications/Emacs.app/Contents/MacOS/bin:$PATH"
alias emacs="emacs -nw" # Always launch "emacs" in terminal mode.
fi
```
Setting the `EMACS` variable to the binary path seems to be a good idea, as some
tools seem to use it to figure out the path to Emacs' executable, including
[doom-emacs][]' `doom` CLI tool.
[doom-emacs]: https://github.com/hlissner/doom-emacs
If you want `emacs` in your terminal to launch a GUI instance of Emacs, don't
use the alias from the above example.
## Build Process
@@ -126,6 +156,7 @@ Actions.
https://github.com/jimeh/emacs-builds/blob/main/.github/workflows/build.yml
Full history for all builds is available on GitHub Actions [here][actions].
Build logs are only retained by GitHub for 90 days though.
[actions]: https://github.com/jimeh/emacs-builds/actions
@@ -134,6 +165,24 @@ commit from the `master` branch of the [emacs-mirror/emacs][] repository. This
means a nightly build will only be produced if there have been new commits since
the last nightly build.
## Application Signing / Trust
As of June 21st, 2021, all builds are fully signed and notarized. The signing
certificate used is: `Developer ID Application: Jim Myhrberg (5HX66GF82Z)`
To verify the application signature and notarization, you can use `spctl`:
```bash
$ spctl -vvv --assess --type exec /Applications/Emacs.app
/Applications/Emacs.app: accepted
source=Notarized Developer ID
origin=Developer ID Application: Jim Myhrberg (5HX66GF82Z)
```
All builds also come with a SHA256 checksum file, which itself can be double
checked against the SHA256 checksum log output from the packaging step of the
GitHub Actions workflow run which produced the build.
[emacs-mirror/emacs]: https://github.com/emacs-mirror/emacs
## Issues / To-Do

View File

@@ -1,57 +0,0 @@
package main
import (
"fmt"
"net/http"
"path/filepath"
"github.com/urfave/cli/v2"
)
func checkCmd() *cli.Command {
return &cli.Command{
Name: "check",
Usage: "Check if GitHub release and asset exists",
UsageText: "github-release [global options] check [options]",
Action: actionHandler(checkAction),
}
}
func checkAction(c *cli.Context, opts *globalOptions) error {
gh := opts.gh
repo := opts.repo
plan, err := LoadPlan(opts.plan)
if err != nil {
return err
}
fmt.Printf(
"==> Checking github.com/%s for release: %s\n",
repo.String(), plan.Release.Name,
)
release, resp, err := gh.Repositories.GetReleaseByTag(
c.Context, repo.Owner, repo.Name, plan.Release.Name,
)
if err != nil {
if resp.StatusCode == http.StatusNotFound {
return fmt.Errorf("release %s does not exist", plan.Release.Name)
} else {
return err
}
}
fmt.Println(" -> Release exists")
filename := filepath.Base(plan.Archive)
fmt.Printf("==> Checking release for asset: %s\n", filename)
for _, a := range release.Assets {
if a.Name != nil && filename == *a.Name {
fmt.Println(" -> Asset exists")
return nil
}
}
return fmt.Errorf("release does contain asset: %s", filename)
}

View File

@@ -1,46 +0,0 @@
package main
import (
"fmt"
"time"
"github.com/google/go-github/v35/github"
)
type Commit struct {
Repo *Repo `yaml:"repo"`
Ref string `yaml:"ref"`
SHA string `yaml:"sha"`
Date *time.Time `yaml:"date"`
Author string `yaml:"author"`
Committer string `yaml:"committer"`
Message string `yaml:"message"`
}
func NewCommit(repo *Repo, ref string, rc *github.RepositoryCommit) *Commit {
return &Commit{
Repo: repo,
Ref: ref,
SHA: rc.GetSHA(),
Date: rc.GetCommit().GetCommitter().Date,
Author: fmt.Sprintf(
"%s <%s>",
rc.GetCommit().GetAuthor().GetName(),
rc.GetCommit().GetAuthor().GetEmail(),
),
Committer: fmt.Sprintf(
"%s <%s>",
rc.GetCommit().GetCommitter().GetName(),
rc.GetCommit().GetCommitter().GetEmail(),
),
Message: rc.GetCommit().GetMessage(),
}
}
func (s *Commit) ShortSHA() string {
return s.SHA[0:7]
}
func (s *Commit) DateString() string {
return s.Date.Format("2006-01-02")
}

View File

@@ -1,22 +0,0 @@
package main
import (
"context"
"net/http"
"github.com/google/go-github/v35/github"
"golang.org/x/oauth2"
)
func NewGitHubClient(ctx context.Context, token string) *github.Client {
var tc *http.Client
if token != "" {
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: token},
)
tc = oauth2.NewClient(ctx, ts)
}
return github.NewClient(tc)
}

View File

@@ -1,74 +0,0 @@
package main
import (
"fmt"
"os"
"github.com/google/go-github/v35/github"
"github.com/urfave/cli/v2"
)
var app = &cli.App{
Name: "github-release",
Usage: "manage GitHub releases",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "github-token",
Aliases: []string{"t"},
Usage: "GitHub API Token (read from GITHUB_TOKEN if set)",
},
&cli.StringFlag{
Name: "release-repo",
Aliases: []string{"r"},
Usage: "Owner/name of GitHub repo to publish releases to",
EnvVars: []string{"GITHUB_REPOSITORY"},
Value: "jimeh/emacs-builds",
},
&cli.PathFlag{
Name: "plan",
Aliases: []string{"p"},
Usage: "Load plan from `FILE`",
EnvVars: []string{"BUILD_PLAN"},
Required: true,
TakesFile: true,
},
},
Commands: []*cli.Command{
checkCmd(),
publishCmd(),
planCmd(),
},
}
type globalOptions struct {
gh *github.Client
repo *Repo
plan string
}
func actionHandler(
f func(*cli.Context, *globalOptions) error,
) func(*cli.Context) error {
return func(c *cli.Context) error {
token := c.String("github-token")
if t := os.Getenv("GITHUB_TOKEN"); t != "" {
token = t
}
opts := &globalOptions{
gh: NewGitHubClient(c.Context, token),
repo: NewRepo(c.String("release-repo")),
plan: c.String("plan"),
}
return f(c, opts)
}
}
func main() {
err := app.Run(os.Args)
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: %s\n", err.Error())
os.Exit(1)
}
}

View File

@@ -1,40 +0,0 @@
package main
import (
"os/exec"
"strings"
)
type OSInfo struct {
Name string `yaml:"name"`
Version string `yaml:"version"`
Arch string `yaml:"arch"`
}
func NewOSInfo() (*OSInfo, error) {
version, err := exec.Command("sw_vers", "-productVersion").CombinedOutput()
if err != nil {
return nil, err
}
arch, err := exec.Command("uname", "-m").CombinedOutput()
if err != nil {
return nil, err
}
return &OSInfo{
Name: "macOS",
Version: strings.TrimSpace(string(version)),
Arch: strings.TrimSpace(string(arch)),
}, nil
}
func (s *OSInfo) ShortVersion() string {
parts := strings.Split(s.Version, ".")
max := len(parts)
if max > 2 {
max = 2
}
return strings.Join(parts[0:max], ".")
}

View File

@@ -1,33 +0,0 @@
package main
import (
"os"
"gopkg.in/yaml.v3"
)
type Release struct {
Name string `yaml:"name"`
Title string `yaml:"title,omitempty"`
Draft bool `yaml:"draft,omitempty"`
Pre bool `yaml:"prerelease,omitempty"`
}
type Plan struct {
Commit *Commit `yaml:"commit"`
OS *OSInfo `yaml:"os"`
Release *Release `yaml:"release"`
Archive string `yaml:"archive"`
}
func LoadPlan(filename string) (*Plan, error) {
b, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
plan := &Plan{}
err = yaml.Unmarshal(b, plan)
return plan, err
}

View File

@@ -1,142 +0,0 @@
package main
import (
"bytes"
"fmt"
"os"
"path/filepath"
"regexp"
"github.com/urfave/cli/v2"
"gopkg.in/yaml.v3"
)
var nonAlphaNum = regexp.MustCompile(`[^\w-_]+`)
func planCmd() *cli.Command {
wd, err := os.Getwd()
if err != nil {
wd = ""
}
return &cli.Command{
Name: "plan",
Usage: "Plan if GitHub release and asset exists",
UsageText: "github-release [global options] plan [<branch/tag>]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "emacs-mirror-repo",
Usage: "Github owner/repo to get Emacs commit info from",
Aliases: []string{"e"},
EnvVars: []string{"EMACS_MIRROR_REPO"},
Value: "emacs-mirror/emacs",
},
&cli.StringFlag{
Name: "work-dir",
Usage: "Github owner/repo to get Emacs commit info from",
Value: wd,
},
&cli.StringFlag{
Name: "sha",
Usage: "Override commit SHA of specified git branch/tag",
},
&cli.BoolFlag{
Name: "test-build",
Usage: "Plan a test build, which is published to a draft " +
"\"test-builds\" release",
},
&cli.StringFlag{
Name: "test-build-name",
Usage: "Set a unique name to distinguish the ",
},
&cli.StringFlag{
Name: "test-release-type",
Value: "prerelease",
Usage: "Type of release when doing a test-build " +
"(prerelease or draft)",
},
},
Action: actionHandler(planAction),
}
}
func planAction(c *cli.Context, opts *globalOptions) error {
gh := opts.gh
planFile := opts.plan
repo := NewRepo(c.String("emacs-mirror-repo"))
buildsDir := filepath.Join(c.String("work-dir"), "builds")
ref := c.Args().Get(0)
if ref == "" {
ref = "master"
}
lookupRef := ref
if s := c.String("sha"); s != "" {
lookupRef = s
}
repoCommit, _, err := gh.Repositories.GetCommit(
c.Context, repo.Owner, repo.Name, lookupRef,
)
if err != nil {
return err
}
commit := NewCommit(repo, ref, repoCommit)
osInfo, err := NewOSInfo()
if err != nil {
return err
}
cleanRef := sanitizeString(ref)
cleanOS := sanitizeString(osInfo.Name + "-" + osInfo.ShortVersion())
cleanArch := sanitizeString(osInfo.Arch)
release := &Release{
Name: fmt.Sprintf(
"Emacs.%s.%s.%s",
commit.DateString(), commit.ShortSHA(), cleanRef,
),
}
archiveName := fmt.Sprintf(
"Emacs.%s.%s.%s.%s.%s",
commit.DateString(), commit.ShortSHA(), cleanRef, cleanOS, cleanArch,
)
if c.Bool("test-build") {
release.Title = "Test Builds"
release.Name = "test-builds"
if c.String("test-release-type") == "draft" {
release.Draft = true
} else {
release.Pre = true
}
archiveName += ".test"
if t := c.String("test-build-name"); t != "" {
archiveName += "." + sanitizeString(t)
}
}
plan := &Plan{
Commit: commit,
OS: osInfo,
Release: release,
Archive: filepath.Join(buildsDir, archiveName+".tbz"),
}
buf := bytes.Buffer{}
enc := yaml.NewEncoder(&buf)
enc.SetIndent(2)
err = enc.Encode(plan)
if err != nil {
return err
}
return os.WriteFile(planFile, buf.Bytes(), 0666)
}
func sanitizeString(s string) string {
return nonAlphaNum.ReplaceAllString(s, "-")
}

View File

@@ -1,196 +0,0 @@
package main
import (
"crypto/sha256"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"github.com/google/go-github/v35/github"
"github.com/urfave/cli/v2"
)
func publishCmd() *cli.Command {
return &cli.Command{
Name: "publish",
Usage: "publish a release",
UsageText: "github-release [global-options] publish [options]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "release-sha",
Aliases: []string{"s"},
Usage: "Git SHA of repo to create release on",
EnvVars: []string{"GITHUB_SHA"},
},
},
Action: actionHandler(publishAction),
}
}
func publishAction(c *cli.Context, opts *globalOptions) error {
gh := opts.gh
repo := opts.repo
plan, err := LoadPlan(opts.plan)
if err != nil {
return err
}
releaseSHA := c.String("release-sha")
assetBaseName := filepath.Base(plan.Archive)
assetSumFile := plan.Archive + ".sha256"
if _, err := os.Stat(assetSumFile); os.IsNotExist(err) {
fmt.Printf("==> Generating SHA256 sum for %s\n", assetBaseName)
assetSum, err := fileSHA256(plan.Archive)
if err != nil {
return err
}
content := fmt.Sprintf("%s %s", assetSum, assetBaseName)
err = os.WriteFile(assetSumFile, []byte(content), 0666)
if err != nil {
return err
}
fmt.Printf(" -> Done: %s\n", assetSum)
}
tagName := plan.Release.Name
name := plan.Release.Title
if name == "" {
name = tagName
}
fmt.Printf("==> Checking release %s\n", tagName)
release, resp, err := gh.Repositories.GetReleaseByTag(
c.Context, repo.Owner, repo.Name, plan.Release.Name,
)
if err != nil {
if resp.StatusCode == http.StatusNotFound {
fmt.Println(" -> Release not found, creating...")
prerelease := false
if !plan.Release.Draft && plan.Release.Pre {
prerelease = true
}
release, _, err = gh.Repositories.CreateRelease(
c.Context, repo.Owner, repo.Name, &github.RepositoryRelease{
Name: &name,
TagName: &tagName,
TargetCommitish: &releaseSHA,
Prerelease: &prerelease,
Draft: &plan.Release.Draft,
},
)
if err != nil {
return err
}
} else {
return err
}
}
if release.GetName() != name {
release.Name = &name
release, _, err = gh.Repositories.EditRelease(
c.Context, repo.Owner, repo.Name, release.GetID(), release,
)
if err != nil {
return err
}
}
if !plan.Release.Draft && release.GetPrerelease() != plan.Release.Pre {
release.Prerelease = &plan.Release.Pre
release, _, err = gh.Repositories.EditRelease(
c.Context, repo.Owner, repo.Name, release.GetID(), release,
)
if err != nil {
return err
}
}
assetFiles := []string{plan.Archive, assetSumFile}
for _, fileName := range assetFiles {
fileIO, err := os.Open(fileName)
if err != nil {
return err
}
defer fileIO.Close()
fileInfo, err := fileIO.Stat()
if err != nil {
return err
}
fileBaseName := filepath.Base(fileName)
assetExists := false
fmt.Printf("==> Checking asset %s\n", fileBaseName)
for _, a := range release.Assets {
if a.GetName() != fileBaseName {
continue
}
if a.GetSize() == int(fileInfo.Size()) {
fmt.Println(" -> Asset already exists")
assetExists = true
} else {
fmt.Println(
" -> Asset exists with wrong file size, deleting...",
)
_, err := gh.Repositories.DeleteReleaseAsset(
c.Context, repo.Owner, repo.Name, a.GetID(),
)
if err != nil {
return err
}
fmt.Println(" -> Done")
}
}
if !assetExists {
fmt.Println(" -> Asset missing, uploading...")
_, _, err = gh.Repositories.UploadReleaseAsset(
c.Context, repo.Owner, repo.Name, release.GetID(),
&github.UploadOptions{Name: fileBaseName},
fileIO,
)
if err != nil {
return err
}
fmt.Println(" -> Done")
}
}
fmt.Printf("==> Release available at: %s\n", release.GetHTMLURL())
return nil
}
func fileSHA256(filename string) (string, error) {
f, err := os.Open(filename)
if err != nil {
return "", err
}
defer f.Close()
h := sha256.New()
if _, err := io.Copy(h, f); err != nil {
return "", err
}
return fmt.Sprintf("%x", h.Sum(nil)), nil
}

View File

@@ -1,26 +0,0 @@
package main
import (
"fmt"
"strings"
)
type Repo struct {
URL string `yaml:"url"`
Owner string `yaml:"owner"`
Name string `yaml:"name"`
}
func NewRepo(ownerAndRepo string) *Repo {
parts := strings.SplitN(ownerAndRepo, "/", 2)
return &Repo{
URL: fmt.Sprintf("https://github.com/%s/%s", parts[0], parts[1]),
Owner: parts[0],
Name: parts[1],
}
}
func (s *Repo) String() string {
return s.Owner + "/" + s.Name
}