From 9ba951ae4949a047336ca0998ab5c01fc5efda6c Mon Sep 17 00:00:00 2001 From: tobtoht Date: Tue, 22 Oct 2024 13:52:11 +0200 Subject: [PATCH] build: codesigning --- .github/workflows/guix.yml | 67 +++-- Makefile | 19 ++ contrib/guix/guix-codesign | 378 ++++++++++++++++++++++++ contrib/guix/libexec/build.sh | 22 +- contrib/guix/libexec/codesign.sh | 96 ++++++ contrib/installers/windows/setup.nsi.in | 2 +- contrib/shell/guix-attest.sh | 44 +++ contrib/shell/guix-build.sh | 15 + contrib/shell/guix-codesign.sh | 0 contrib/shell/guix-verify.sh | 25 ++ 10 files changed, 628 insertions(+), 40 deletions(-) create mode 100644 Makefile create mode 100755 contrib/guix/guix-codesign create mode 100755 contrib/guix/libexec/codesign.sh create mode 100755 contrib/shell/guix-attest.sh create mode 100755 contrib/shell/guix-build.sh create mode 100644 contrib/shell/guix-codesign.sh create mode 100755 contrib/shell/guix-verify.sh diff --git a/.github/workflows/guix.yml b/.github/workflows/guix.yml index 6c7c57bd..2aae5b45 100644 --- a/.github/workflows/guix.yml +++ b/.github/workflows/guix.yml @@ -37,7 +37,9 @@ jobs: - target: "x86_64-w64-mingw32.installer" - target: "x86_64-apple-darwin" - target: "arm64-apple-darwin" - + outputs: + WIN_INSTALLER_ARTIFACT_ID: ${{ steps.win-installer.outputs.WIN_INSTALLER_ARTIFACT_ID }} + WIN_EXECUTABLE_ARTIFACT_ID: ${{ steps.win-executable.outputs.WIN_EXECUTABLE_ARTIFACT_ID }} name: ${{ matrix.toolchain.target }} steps: - uses: actions/checkout@v4 @@ -79,26 +81,12 @@ jobs: path: | guix/guix-build-*/output/${{ matrix.toolchain.target }}/* guix/guix-build-*/logs/${{ matrix.toolchain.target }}/* - - uses: signpath/github-action-submit-signing-request@v1 - if: ${{ matrix.toolchain.target == 'x86_64-w64-mingw32.installer' }} - with: - api-token: '${{ secrets.SIGNPATH_API_KEY }}' - organization-id: 'd3e94749-9c69-44e9-82de-c65cb3832869' - project-slug: 'feather' - signing-policy-slug: 'test-signing' - artifact-configuration-slug: 'installer' - github-artifact-id: ${{ steps.upload-artifact.outputs.artifact-id }} - wait-for-completion: true - output-artifact-directory: codesigning/ - if: ${{ matrix.toolchain.target == 'x86_64-w64-mingw32.installer' }} - run: osslsigncode extract-signature -in codesigning/guix-build-*/output/${{ matrix.toolchain.target }}/FeatherWalletSetup-*.exe -out codesigning/${{matrix.toolchain.target}}-${{github.ref_name}}.pem - - uses: actions/upload-artifact@v4 - if: ${{ matrix.toolchain.target == 'x86_64-w64-mingw32.installer' }} - with: - name: ${{ matrix.toolchain.target }}.pem - path: | - codesigning/${{matrix.toolchain.target}}-${{github.ref_name}}.pem - + id: win-installer + run: echo "WIN_INSTALLER_ARTIFACT_ID=${{ steps.upload-artifact.outputs.artifact-id }}" >> $GITHUB_ENV + - if: ${{ matrix.toolchain.target == 'x86_64-w64-mingw32' }} + id: win-executable + run: echo "WIN_EXECUTABLE_ARTIFACT_ID=${{ steps.upload-artifact.outputs.artifact-id }}" >> $GITHUB_ENV bundle-logs: runs-on: ubuntu-24.04 @@ -122,3 +110,42 @@ jobs: artifacts: "**/*.AppImage,**/*-linux-arm.zip,**/*-linux-arm64.zip,**/*-linux-riscv64.zip,**/*-linux.zip,**/*-mac-arm64.zip,**/*-mac.zip,**/*-win.zip,**/FeatherWalletSetup-*.exe,**/feather-${{github.ref_name}}.tar.gz" draft: true name: v${{github.ref_name}} + + codesigning: + runs-on: ubuntu-24.04 + needs: [bundle-logs] + strategy: + fail-fast: false + matrix: + toolchain: + - target: "x86_64-w64-mingw32" + - target: "x86_64-w64-mingw32.installer" + steps: + - name: "set artifact id" + run: | + if [ "${{ matrix.toolchain.target }}" == "x86_64-w64-mingw32" ]; then + echo "ARTIFACT_ID=${{ needs.build-guix.outputs.WIN_EXECUTABLE_ARTIFACT_ID }}" >> $GITHUB_ENV + echo "ARTIFACT_SLUG=executable" >> $GITHUB_ENV + elif [ "${{ matrix.toolchain.target }}" == "x86_64-w64-mingw32.installer" ]; then + echo "ARTIFACT_ID=${{ needs.build-guix.outputs.WIN_INSTALLER_ARTIFACT_ID }}" >> $GITHUB_ENV + echo "ARTIFACT_SLUG=installer" >> $GITHUB_ENV + fi + - uses: signpath/github-action-submit-signing-request@v1 + name: "request signature" + with: + api-token: '${{ secrets.SIGNPATH_API_KEY }}' + organization-id: 'd3e94749-9c69-44e9-82de-c65cb3832869' + project-slug: 'feather' + signing-policy-slug: 'test-signing' + artifact-configuration-slug: ${{ ARTIFACT_SLUG }} + github-artifact-id: ${{ ARTIFACT_ID }} + wait-for-completion: true + output-artifact-directory: codesigning/ + - name: "extract signature" + run: osslsigncode extract-signature -in codesigning/guix-build-*/output/${{ matrix.toolchain.target }}/*-unsigned.exe -out codesigning/${{ matrix.toolchain.target }}-${{github.ref_name}}.pem + - uses: actions/upload-artifact@v4 + name: "upload signature" + with: + name: ${{ matrix.toolchain.target }}.pem + path: | + codesigning/${{ matrix.toolchain.target }}-${{github.ref_name}}.pem diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..6819ace1 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +release: + @./contrib/guix/guix-build + +codesign: + @./contrib/shell/guix-codesign.sh + +attest: + @./contrib/shell/guix-attest.sh + +verify: + @./contrib/shell/guix-verify.sh + +clean: + @./contrib/guix/guix-clean + +DEFAULT_GOAL := default +default: release + +.PHONY: default release attest verify clean diff --git a/contrib/guix/guix-codesign b/contrib/guix/guix-codesign new file mode 100755 index 00000000..8ae8676b --- /dev/null +++ b/contrib/guix/guix-codesign @@ -0,0 +1,378 @@ +#!/usr/bin/env bash +export LC_ALL=C +set -e -o pipefail + +# Source the common prelude, which: +# 1. Checks if we're at the top directory of the Bitcoin Core repository +# 2. Defines a few common functions and variables +# +# shellcheck source=libexec/prelude.bash +source "$(dirname "${BASH_SOURCE[0]}")/libexec/prelude.bash" + + +################### +## SANITY CHECKS ## +################### + +################ +# Required non-builtin commands should be invocable +################ + +check_tools cat mkdir git guix + +################ +# Required env vars should be non-empty +################ + +cmd_usage() { + cat < \\ + ./contrib/guix/guix-codesign + +EOF +} + +if [ -z "$GUIX_SIGS_REPO" ]; then + cmd_usage + exit 1 +fi + +################ +# GUIX_BUILD_OPTIONS should be empty +################ +# +# GUIX_BUILD_OPTIONS is an environment variable recognized by guix commands that +# can perform builds. This seems like what we want instead of +# ADDITIONAL_GUIX_COMMON_FLAGS, but the value of GUIX_BUILD_OPTIONS is actually +# _appended_ to normal command-line options. Meaning that they will take +# precedence over the command-specific ADDITIONAL_GUIX__FLAGS. +# +# This seems like a poor user experience. Thus we check for GUIX_BUILD_OPTIONS's +# existence here and direct users of this script to use our (more flexible) +# custom environment variables. +if [ -n "$GUIX_BUILD_OPTIONS" ]; then +cat << EOF +Error: Environment variable GUIX_BUILD_OPTIONS is not empty: + '$GUIX_BUILD_OPTIONS' + +Unfortunately this script is incompatible with GUIX_BUILD_OPTIONS, please unset +GUIX_BUILD_OPTIONS and use ADDITIONAL_GUIX_COMMON_FLAGS to set build options +across guix commands or ADDITIONAL_GUIX__FLAGS to set build options for a +specific guix command. + +See contrib/guix/README.md for more details. +EOF +exit 1 +fi + +################ +# The codesignature git worktree should not be dirty +################ + +if ! git -C "$GUIX_SIGS_REPO" diff-index --quiet HEAD -- && [ -z "$FORCE_DIRTY_WORKTREE" ]; then + cat << EOF +ERR: The DETACHED CODESIGNATURE git worktree is dirty, which may lead to broken builds. + + Aborting... + +Hint: To make your git worktree clean, You may want to: + 1. Commit your changes, + 2. Stash your changes, or + 3. Set the 'FORCE_DIRTY_WORKTREE' environment variable if you insist on + using a dirty worktree +EOF + exit 1 +fi + +################ +# Build directories should not exist +################ + +# Default to building for all supported HOSTs (overridable by environment) +export HOSTS="${HOSTS:-x86_64-w64-mingw32 x86_64-apple-darwin arm64-apple-darwin}" + +# Usage: distsrc_for_host HOST +# +# HOST: The current platform triple we're building for +# +distsrc_for_host() { + echo "${DISTSRC_BASE}/distsrc-${VERSION}-${1}-codesigned" +} + +# Accumulate a list of build directories that already exist... +hosts_distsrc_exists="" +for host in $HOSTS; do + if [ -e "$(distsrc_for_host "$host")" ]; then + hosts_distsrc_exists+=" ${host}" + fi +done + +if [ -n "$hosts_distsrc_exists" ]; then +# ...so that we can print them out nicely in an error message +cat << EOF +ERR: Build directories for this commit already exist for the following platform + triples you're attempting to build, probably because of previous builds. + Please remove, or otherwise deal with them prior to starting another build. + + Aborting... + +Hint: To blow everything away, you may want to use: + + $ ./contrib/guix/guix-clean + +Specifically, this will remove all files without an entry in the index, +excluding the SDK directory, the depends download cache, the depends built +packages cache, the garbage collector roots for Guix environments, and the +output directory. +EOF +for host in $hosts_distsrc_exists; do + echo " ${host} '$(distsrc_for_host "$host")'" +done +exit 1 +else + mkdir -p "$DISTSRC_BASE" +fi + + +################ +# Unsigned tarballs SHOULD exist +################ + +# Usage: outdir_for_host HOST SUFFIX +# +# HOST: The current platform triple we're building for +# +outdir_for_host() { + echo "${OUTDIR_BASE}/${1}${2:+-${2}}" +} + + +unsigned_tarball_for_host() { + case "$1" in + *mingw*) + echo "$(outdir_for_host "$1")/${DISTNAME}-win64-unsigned.tar.gz" + ;; + *darwin*) + echo "$(outdir_for_host "$1")/${DISTNAME}-${1}-unsigned.tar.gz" + ;; + *) + exit 1 + ;; + esac +} + +# Accumulate a list of build directories that already exist... +hosts_unsigned_tarball_missing="" +for host in $HOSTS; do + if [ ! -e "$(unsigned_tarball_for_host "$host")" ]; then + hosts_unsigned_tarball_missing+=" ${host}" + fi +done + +if [ -n "$hosts_unsigned_tarball_missing" ]; then + # ...so that we can print them out nicely in an error message + cat << EOF +ERR: Unsigned tarballs do not exist +... + +EOF +for host in $hosts_unsigned_tarball_missing; do + echo " ${host} '$(unsigned_tarball_for_host "$host")'" +done +exit 1 +fi + +################ +# Check that we can connect to the guix-daemon +################ + +cat << EOF +Checking that we can connect to the guix-daemon... + +Hint: If this hangs, you may want to try turning your guix-daemon off and on + again. + +EOF +if ! guix gc --list-failures > /dev/null; then + cat << EOF + +ERR: Failed to connect to the guix-daemon, please ensure that one is running and + reachable. +EOF + exit 1 +fi + +# Developer note: we could use `guix repl` for this check and run: +# +# (import (guix store)) (close-connection (open-connection)) +# +# However, the internal API is likely to change more than the CLI invocation + + +######### +# SETUP # +######### + +# Determine the maximum number of jobs to run simultaneously (overridable by +# environment) +JOBS="${JOBS:-$(nproc)}" + +# Determine the reference time used for determinism (overridable by environment) +SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(git -c log.showSignature=false log --format=%at -1)}" + +# Make sure an output directory exists for our builds +OUTDIR_BASE="${OUTDIR_BASE:-${VERSION_BASE}/output}" +mkdir -p "$OUTDIR_BASE" + +# Usage: profiledir_for_host HOST SUFFIX +# +# HOST: The current platform triple we're building for +# +profiledir_for_host() { + echo "${PROFILES_BASE}/${1}${2:+-${2}}" +} + +######### +# BUILD # +######### + +# Function to be called when codesigning for host ${1} and the user interrupts +# the codesign +int_trap() { +cat << EOF +** INT received while codesigning ${1}, you may want to clean up the relevant + work directories (e.g. distsrc-*) before recodesigning + +Hint: To blow everything away, you may want to use: + + $ ./contrib/guix/guix-clean + +Specifically, this will remove all files without an entry in the index, +excluding the SDK directory, the depends download cache, the depends built +packages cache, the garbage collector roots for Guix environments, and the +output directory. +EOF +} + +# Deterministically build Bitcoin Core +# shellcheck disable=SC2153 +for host in $HOSTS; do + + # Display proper warning when the user interrupts the build + trap 'int_trap ${host}' INT + + ( + # Required for 'contrib/guix/manifest.scm' to output the right manifest + # for the particular $HOST we're building for + export HOST="$host" + + # shellcheck disable=SC2030 +cat << EOF +INFO: Codesigning ${VERSION:?not set} for platform triple ${HOST:?not set}: + ...using reference timestamp: ${SOURCE_DATE_EPOCH:?not set} + ...from worktree directory: '${PWD}' + ...bind-mounted in container to: '/bitcoin' + ...in build directory: '$(distsrc_for_host "$HOST")' + ...bind-mounted in container to: '$(DISTSRC_BASE=/distsrc-base && distsrc_for_host "$HOST")' + ...outputting in: '$(outdir_for_host "$HOST" codesigned)' + ...bind-mounted in container to: '$(OUTDIR_BASE=/outdir-base && outdir_for_host "$HOST" codesigned)' + ...using detached signatures in: '${GUIX_SIGS_REPO:?not set}' + ...bind-mounted in container to: '/detached-sigs' +EOF + + + # Run the build script 'contrib/guix/libexec/build.sh' in the build + # container specified by 'contrib/guix/manifest.scm'. + # + # Explanation of `guix shell` flags: + # + # --container run command within an isolated container + # + # Running in an isolated container minimizes build-time differences + # between machines and improves reproducibility + # + # --pure unset existing environment variables + # + # Same rationale as --container + # + # --no-cwd do not share current working directory with an + # isolated container + # + # When --container is specified, the default behavior is to share + # the current working directory with the isolated container at the + # same exact path (e.g. mapping '/home/satoshi/bitcoin/' to + # '/home/satoshi/bitcoin/'). This means that the $PWD inside the + # container becomes a source of irreproducibility. --no-cwd disables + # this behaviour. + # + # --share=SPEC for containers, share writable host file system + # according to SPEC + # + # --share="$PWD"=/bitcoin + # + # maps our current working directory to /bitcoin + # inside the isolated container, which we later cd + # into. + # + # While we don't want to map our current working directory to the + # same exact path (as this introduces irreproducibility), we do want + # it to be at a _fixed_ path _somewhere_ inside the isolated + # container so that we have something to build. '/bitcoin' was + # chosen arbitrarily. + # + # ${SOURCES_PATH:+--share="$SOURCES_PATH"} + # + # make the downloaded depends sources path available + # inside the isolated container + # + # The isolated container has no network access as it's in a + # different network namespace from the main machine, so we have to + # make the downloaded depends sources available to it. The sources + # should have been downloaded prior to this invocation. + # + # ${SUBSTITUTE_URLS:+--substitute-urls="$SUBSTITUTE_URLS"} + # + # fetch substitute from SUBSTITUTE_URLS if they are + # authorized + # + # Depending on the user's security model, it may be desirable to use + # substitutes (pre-built packages) from servers that the user trusts. + # Please read the README.md in the same directory as this file for + # more information. + # + # shellcheck disable=SC2086,SC2031 + time-machine shell --manifest="${PWD}/contrib/guix/manifest.scm" \ + --container \ + --pure \ + --no-cwd \ + --share="$PWD"=/bitcoin \ + --share="$DISTSRC_BASE"=/distsrc-base \ + --share="$OUTDIR_BASE"=/outdir-base \ + --share="$GUIX_SIGS_REPO"=/detached-sigs \ + --expose="$(git rev-parse --git-common-dir)" \ + --expose="$(git -C "$GUIX_SIGS_REPO" rev-parse --git-common-dir)" \ + ${SOURCES_PATH:+--share="$SOURCES_PATH"} \ + --cores="$JOBS" \ + --keep-failed \ + --fallback \ + --link-profile \ + --root="$(profiledir_for_host "${HOST}" codesigned)" \ + ${SUBSTITUTE_URLS:+--substitute-urls="$SUBSTITUTE_URLS"} \ + ${ADDITIONAL_GUIX_COMMON_FLAGS} ${ADDITIONAL_GUIX_ENVIRONMENT_FLAGS} \ + -- env HOST="$host" \ + DISTNAME="$DISTNAME" \ + JOBS="$JOBS" \ + SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:?unable to determine value}" \ + ${V:+V=1} \ + ${SOURCES_PATH:+SOURCES_PATH="$SOURCES_PATH"} \ + DISTSRC="$(DISTSRC_BASE=/distsrc-base && distsrc_for_host "$HOST")" \ + OUTDIR="$(OUTDIR_BASE=/outdir-base && outdir_for_host "$HOST" codesigned)" \ + DIST_ARCHIVE_BASE=/outdir-base/dist-archive \ + GUIX_SIGS_REPO=/detached-sigs \ + UNSIGNED_TARBALL="$(OUTDIR_BASE=/outdir-base && unsigned_tarball_for_host "$HOST")" \ + bash -c "cd /bitcoin && bash contrib/guix/libexec/codesign.sh" + ) + +done diff --git a/contrib/guix/libexec/build.sh b/contrib/guix/libexec/build.sh index c4342080..10496269 100755 --- a/contrib/guix/libexec/build.sh +++ b/contrib/guix/libexec/build.sh @@ -440,25 +440,9 @@ mkdir -p "$DISTSRC" # for release case "$HOST" in *mingw*) - case "$OPTIONS" in - installer) - find . -print0 \ - | xargs -0r touch --no-dereference --date="@${SOURCE_DATE_EPOCH}" - find . \ - | sort \ - | zip -X@ "${OUTDIR}/${DISTNAME}-win-installer.zip" \ - || ( rm -f "${OUTDIR}/${DISTNAME}-win-installer.zip" && exit 1 ) - ;; - "") - mv feather.exe ${DISTNAME}.exe && \ - find . -print0 \ - | xargs -0r touch --no-dereference --date="@${SOURCE_DATE_EPOCH}" - find . \ - | sort \ - | zip -X@ "${OUTDIR}/${DISTNAME}-win.zip" \ - || ( rm -f "${OUTDIR}/${DISTNAME}-win.zip" && exit 1 ) - ;; - esac + if [ -z "$OPTIONS" ]; then + mv feather.exe "${OUTDIR}/${DISTNAME}-unsigned.exe" + fi ;; *linux*) if [ "$OPTIONS" != "pack" ]; then diff --git a/contrib/guix/libexec/codesign.sh b/contrib/guix/libexec/codesign.sh new file mode 100755 index 00000000..7d04d98e --- /dev/null +++ b/contrib/guix/libexec/codesign.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash +# Copyright (c) 2021-2022 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +export LC_ALL=C +set -e -o pipefail +export TZ=UTC + +# Although Guix _does_ set umask when building its own packages (in our case, +# this is all packages in manifest.scm), it does not set it for `guix +# shell`. It does make sense for at least `guix shell --container` +# to set umask, so if that change gets merged upstream and we bump the +# time-machine to a commit which includes the aforementioned change, we can +# remove this line. +# +# This line should be placed before any commands which creates files. +umask 0022 + +if [ -n "$V" ]; then + # Print both unexpanded (-v) and expanded (-x) forms of commands as they are + # read from this file. + set -vx + # Set VERBOSE for CMake-based builds + export VERBOSE="$V" +fi + +# Check that required environment variables are set +cat << EOF +Required environment variables as seen inside the container: + UNSIGNED_TARBALL: ${UNSIGNED_TARBALL:?not set} + DETACHED_SIGS_REPO: ${DETACHED_SIGS_REPO:?not set} + DIST_ARCHIVE_BASE: ${DIST_ARCHIVE_BASE:?not set} + DISTNAME: ${DISTNAME:?not set} + HOST: ${HOST:?not set} + SOURCE_DATE_EPOCH: ${SOURCE_DATE_EPOCH:?not set} + DISTSRC: ${DISTSRC:?not set} + OUTDIR: ${OUTDIR:?not set} +EOF + +ACTUAL_OUTDIR="${OUTDIR}" +OUTDIR="${DISTSRC}/output" + +git_head_version() { + local recent_tag + if recent_tag="$(git -C "$1" describe --exact-match HEAD 2> /dev/null)"; then + echo "${recent_tag#v}" + else + git -C "$1" rev-parse --short=12 HEAD + fi +} + +mkdir -p "$OUTDIR" + +mkdir -p "$DISTSRC" +( + cd "$DISTSRC" + + tar -xf "$UNSIGNED_TARBALL" + + mkdir -p codesignatures + tar -C codesignatures -xf "$CODESIGNATURE_GIT_ARCHIVE" + + case "$HOST" in + *mingw*) + find "$PWD" -name "*-unsigned.exe" | while read -r infile; do + infile_base="$(basename "$infile")" + + # Codesigned *-unsigned.exe and output to OUTDIR + osslsigncode attach-signature \ + -in "$infile" \ + -out "${OUTDIR}/${infile_base/-unsigned}" \ + -CAfile "$GUIX_ENVIRONMENT/etc/ssl/certs/ca-certificates.crt" \ + -sigin codesignatures/win/"$infile_base".pem + done + ;; + *) + exit 1 + ;; + esac +) # $DISTSRC + +rm -rf "$ACTUAL_OUTDIR" +mv --no-target-directory "$OUTDIR" "$ACTUAL_OUTDIR" \ + || ( rm -rf "$ACTUAL_OUTDIR" && exit 1 ) + +( + cd /outdir-base + { + echo "$UNSIGNED_TARBALL" + echo "$CODESIGNATURE_GIT_ARCHIVE" + find "$ACTUAL_OUTDIR" -type f + } | xargs realpath --relative-base="$PWD" \ + | xargs sha256sum \ + | sort -k2 \ + | sponge "$ACTUAL_OUTDIR"/SHA256SUMS.part +) diff --git a/contrib/installers/windows/setup.nsi.in b/contrib/installers/windows/setup.nsi.in index 323c25f3..0e0d5eb3 100644 --- a/contrib/installers/windows/setup.nsi.in +++ b/contrib/installers/windows/setup.nsi.in @@ -1,6 +1,6 @@ Name "Feather Wallet" -OutFile "${CUR_PATH}\contrib\installers\windows\FeatherWalletSetup-@PROJECT_VERSION@.exe" +OutFile "${CUR_PATH}\contrib\installers\windows\FeatherWalletSetup-@PROJECT_VERSION@-unsigned.exe" RequestExecutionLevel highest SetCompressor /SOLID lzma SetDateSave off diff --git a/contrib/shell/guix-attest.sh b/contrib/shell/guix-attest.sh new file mode 100755 index 00000000..e7bf0596 --- /dev/null +++ b/contrib/shell/guix-attest.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +set -e -o pipefail + +# Convenience wrapper around contrib/guix/guix-attest + +if [ -z "${GUIX_SIGS_REPO}" ]; then + echo "[HINT] Fork and clone the feather-sigs repo:" + echo "https://github.com/feather-wallet/feather-sigs" + echo "" + + printf "Enter path to 'feather-sigs' repo: " + read -r repo + + if [ ! -d "${repo}" ]; then + echo "Directory does not exist" + exit 1 + fi + + export GUIX_SIGS_REPO="$repo" +fi + +if [ -z "${SIGNER}" ]; then + printf "Enter your GitHub username: " + read -r signer + + echo "" + echo "[HINT] To find your GPG fingerprint use:" + echo "gpg --list-secret-keys --keyid-format=long" + echo "It should look like: E87BD921CDD885C9D78A38C5E45B10DD027D2472" + echo "" + + printf "Enter fingerprint of your GPG key: " + read -r fingerprint + + export SIGNER="${fingerprint}=${signer}" +fi + +#echo "To skip these steps, invoke this command as:" +#echo "GUIX_SIGS_REPO=${GUIX_SIGS_REPO} SIGNER=${SIGNER} ./contrib/guix/guix-attest" + +./contrib/guix/guix-attest + +read -p "Commit changes? [Yn]: " \ No newline at end of file diff --git a/contrib/shell/guix-build.sh b/contrib/shell/guix-build.sh new file mode 100755 index 00000000..80113814 --- /dev/null +++ b/contrib/shell/guix-build.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +source contrib/guix/libexec/hosts.sh + +echo "Available targets:" +echo "---" +echo "0) build all targets" +for i in "${!DEFAULT_HOSTS[@]}"; do + echo "$((i+1))) ${DEFAULT_HOSTS[$i]}" +done + +echo "---" +read -p "Select target to build [0]: " + +./contrib/guix/guix-build diff --git a/contrib/shell/guix-codesign.sh b/contrib/shell/guix-codesign.sh new file mode 100644 index 00000000..e69de29b diff --git a/contrib/shell/guix-verify.sh b/contrib/shell/guix-verify.sh new file mode 100755 index 00000000..3b875a71 --- /dev/null +++ b/contrib/shell/guix-verify.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +set -e + +# Convenience wrapper around contrib/guix/guix-verify + +if [ -z "${GUIX_SIGS_REPO}" ]; then + printf "Enter path to 'feather-sigs' repo: " + read -r repo + + if [ ! -d "${repo}" ]; then + echo "Directory does not exist" + exit 1 + fi + + export GUIX_SIGS_REPO="$repo" +fi + +if [ -z "${SIGNER}" ]; then + printf "Enter name of signer: " + read -r signer + export SIGNER="$signer" +fi + +./contrib/guix/guix-verify