Skip to content

Commit

Permalink
Merge pull request #6 from dunkmann00/update
Browse files Browse the repository at this point in the history
Drive Backup 2.0
  • Loading branch information
dunkmann00 authored Sep 27, 2024
2 parents 1ea8e16 + 7c8df0b commit 19e1188
Show file tree
Hide file tree
Showing 65 changed files with 6,702 additions and 437 deletions.
58 changes: 58 additions & 0 deletions .github/actions/setup-keychain/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: "Setup Keychain"
description: "Sets up the Keychain on macOS for codesigning with the given
inputs."
inputs:
macos-certificate:
description: "Base64 encoded signing certificate."
required: true
macos-certificate-pwd:
description: "Password for the signing certificate."
required: true
macos-ci-keychain-pwd:
description: "A password to use for the CI keychain. Can be anything, should
be a strong randomly generated password."
required: true
runs:
using: "composite"
steps:
- name: Check for macOS
shell: bash
if: runner.os != 'macOS'
run: |
echo "setup-keychain should only be ran on a macOS runner."
exit 1
- name: Setup Keychain
shell: bash
env:
MACOS_CERTIFICATE: ${{ inputs.macos-certificate }}
MACOS_CERTIFICATE_PWD: ${{ inputs.macos-certificate-pwd }}
MACOS_CI_KEYCHAIN_PWD: ${{ inputs.macos-ci-keychain-pwd }}
CERTIFICATE_PATH: ${{ runner.temp }}/keychain/build_certificate.p12
KEYCHAIN_PATH: ${{ runner.temp }}/keychain/build.keychain
run: |
# Based on blog post by Federico Terzi & Localazy:
# https://federicoterzi.com/blog/automatic-code-signing-and-notarization-for-macos-apps-using-github-actions/
# https://localazy.com/blog/how-to-automatically-sign-macos-apps-using-github-actions
# Also based on Github"s guide for signing Xcode applications
# https://docs.github.com/en/actions/deployment/deploying-xcode-applications/installing-an-apple-certificate-on-macos-runners-for-xcode-development
# Make keychain temporary directory
mkdir $RUNNER_TEMP/keychain
# Turn our base64-encoded certificate back to a regular .p12 file
echo $MACOS_CERTIFICATE | base64 --decode > $CERTIFICATE_PATH
# We need to create a new keychain, otherwise using the certificate will prompt
# with a UI dialog asking for the certificate password, which we can"t
# use in a headless CI environment
# Create keychain
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security default-keychain -s $KEYCHAIN_PATH
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" $KEYCHAIN_PATH
# Import certificate to keychain
security import $CERTIFICATE_PATH -k $KEYCHAIN_PATH -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
security list-keychain -d user -s $KEYCHAIN_PATH
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" $KEYCHAIN_PATH
18 changes: 18 additions & 0 deletions .github/actions/setup-poetry/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Setup Poetry
description: Sets up the Keychain on macOS for codesigning with the given
inputs.
runs:
using: composite
steps:
- name: Install Poetry
shell: bash
run: |
pipx install poetry==1.8.3
poetry config virtualenvs.in-project true
pipx inject poetry poetry-plugin-export==1.8.0
# Handle paths correctly whether on windows or otherwise
pipx inject poetry "$(python -c "import pathlib; print( str(pathlib.Path.cwd() / 'poetry-plugins' / 'poetry-plugin-pin-build') )")"
- name: Install macOS plugin
if: runner.os == 'macOS'
shell: bash
run: pipx inject poetry "$(python -c "import pathlib; print( str(pathlib.Path.cwd() / 'poetry-plugins' / 'poetry-plugin-universal2-wheel') )")"
198 changes: 198 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
name: Build App

on:
push:
branches: [main]
pull_request:

workflow_call:
outputs:
pypi-artifact-name:
description: The name of the artifact containing the python sdist and wheel for pypi.
value: ${{ jobs.package-build.outputs.artifact-name }}

env:
PYTHONUNBUFFERED: 1
PYTHON_VERSION: "3.11"

jobs:
notifications-build:
uses: ./.github/workflows/notifications.yml
secrets: inherit

