diff --git a/README.md b/README.md index fd85a3d..a543955 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Expensify Shared GitHub Actions workflows 🔄 +# Expensify Shared GitHub Actions workflows 🔄 ## What is the repository used for? @@ -18,7 +18,7 @@ jobs: with: # Repository name with owner. For example, Expensify/eslint-config-expensify # Required, String, default: ${{ github.repository }} - repository: '' + repository: "" # True if we should run npm run build for the package # Optional, Boolean, default: false @@ -37,13 +37,23 @@ jobs: secrets: inherit ``` +### `setup-ubuntu-gpg-cache` + +Installs the Expensify aptly GPG key and caches Ubuntu apt keyserver exports for faster `apt-get` in CI. See [setup-ubuntu-gpg-cache/README.md](./setup-ubuntu-gpg-cache/README.md) for details. + +```yml +- name: Setup Ubuntu GPG Cache + uses: Expensify/GitHub-Actions/setup-ubuntu-gpg-cache@main +``` + ## Rulesets + GitHub [org-level rulesets](https://docs.github.com/en/enterprise-cloud@latest/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets#require-workflows-to-pass-before-merging) can be configured to run a workflow check against pull requests in all repos in the org. This is a very powerful feature, but there are some caveats and best practices to be aware of when enabling a ruleset. - Supported Event Triggers are documented [here](https://docs.github.com/en/enterprise-cloud@latest/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets#supported-event-triggers). However: - - When a workflow runs in response to a ruleset, some configs such as `branches`, `paths`, `paths-ignore`, that would normally be valid in a workflow are ignored. - - The default activity types for each event will be used. This means that something like `pull_request:comment` will not work - the `pull_request` event will always be triggered for the default activity types listed in the documentation. - - If you need to target or exclude specific branches, that can be configured in the ruleset settings. - - If you need to target or exclude specific paths, that must be implemented manually in the workflow itself. + - When a workflow runs in response to a ruleset, some configs such as `branches`, `paths`, `paths-ignore`, that would normally be valid in a workflow are ignored. + - The default activity types for each event will be used. This means that something like `pull_request:comment` will not work - the `pull_request` event will always be triggered for the default activity types listed in the documentation. + - If you need to target or exclude specific branches, that can be configured in the ruleset settings. + - If you need to target or exclude specific paths, that must be implemented manually in the workflow itself. - Due to a GitHub :bug:, PRs that are open when the rule is enabled will get stuck with a pending check that will never get picked up. The easiest way to fix that is to close and reopen the PR. Consider writing a script to close and reopen all open PRs across the org after the check is enabled. - It is less disruptive to [configure the ruleset to `Evaluate` first](https://docs.github.com/en/enterprise-cloud@latest/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets#using-evaluate-mode-for-ruleset-workflows), then `Active` once the kinks are worked out. diff --git a/setup-ubuntu-gpg-cache/README.md b/setup-ubuntu-gpg-cache/README.md new file mode 100644 index 0000000..4b77189 --- /dev/null +++ b/setup-ubuntu-gpg-cache/README.md @@ -0,0 +1,17 @@ +# setup-ubuntu-gpg-cache + +Composite action that installs the Expensify aptly GPG key and caches Ubuntu apt keyserver exports so CI jobs can run `apt-get` without repeated keyserver lookups. + +## Usage + +```yaml +- name: Setup Ubuntu GPG Cache + uses: Expensify/GitHub-Actions/setup-ubuntu-gpg-cache@main +``` + +## What it does + +1. Installs `aptly-public.gpg` from the action directory into `/etc/apt/trusted.gpg.d/aptly.gpg`. +2. Restores a daily GPG key export from the GitHub Actions cache. +3. On an exact same-day cache hit, imports the cached keys. +4. On a miss or stale partial hit, fetches required keys from `keyserver.ubuntu.com` and re-exports them for caching. diff --git a/setup-ubuntu-gpg-cache/action.yml b/setup-ubuntu-gpg-cache/action.yml new file mode 100644 index 0000000..d44dba2 --- /dev/null +++ b/setup-ubuntu-gpg-cache/action.yml @@ -0,0 +1,49 @@ +name: Set up GPG Cache +description: Set up GPG Cache + +runs: + using: composite + steps: + - name: Get Date for cache keying + id: get-date + run: | + echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT + shell: bash + + - name: Install local aptly key + run: | + sudo install -o root -g root -m 644 "${{ github.action_path }}/aptly-public.gpg" /etc/apt/trusted.gpg.d/aptly.gpg + shell: bash + + - name: Restore GPG key cache + id: gpg-cache + # v4.2.0 + uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 + with: + path: ./apt-key-export.gpg + key: "${{ runner.os }}-keyserver-${{ steps.get-date.outputs.date }}" + restore-keys: | + ${{ runner.os }}-keyserver- + + # Only import from cache on an exact same-day hit; a restore-keys partial hit means + # the keys are stale and we should re-fetch from keyservers instead. + - name: Import keys from cache (exact hit only) + if: steps.gpg-cache.outputs.cache-hit == 'true' + run: sudo apt-key add ./apt-key-export.gpg + shell: bash + + # Contact keyservers on a cache miss or a stale restore-keys partial hit to ensure + # keys are refreshed daily. This avoids perpetuating stale signing keys indefinitely. + - name: Fetch keys from keyservers (miss or stale partial hit) + if: steps.gpg-cache.outputs.cache-hit != 'true' + run: | + # NB: apt-key is deprecated so these lines will stop working in the near future + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3B4FE6ACC0B21F32 || true + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 871920D1991BC93C || true + shell: bash + + - name: Export keys for caching + run: | + sudo rm -f ./apt-key-export.gpg + sudo apt-key exportall > ./apt-key-export.gpg + shell: bash diff --git a/setup-ubuntu-gpg-cache/aptly-public.gpg b/setup-ubuntu-gpg-cache/aptly-public.gpg new file mode 100644 index 0000000..b7054c9 Binary files /dev/null and b/setup-ubuntu-gpg-cache/aptly-public.gpg differ