mirror of
https://github.com/jimeh/emacs-builds.git
synced 2026-02-19 10:46:40 +00:00
Compare commits
125 Commits
Emacs.2021
...
Emacs-29.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
dc1fdc91fc
|
|||
|
54e3c95ade
|
|||
|
f73a9c6c03
|
|||
|
f1e9216ef5
|
|||
|
1dd8a0a863
|
|||
|
f555605f93
|
|||
|
29e5fad03d
|
|||
|
11b57f3ed1
|
|||
|
01805db074
|
|||
|
2f408c834e
|
|||
|
9e2d7cb592
|
|||
|
d351fb20ce
|
|||
|
1fa1a3be36
|
|||
|
f1a232b18a
|
|||
|
86be2a1c30
|
|||
|
c2bba0dc34
|
|||
|
5991d0aaf2
|
|||
|
54ff01d673
|
|||
|
c1c4a03471
|
|||
|
adc48a6492
|
|||
|
14575aa77c
|
|||
| 3e3347dbec | |||
|
4f2d35c1ac
|
|||
|
2e80b79110
|
|||
|
88bfa2e603
|
|||
|
9934f47937
|
|||
|
|
13e8c9cc9e | ||
|
4204855346
|
|||
|
11b4492488
|
|||
|
a39895e8f6
|
|||
|
27b104d7b7
|
|||
|
0af73aaee1
|
|||
|
16087a80d0
|
|||
|
5835cd9712
|
|||
|
fe10ed4c34
|
|||
|
9615ab20a6
|
|||
|
cad73f3555
|
|||
|
30f92f734d
|
|||
|
83b08dc596
|
|||
|
f3213d9f5a
|
|||
|
b40f9e29c8
|
|||
|
e552de3cac
|
|||
|
9c731dac34
|
|||
|
bf358f42d5
|
|||
|
646d8775fb
|
|||
|
7e4ba5a9b8
|
|||
|
f82d299015
|
|||
|
fe0972217f
|
|||
|
a61807dea3
|
|||
|
d1e14bb59b
|
|||
|
06c6c2dbf2
|
|||
|
4561c9d4ce
|
|||
|
ebc4626270
|
|||
|
1e45868817
|
|||
|
8e6aa813f9
|
|||
|
f8bf0870a7
|
|||
|
b84115f251
|
|||
|
ffd1f41e19
|
|||
|
195a5f9775
|
|||
|
31172c47c3
|
|||
|
482bde4c00
|
|||
|
aab02b7454
|
|||
|
a8d3b9d473
|
|||
|
82353b98c5
|
|||
|
5b48a4ac70
|
|||
|
2c06f2c0c8
|
|||
|
1f67047d8d
|
|||
|
9809dd349e
|
|||
|
a4b07f609d
|
|||
|
1049006024
|
|||
|
1ba8aaecfd
|
|||
|
6561dc4a02
|
|||
|
dae8939b35
|
|||
|
baea14c975
|
|||
|
ee9e58b873
|
|||
|
04d20d42a4
|
|||
|
259b0ac92b
|
|||
|
162f9ad529
|
|||
|
a6324b58c9
|
|||
|
9be0607ee5
|
|||
|
18f753e476
|
|||
|
9e71a079a9
|
|||
|
8e92655b4b
|
|||
|
1782d42a7d
|
|||
|
ac5ff5d3c2
|
|||
|
13410e3977
|
|||
|
88f47746e4
|
|||
|
4ffe25022c
|
|||
|
00094c131c
|
|||
|
26b12fac27
|
|||
|
25e2a41b22
|
|||
|
1b2cc6e676
|
|||
|
376125273b
|
|||
|
832a6ffe75
|
|||
|
72fc6962a7
|
|||
|
d2d9494a44
|
|||
|
8d84df095a
|
|||
| 6883fd0f12 | |||
|
ca4e7e2c44
|
|||
|
ffad4f21d2
|
|||
|
b94cb495ae
|
|||
|
d6fb7efc3a
|
|||
|
cf0c1d0d07
|
|||
|
4ce0cf69d5
|
|||
|
831bb394af
|
|||
|
7a6e5b52ef
|
|||
|
7ffbd12e87
|
|||
|
4e22cf33ee
|
|||
|
628092755e
|
|||
|
27bcad6052
|
|||
|
ff22622f87
|
|||
|
ee642683c4
|
|||
|
56d9178919
|
|||
|
29f5577efe
|
|||
|
8544a650ab
|
|||
|
31a12fc502
|
|||
|
cec5748301
|
|||
|
f5ccfd297a
|
|||
|
6d95b9e550
|
|||
|
3072334b7f
|
|||
|
813835a540
|
|||
|
52ec1c6a6b
|
|||
|
3a96925657
|
|||
|
aaa4aa947d
|
|||
|
c6b1e95f4c
|
254
.github/workflows/_build.yml
vendored
Normal file
254
.github/workflows/_build.yml
vendored
Normal file
@@ -0,0 +1,254 @@
|
||||
---
|
||||
# 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@v3
|
||||
with:
|
||||
name: emacs-builder-git-sha
|
||||
path: ./
|
||||
- name: Store builder Git SHA
|
||||
id: builder_sha
|
||||
run: >-
|
||||
echo "sha=$(cat emacs-builder-git-sha.txt)" >> $GITHUB_OUTPUT
|
||||
- name: Prepare plan test args
|
||||
id: test_plan_args
|
||||
if: ${{ inputs.test_build_name != '' }}
|
||||
run: >-
|
||||
echo "args=--test-build '${{ inputs.test_build_name }}' --test-release-type '${{ inputs.test_release_type }}'" >> $GITHUB_OUTPUT
|
||||
- name: Set git SHA override
|
||||
id: emacs_sha
|
||||
if: ${{ inputs.git_sha != '' }}
|
||||
run: >-
|
||||
echo "sha=--sha '${{ inputs.git_sha }}'" >> $GITHUB_OUTPUT
|
||||
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@v3
|
||||
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@v3
|
||||
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: |
|
||||
echo "result=$((bin/emacs-builder -l debug release --plan build-plan.yml check && echo 'ok') || echo 'fail')" >> $GITHUB_OUTPUT
|
||||
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: Fix system python breaking homebrew
|
||||
run: >-
|
||||
find /usr/local/bin -type l
|
||||
-ilname '*/Library/Frameworks/Python.framework/*'
|
||||
-delete
|
||||
- name: Install dependencies
|
||||
run: make bootstrap-ci
|
||||
working-directory: builder
|
||||
- name: Download build-plan artifact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ${{ inputs.artifact_prefix }}build-plan
|
||||
path: ./
|
||||
- name: Build Emacs
|
||||
run: >-
|
||||
./builder/build-emacs-for-macos
|
||||
--log-level debug
|
||||
--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@v3
|
||||
with:
|
||||
name: ${{ inputs.artifact_prefix }}unsigned-app
|
||||
path: builds/*.tbz
|
||||
if-no-files-found: error
|
||||
- name: Upload Emacs source artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
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:
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- name: Install dmgbuild
|
||||
run: |
|
||||
$(command -v pip3 || command -v pip) install --upgrade dmgbuild
|
||||
- name: Download pre-built emacs-builder artifact
|
||||
uses: actions/download-artifact@v3
|
||||
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@v3
|
||||
with:
|
||||
name: ${{ inputs.artifact_prefix }}build-plan
|
||||
path: ./
|
||||
- name: Download unsigned app artifact
|
||||
uses: actions/download-artifact@v3
|
||||
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@v3
|
||||
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
54
.github/workflows/_prepare.yml
vendored
Normal 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.42"
|
||||
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-11
|
||||
steps:
|
||||
- name: Checkout build-emacs-for-macos repo
|
||||
uses: actions/checkout@v3
|
||||
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@v3
|
||||
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@v3
|
||||
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@v3
|
||||
with:
|
||||
name: emacs-builder
|
||||
path: builder/bin/emacs-builder
|
||||
if-no-files-found: error
|
||||
57
.github/workflows/_release.yml
vendored
Normal file
57
.github/workflows/_release.yml
vendored
Normal 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@v3
|
||||
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@v3
|
||||
with:
|
||||
name: ${{ inputs.plan_artifact }}
|
||||
path: ./
|
||||
- name: Download disk image artifacts
|
||||
id: dmg
|
||||
continue-on-error: true
|
||||
uses: actions/download-artifact@v3
|
||||
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' }}
|
||||
126
.github/workflows/build.yml
vendored
126
.github/workflows/build.yml
vendored
@@ -1,84 +1,72 @@
|
||||
---
|
||||
name: Build
|
||||
on:
|
||||
schedule:
|
||||
- cron: "35 2 * * *"
|
||||
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-11", "macos-12", or "macos-latest")'
|
||||
required: true
|
||||
default: "macos-11"
|
||||
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.11"
|
||||
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: ./.github/workflows/_prepare.yml
|
||||
with:
|
||||
builder_ref: ${{ github.event.inputs.builder_ref }}
|
||||
secrets:
|
||||
TAP_REPO_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}
|
||||
|
||||
build:
|
||||
name: Build
|
||||
needs: [prepare]
|
||||
uses: ./.github/workflows/_build.yml
|
||||
with:
|
||||
os: ${{ github.event.inputs.os }}
|
||||
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: ./.github/workflows/_release.yml
|
||||
with:
|
||||
plan_artifact: build-plan
|
||||
dmg_artifact: dmg
|
||||
secrets:
|
||||
TAP_REPO_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}
|
||||
|
||||
46
.github/workflows/nightly-emacs-29.yml
vendored
Normal file
46
.github/workflows/nightly-emacs-29.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
name: Nightly (emacs-29)
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 23 * * *"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
git_sha:
|
||||
description: Override Emacs git commit SHA to build
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
name: Prepare
|
||||
uses: ./.github/workflows/_prepare.yml
|
||||
secrets:
|
||||
TAP_REPO_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}
|
||||
|
||||
build:
|
||||
name: Build
|
||||
needs: [prepare]
|
||||
uses: ./.github/workflows/_build.yml
|
||||
with:
|
||||
os: macos-11
|
||||
git_ref: emacs-29
|
||||
git_sha: ${{ github.event.inputs.git_sha }}
|
||||
build_args: --native-comp
|
||||
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: ./.github/workflows/_release.yml
|
||||
with:
|
||||
plan_artifact: build-plan
|
||||
dmg_artifact: dmg
|
||||
secrets:
|
||||
TAP_REPO_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}
|
||||
46
.github/workflows/nightly-master.yml
vendored
Normal file
46
.github/workflows/nightly-master.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
name: Nightly (master)
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 23 * * *"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
git_sha:
|
||||
description: Override Emacs git commit SHA to build
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
name: Prepare
|
||||
uses: ./.github/workflows/_prepare.yml
|
||||
secrets:
|
||||
TAP_REPO_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}
|
||||
|
||||
build:
|
||||
name: Build
|
||||
needs: [prepare]
|
||||
uses: ./.github/workflows/_build.yml
|
||||
with:
|
||||
os: macos-11
|
||||
git_ref: master
|
||||
git_sha: ${{ github.event.inputs.git_sha }}
|
||||
build_args: --native-comp
|
||||
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: ./.github/workflows/_release.yml
|
||||
with:
|
||||
plan_artifact: build-plan
|
||||
dmg_artifact: dmg
|
||||
secrets:
|
||||
TAP_REPO_TOKEN: ${{ secrets.TAP_REPO_TOKEN }}
|
||||
33
.github/workflows/update-metadata.yml
vendored
Normal file
33
.github/workflows/update-metadata.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
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 meta branch
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: meta
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "1.20"
|
||||
- name: update total downloads shield JSON
|
||||
run: >-
|
||||
go run . badges downloads -o total-downloads/shield.json
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
- 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
|
||||
213
README.md
213
README.md
@@ -1,81 +1,194 @@
|
||||
# Emacs Builds
|
||||
|
||||
<p>
|
||||
<a href="https://github.com/jimeh/emacs-builds/releases">
|
||||
<img src="https://img.shields.io/github/v/tag/jimeh/emacs-builds?label=nightly" alt="GitHub tag (latest SemVer)">
|
||||
</a>
|
||||
<a href="https://github.com/jimeh/emacs-builds/issues">
|
||||
<img src="https://img.shields.io/github/issues-raw/jimeh/emacs-builds.svg?style=flat&logo=github&logoColor=white"
|
||||
alt="GitHub issues">
|
||||
</a>
|
||||
<a href="https://github.com/jimeh/emacs-builds/pulls">
|
||||
<img src="https://img.shields.io/github/issues-pr-raw/jimeh/emacs-builds.svg?style=flat&logo=github&logoColor=white" alt="GitHub pull requests">
|
||||
</a>
|
||||
<p align="center">
|
||||
<img width="192px" src="https://github.com/emacs-mirror/emacs/raw/emacs-27.2/etc/images/icons/hicolor/scalable/apps/emacs.svg" alt="Logo">
|
||||
</p>
|
||||
|
||||
Nightly binary builds of Emacs for macOS, with native-compilation enabled, as a
|
||||
completely self-contained Emacs.app application bundle.
|
||||
<h1 align="center">
|
||||
Emacs Builds
|
||||
</h1>
|
||||
|
||||
<p align="center">
|
||||
<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-29&expanded=true"><img alt="GitHub release (nightly@emacs-29)" src="https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjimeh%2Fhomebrew-emacs-builds%2Fmeta%2FCasks%2Femacs-app-nightly-29%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>
|
||||
Self-contained Emacs.app builds for macOS, with native-compilation support.
|
||||
</strong>
|
||||
</p>
|
||||
|
||||
## Features
|
||||
|
||||
- Self-contained Emacs.app application, with no external dependencies.
|
||||
- Native-compilation is enabled in nightly builds from the `master` branch of
|
||||
Emacs, and should just work without the need to install GCC, libgccjit, or any
|
||||
other dependencies.
|
||||
- Includes the [fix-window-role][] and [system-appearance][] patches from the
|
||||
excellent [emacs-plus][] project.
|
||||
- Build are 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.
|
||||
- Self-contained Emacs.app application bundle, with no external dependencies.
|
||||
- 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.
|
||||
- Xwidget-webkit support is enabled, allowing access to a embedded WebKit-based
|
||||
browser with `M-x xwidget-webkit-browse-url`.
|
||||
- Native XML parsing via libxml2.
|
||||
- Dynamic module loading.
|
||||
- Includes the [fix-window-role][], [system-appearance][], and
|
||||
[round-undecorated-frame][] patches from the excellent [emacs-plus][] project.
|
||||
- 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.
|
||||
- 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
|
||||
[gccemacs]: https://www.emacswiki.org/emacs/GccEmacs
|
||||
[fix-window-role]:
|
||||
https://github.com/d12frosted/homebrew-emacs-plus/blob/master/patches/emacs-28/fix-window-role.patch
|
||||
[system-appearance]:
|
||||
https://github.com/d12frosted/homebrew-emacs-plus/blob/master/patches/emacs-28/system-appearance.patch
|
||||
[round-undecorated-frame]:
|
||||
https://github.com/d12frosted/homebrew-emacs-plus/blob/master/patches/emacs-29/round-undecorated-frame.patch
|
||||
[emacs-plus]: https://github.com/d12frosted/homebrew-emacs-plus
|
||||
[emacs-mirror/emacs]: https://github.com/emacs-mirror/emacs
|
||||
|
||||
## Downloads
|
||||
## System Requirements
|
||||
|
||||
See the [Releases][] page to download latest builds.
|
||||
- macOS 11.x (Big Sur) or later (uses Rosetta2 on Apple Silicon machines).
|
||||
- Xcode Command Line Tools for native compilation (Emacs 28.x and later).
|
||||
|
||||
## Installation
|
||||
|
||||
### Manual Download
|
||||
|
||||
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 at least 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
|
||||
|
||||
### Homebrew Cask
|
||||
|
||||
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-29` for the latest Emacs 29.x nightly build from the
|
||||
`emacs-29` branch:
|
||||
```
|
||||
brew install --cask emacs-app-nightly-29
|
||||
```
|
||||
|
||||
[7]: https://github.com/jimeh/emacs-builds/issues/7
|
||||
|
||||
## Use Emacs.app as `emacs` CLI Tool
|
||||
|
||||
### Installed via Homebrew Cask
|
||||
|
||||
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
|
||||
alias emacs="emacs -nw"
|
||||
```
|
||||
|
||||
### 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
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
Building Emacs is done using the [jimeh/build-emacs-for-macos][] build script,
|
||||
executed within a GitHub Actions workflow. Full build history is available
|
||||
[here][actions].
|
||||
executed within a GitHub Actions [workflow][]. This is why macOS 11.x (Big Sur)
|
||||
or later is required, as it's the oldest version of macOS available in GitHub
|
||||
Actions.
|
||||
|
||||
[jimeh/build-emacs-for-macos]: https://github.com/jimeh/build-emacs-for-macos
|
||||
[workflow]:
|
||||
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
|
||||
|
||||
Nightly builds are scheduled for 2:35 UTC every night, based on the latest
|
||||
Nightly builds are scheduled for 23:00 UTC every night, based on the latest
|
||||
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
|
||||
|
||||
## Untrusted Application
|
||||
## Issues / To-Do
|
||||
|
||||
Currently builds are not signed or notarized, meaning macOS cannot verify
|
||||
Emacs.app came from a trusted developer, and by default you are not even given
|
||||
the option to trust the app and open it anyway.
|
||||
Please see [Issues][] for details of things to come, or to report issues.
|
||||
|
||||
Simplest way around this: Instead of double-clicking on Emacs.app in Finder,
|
||||
right-click (or control-click) on Emacs and select "Open". You will then be
|
||||
given the same warning as before, with a "Open" button now available to open the
|
||||
app anyway. After that you can open the application like normal without any
|
||||
warnings.
|
||||
|
||||
## To-Do
|
||||
|
||||
- [ ] Sign and notarize builds.
|
||||
- [ ] Builds for stable versions of Emacs.
|
||||
- [ ] Populate GitHub Release description with relevant info about the build,
|
||||
including a link to the GitHub Actions workflow run that produced the
|
||||
build.
|
||||
- [ ] (Eventually) support Apple Silicon mac builds when native-compilation
|
||||
actually works on Apple Silicon.
|
||||
- [ ] (Eventually) support builds for Linux.
|
||||
[issues]: https://github.com/jimeh/emacs-builds/issues
|
||||
|
||||
248
cmd/dylib-tree/main.go
Normal file
248
cmd/dylib-tree/main.go
Normal file
@@ -0,0 +1,248 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"debug/macho"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/xlab/treeprint"
|
||||
)
|
||||
|
||||
var app = &cli.App{
|
||||
Name: "dylib-tree",
|
||||
Usage: "recursive list shared-libraries as a tree",
|
||||
UsageText: "dylib-tree [options] <binary-file> [<binary-file>]",
|
||||
Flags: []cli.Flag{
|
||||
&cli.IntFlag{
|
||||
Name: "depth",
|
||||
Usage: "max depth of tree (default: 0 = unlimited)",
|
||||
Value: 0,
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "ignore",
|
||||
Usage: "path patterns to ignore",
|
||||
},
|
||||
|
||||
&cli.BoolFlag{
|
||||
Name: "ignore-system",
|
||||
Usage: "ignore system libraries",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "real-path",
|
||||
Usage: "show resolved full paths instead of @executable_path " +
|
||||
"and @rpath",
|
||||
},
|
||||
},
|
||||
Action: actionHandler(LinkTreeCmd),
|
||||
}
|
||||
|
||||
type Context struct {
|
||||
Root string
|
||||
ExecutablePath string
|
||||
Depth int
|
||||
MaxDepth int
|
||||
RealPath bool
|
||||
Ignore []string
|
||||
RPaths []string
|
||||
}
|
||||
|
||||
func (s *Context) WithFile(filename string) *Context {
|
||||
ctx := *s
|
||||
ctx.Root = filename
|
||||
ctx.ExecutablePath = filepath.Dir(filename)
|
||||
return &ctx
|
||||
}
|
||||
|
||||
func (s *Context) WithDepth(depth int) *Context {
|
||||
ctx := *s
|
||||
ctx.Depth = depth
|
||||
return &ctx
|
||||
}
|
||||
|
||||
func (s *Context) WithIgnore(ignore []string) *Context {
|
||||
ctx := *s
|
||||
ctx.Ignore = append(ctx.Ignore, ignore...)
|
||||
return &ctx
|
||||
}
|
||||
|
||||
func (s *Context) WithRpaths(rpaths []string) *Context {
|
||||
ctx := *s
|
||||
ctx.RPaths = append(ctx.RPaths, rpaths...)
|
||||
return &ctx
|
||||
}
|
||||
|
||||
func actionHandler(
|
||||
f func(*cli.Context, *Context) error,
|
||||
) func(*cli.Context) error {
|
||||
return func(c *cli.Context) error {
|
||||
ignore := c.StringSlice("ignore")
|
||||
if c.Bool("ignore-system") {
|
||||
ignore = append(
|
||||
ignore,
|
||||
"/System/Library/*",
|
||||
"*/libSystem.*.dylib",
|
||||
"*/libobjc.*.dylib",
|
||||
)
|
||||
}
|
||||
|
||||
ctx := &Context{
|
||||
Ignore: ignore,
|
||||
MaxDepth: c.Int("depth"),
|
||||
RealPath: c.Bool("real-path"),
|
||||
}
|
||||
|
||||
return f(c, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
func LinkTreeCmd(c *cli.Context, ctx *Context) error {
|
||||
for _, filename := range c.Args().Slice() {
|
||||
ctx := ctx.WithFile(filename)
|
||||
|
||||
treeRoot := treeprint.New()
|
||||
tree := treeRoot.AddBranch(filename)
|
||||
|
||||
err := processBinary(&tree, ctx, filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(treeRoot.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func processBinary(
|
||||
parent *treeprint.Tree,
|
||||
ctx *Context,
|
||||
filename string,
|
||||
) error {
|
||||
f, err := macho.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx = ctx.WithDepth(ctx.Depth + 1).WithRpaths(getRpaths(f))
|
||||
|
||||
if ctx.MaxDepth > 0 && ctx.Depth > ctx.MaxDepth {
|
||||
return nil
|
||||
}
|
||||
|
||||
libs, err := f.ImportedLibraries()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, lib := range libs {
|
||||
skip, err := ignoreLib(ctx, lib)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skip {
|
||||
continue
|
||||
}
|
||||
|
||||
filename, err := resolveLibFilename(ctx, lib)
|
||||
if err != nil {
|
||||
(*parent).AddBranch(lib)
|
||||
continue
|
||||
}
|
||||
|
||||
skip, err = ignoreLib(ctx, filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skip {
|
||||
continue
|
||||
}
|
||||
|
||||
displayName := lib
|
||||
if ctx.RealPath {
|
||||
displayName = filename
|
||||
}
|
||||
|
||||
tree := (*parent).AddBranch(displayName)
|
||||
|
||||
err = processBinary(&tree, ctx, filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ignoreLib(ctx *Context, lib string) (bool, error) {
|
||||
for _, pattern := range ctx.Ignore {
|
||||
m, err := ignoreRegexp(pattern)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if m.MatchString(lib) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func ignoreRegexp(p string) (*regexp.Regexp, error) {
|
||||
rp := "^" + regexp.QuoteMeta(p) + "$"
|
||||
rp = strings.ReplaceAll(rp, `\*`, ".*")
|
||||
rp = strings.ReplaceAll(rp, `\?`, ".")
|
||||
|
||||
return regexp.Compile(rp)
|
||||
}
|
||||
|
||||
func resolveLibFilename(ctx *Context, lib string) (string, error) {
|
||||
filename := lib
|
||||
|
||||
if strings.HasPrefix(lib, "@executable_path") {
|
||||
filename = filepath.Join(ctx.ExecutablePath, lib[16:])
|
||||
} else if strings.HasPrefix(lib, "@rpath") {
|
||||
for _, r := range ctx.RPaths {
|
||||
if strings.HasPrefix(r, "@executable_path") {
|
||||
r = filepath.Join(ctx.ExecutablePath, r[16:])
|
||||
}
|
||||
|
||||
rfile := filepath.Join(r, lib[6:])
|
||||
_, err := os.Stat(rfile)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
return rfile, nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("could not find %s", lib)
|
||||
}
|
||||
|
||||
_, err := os.Stat(filename)
|
||||
|
||||
return filename, err
|
||||
}
|
||||
|
||||
func getRpaths(f *macho.File) []string {
|
||||
paths := []string{}
|
||||
|
||||
for _, i := range f.Loads {
|
||||
if r, ok := i.(*macho.Rpath); ok {
|
||||
paths = append(paths, r.Path)
|
||||
}
|
||||
}
|
||||
|
||||
return paths
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "ERROR: %s\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
release, resp, err := gh.Repositories.GetReleaseByTag(
|
||||
c.Context, repo.Owner, repo.Name, plan.Release,
|
||||
)
|
||||
if err != nil {
|
||||
if resp.StatusCode == http.StatusNotFound {
|
||||
return fmt.Errorf("release %s does not exist", plan.Release)
|
||||
} 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)
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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], ".")
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Plan struct {
|
||||
Commit *Commit `yaml:"commit"`
|
||||
OS *OSInfo `yaml:"os"`
|
||||
Release string `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
|
||||
}
|
||||
@@ -1,110 +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",
|
||||
},
|
||||
},
|
||||
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)
|
||||
|
||||
releaseName := fmt.Sprintf(
|
||||
"Emacs.%s.%s.%s",
|
||||
commit.DateString(), commit.ShortSHA(), cleanRef,
|
||||
)
|
||||
archiveName := fmt.Sprintf(
|
||||
"Emacs.%s.%s.%s.%s.%s.tbz",
|
||||
commit.DateString(), commit.ShortSHA(), cleanRef, cleanOS, cleanArch,
|
||||
)
|
||||
|
||||
plan := &Plan{
|
||||
Commit: commit,
|
||||
OS: osInfo,
|
||||
Release: releaseName,
|
||||
Archive: filepath.Join(buildsDir, archiveName),
|
||||
}
|
||||
|
||||
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, "-")
|
||||
}
|
||||
@@ -1,178 +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"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "prerelease",
|
||||
Usage: "Git SHA of repo to create release on",
|
||||
EnvVars: []string{"RELEASE_PRERELEASE"},
|
||||
Value: true,
|
||||
},
|
||||
},
|
||||
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")
|
||||
prerelease := c.Bool("prerelease")
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
fmt.Printf("==> Checking release %s\n", plan.Release)
|
||||
|
||||
release, resp, err := gh.Repositories.GetReleaseByTag(
|
||||
c.Context, repo.Owner, repo.Name, plan.Release,
|
||||
)
|
||||
if err != nil {
|
||||
if resp.StatusCode == http.StatusNotFound {
|
||||
fmt.Println(" -> Release not found, creating...")
|
||||
release, _, err = gh.Repositories.CreateRelease(
|
||||
c.Context, repo.Owner, repo.Name, &github.RepositoryRelease{
|
||||
Name: &plan.Release,
|
||||
TagName: &plan.Release,
|
||||
TargetCommitish: &releaseSHA,
|
||||
Prerelease: &prerelease,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if release.GetPrerelease() != prerelease {
|
||||
release.Prerelease = &prerelease
|
||||
|
||||
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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
3
go.mod
3
go.mod
@@ -1,10 +1,11 @@
|
||||
module github.com/jimeh/build-emacs
|
||||
module github.com/jimeh/emacs-builds
|
||||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/google/go-github/v35 v35.1.0
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
github.com/xlab/treeprint v1.1.0
|
||||
golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
)
|
||||
|
||||
6
go.sum
6
go.sum
@@ -41,6 +41,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
@@ -121,8 +122,12 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5I
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
|
||||
github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@@ -368,6 +373,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
Reference in New Issue
Block a user