package-build:
name: Build PyPI Package
needs: notifications-build
runs-on: ubuntu-22.04
defaults:
run:
shell: bash
env:
ARTIFACT_NAME: pypi-package-build
outputs:
artifact-name: ${{ env.ARTIFACT_NAME }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
id: python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set pipx default python
env:
PIPX_DEFAULT_PYTHON: ${{ steps.python.outputs.python-path }}
run: echo "PIPX_DEFAULT_PYTHON=$PIPX_DEFAULT_PYTHON" >> "$GITHUB_ENV"
- name: Setup Poetry
uses: ./.github/actions/setup-poetry
- name: Get notification apps
id: download-notifications
uses: actions/download-artifact@v4
with:
path: ${{ runner.temp }}/notifications-artifacts
merge-multiple: true
- name: Unzip & move notifications apps
env:
ARTIFACTS_PATH: ${{ steps.download-notifications.outputs.download-path }}
MACOS_ARTIFACT_NAME: ${{ needs.notifications-build.outputs.macos-artifact-name }}
MACOS_BUILD_PATH: ${{ needs.notifications-build.outputs.macos-build-path }}
WINDOWS_ARTIFACT_NAME: ${{ needs.notifications-build.outputs.windows-artifact-name }}
WINDOWS_BUILD_PATH: ${{ needs.notifications-build.outputs.windows-posix-build-path }}
run: |
# macOS Notifications App
mkdir "$GITHUB_WORKSPACE/$MACOS_BUILD_PATH"
unzip "$ARTIFACTS_PATH/$MACOS_ARTIFACT_NAME.zip" -d "$GITHUB_WORKSPACE/$MACOS_BUILD_PATH"
# Windows Notifications App
mkdir "$GITHUB_WORKSPACE/$WINDOWS_BUILD_PATH"
unzip "$ARTIFACTS_PATH/$WINDOWS_ARTIFACT_NAME.zip" -d "$GITHUB_WORKSPACE/$WINDOWS_BUILD_PATH"
- name: Build package sdist & wheel
run: poetry build
- name: Upload package sdist & wheel
uses: actions/upload-artifact@v4
with:
name: ${{ env.ARTIFACT_NAME }}
path: ./dist

binary-build:
name: Build ${{ matrix.build.os }} App Binary
needs: notifications-build
runs-on: ${{ matrix.build.os }}
defaults:
run:
shell: bash
strategy:
fail-fast: false
matrix:
build:
- os: macos-14
notifications:
artifact-name: ${{ needs.notifications-build.outputs.macos-artifact-name }}
build-path: ./${{ needs.notifications-build.outputs.macos-build-path }}
- os: windows-2022
notifications:
artifact-name: ${{ needs.notifications-build.outputs.windows-artifact-name }}
build-path: .\${{ needs.notifications-build.outputs.windows-build-path }}
- os: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
id: python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set pipx default python
env:
PIPX_DEFAULT_PYTHON: ${{ steps.python.outputs.python-path }}
run: echo "PIPX_DEFAULT_PYTHON=$PIPX_DEFAULT_PYTHON" >> "$GITHUB_ENV"
- name: Setup Poetry
uses: ./.github/actions/setup-poetry
- name: Setup Keychain (macOS)
if: runner.os == 'macOS'
uses: ./.github/actions/setup-keychain
with:
macos-certificate: ${{ secrets.PROD_MACOS_CERTIFICATE }}
macos-certificate-pwd: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }}
macos-ci-keychain-pwd: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
- name: Install Drive Backup package & dependencies
run: poetry install
- name: Get notification app (macOS & Windows)
if: runner.os == 'macOS' || runner.os == 'Windows'
uses: actions/download-artifact@v4
with:
name: ${{ matrix.build.notifications.artifact-name }}
path: ${{ matrix.build.notifications.build-path }}
- name: Unzip notification app (macOS & Windows)
if: runner.os == 'macOS' || runner.os == 'Windows'
env:
NOTIFICATION_NAME: ${{ matrix.build.notifications.artifact-name }}
NOTIFICATION_BUILD: ${{ matrix.build.notifications.build-path }}
run: |
ZIP_PATH=$(python -c "import pathlib; print(pathlib.Path(r'$NOTIFICATION_BUILD') / '$NOTIFICATION_NAME.zip')")
unzip "$ZIP_PATH" -d "$NOTIFICATION_BUILD"
- name: Build app binary
env:
MACOS_CODESIGN_IDENTITY: ${{ secrets.PROD_MACOS_CERTIFICATE_IDENTITY }}
run: poetry run python app_build.py build
- name: Notarize app (macOS)
if: runner.os == 'macOS'
env:
MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
run: |
echo "Create Zip Archive"
ZIP_PATH="$(poetry run python app_build.py archive --format zip)"
# Here we send the notarization request to Apple's Notarization service, waiting for the result.
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App
# characteristics. We pass in all the credentials, including the password so that we can prevent a
# UI password dialog from blocking the CI
echo "Notarize app"
xcrun notarytool submit "$ZIP_PATH" \
--apple-id "$MACOS_NOTARIZATION_APPLE_ID" \
--team-id "$MACOS_NOTARIZATION_TEAM_ID" \
--password "$MACOS_NOTARIZATION_PWD" \
--wait
# Remove the zip, we don't need it anymore
rm "$ZIP_PATH"
# This is where we would normally "attach the staple" to our executable. Unfortunately that can't be done at
# this time:
#
# "Although tickets are created for standalone binaries, it’s not currently possible to staple tickets to them."
# (Source: https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution/customizing_the_notarization_workflow#3087720)
#
# This isn't a huge problem because our binary can still be verified on a users machine as long as there is an
# internet connection.
- name: Move notification app into binary directory (macOS & Windows)
if: runner.os == 'macOS' || runner.os == 'Windows'
run: poetry run python app_build.py add-notifications
- name: Get Archive Name
env:
RELEVANT_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: |
# Get the project's version
VERSION=$(poetry version -s)
if [ "$GITHUB_EVENT_NAME" != "release" ]; then
VERSION="$VERSION+$(git rev-parse --short $RELEVANT_SHA)"
fi
# Create the archive name and store as an environment varable
ARCHIVE_NAME=$(poetry run python app_build.py archive-name --version $VERSION)
echo "ARCHIVE_NAME=$ARCHIVE_NAME" >> "$GITHUB_ENV"
- name: Archive app
run: |
# Build the archive and store the path to it
ARCHIVE_PATH="$(poetry run python app_build.py archive --archive-name "$ARCHIVE_NAME")"
# Store the archive path as an environment variable
echo "ARCHIVE_PATH=$ARCHIVE_PATH" >> "$GITHUB_ENV"
- name: Upload binary archive
uses: actions/upload-artifact@v4
with:
name: ${{ env.ARCHIVE_NAME }}
path: ${{ env.ARCHIVE_PATH }}
56 changes: 56 additions & 0 deletions .github/workflows/github_pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Github Pages

on:
push:
# Runs when a release is published
release:
types: [released]

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write

# Allow one concurrent deployment
concurrency:
group: "pages"
cancel-in-progress: true

jobs:
# Build & Deploy Job
gh_pages:
name: Build & Deploy Github Pages
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.gh_pages.outputs.page_url }}
env:
GHP_SOURCE_DIR: pages
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Prep For Pages
run: |
# Copy md files into Pages directory
cp {README.md,Privacy.md,LICENSE.md} $GHP_SOURCE_DIR
# Copy the icon into the images sub-directory
cp src/drive_backup/resources/drive-backup-icon.png $GHP_SOURCE_DIR/images
# Update the image links in the README
sed -i 's#src/drive_backup/resources/drive-backup-icon.png#images/drive-backup-icon.png#g' $GHP_SOURCE_DIR/README.md
sed -i 's#pages/images/google-verification-warning.png#images/google-verification-warning.png#g' $GHP_SOURCE_DIR/README.md
# Update md links
sed -i 's#.md##g' $GHP_SOURCE_DIR/README.md
# Copy demo gif into Pages directory
mkdir -p $GHP_SOURCE_DIR/asciinema/demo
cp asciinema/demo/drive-backup-demo.gif $GHP_SOURCE_DIR/asciinema/demo
# Replace demo gif with asciinema player
perl -i -0777 -pe 's#<!-- asciinema-start -->(.*)<!-- asciinema-end -->#<script src="https://asciinema.org/a/656228.js" id="asciicast-656228" async="true"></script>#gs' $GHP_SOURCE_DIR/README.md
- name: Build & Deploy
id: gh_pages
uses: dunkmann00/jekyll-v4-gh-pages@v1
with:
source: ${{ env.GHP_SOURCE_DIR }}
Loading

0 comments on commit 19e1188

Please sign in to comment.