Skip to content

Commit

Permalink
Create reusable validateActor action
Browse files Browse the repository at this point in the history
  • Loading branch information
roryabraham committed Feb 6, 2025
1 parent ba9e3fc commit 528a734
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 146 deletions.
8 changes: 8 additions & 0 deletions .github/actionlint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,11 @@ self-hosted-runner:
- macos-15-xlarge
- ubuntu-latest-reassure-tests
- macos-12

paths:
'**/*':
ignore:
# This is meant to be a temporary workaround for a bug in actionslint. Upstream:
# - issue: https://github.com/rhysd/actionlint/issues/511
# - PR: https://github.com/rhysd/actionlint/pull/513
- '"env" is not allowed in "runs" section because .* is a Composite action.*'
45 changes: 45 additions & 0 deletions .github/actions/composite/validateActor/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Validate actor
description: Validate the the current actor has the permissions they need. By default, it validates that the user has write permissions.

inputs:
# If `REQUIRE_APP_DEPLOYER` is true, we check that they're an app deployer. If not, we just check that they have write access.
REQUIRE_APP_DEPLOYER:
description: Should this action require the actor to be an app deployer?
required: false
default: 'true'
OS_BOTIFY_TOKEN:
description: OSBotify token. Needed to access certain API endpoints the regular github.token can't
required: true

runs:
using: composite
steps:
- name: Get user permissions
if: ${{ !fromJSON(inputs.REQUIRE_APP_DEPLOYER) }}
id: getUserPermissions
shell: bash
run: |
PERMISSION=$(gh api /repos/${{ github.repository }}/collaborators/${{ github.actor }}/permission | jq -r '.permission')
if [[ "$PERMISSION" == 'write' || "$PERMISSION" == 'admin' ]]; then
echo "::notice::✅ Actor ${{ github.actor }} has write permission"
else
echo "::error::❌ Actor ${{ github.actor }} does not have write permission"
exit 1
fi
env:
GITHUB_TOKEN: ${{ inputs.OS_BOTIFY_TOKEN }}

- name: Check if user is deployer
id: isUserDeployer
if: fromJSON(inputs.REQUIRE_APP_DEPLOYER)
shell: bash
run: |
if [[ "${{ github.actor }}" == "OSBotify" || "${{ github.actor }}" == "os-botify[bot]" ]] || \
gh api /orgs/Expensify/teams/mobile-deployers/memberships/${{ github.actor }} --silent; then
echo "::notice::✅ Actor ${{ github.actor }} is an app deployer"
else
echo "::error::❌ Actor ${{ github.actor }} is not an app deployer"
exit 1
fi
env:
GITHUB_TOKEN: ${{ inputs.OS_BOTIFY_TOKEN }}
18 changes: 0 additions & 18 deletions .github/workflows/cherryPick.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,7 @@ on:
required: true

jobs:
validateActor:
runs-on: ubuntu-latest
outputs:
IS_DEPLOYER: ${{ fromJSON(steps.isDeployer.outputs.IS_DEPLOYER) || github.actor == 'OSBotify' || github.actor == 'os-botify[bot]' }}
steps:
- name: Check if user is deployer
id: isDeployer
run: |
if gh api /orgs/Expensify/teams/mobile-deployers/memberships/${{ github.actor }} --silent; then
echo "IS_DEPLOYER=true" >> "$GITHUB_OUTPUT"
else
echo "IS_DEPLOYER=false" >> "$GITHUB_OUTPUT"
fi
env:
GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }}

createNewVersion:
needs: validateActor
if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }}
uses: ./.github/workflows/createNewVersion.yml
secrets: inherit

Expand Down
20 changes: 5 additions & 15 deletions .github/workflows/createNewVersion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,16 @@ on:
required: true

jobs:
validateActor:
runs-on: ubuntu-latest
outputs:
HAS_WRITE_ACCESS: ${{ contains(fromJSON('["write", "admin"]'), steps.getUserPermissions.outputs.PERMISSION) }}
steps:
- name: Get user permissions
id: getUserPermissions
run: echo "PERMISSION=$(gh api /repos/${{ github.repository }}/collaborators/${{ github.actor }}/permission | jq -r '.permission')" >> "$GITHUB_OUTPUT"
env:
GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_COMMIT_TOKEN }}

createNewVersion:
runs-on: macos-latest
needs: validateActor
if: ${{ fromJSON(needs.validateActor.outputs.HAS_WRITE_ACCESS) }}

outputs:
NEW_VERSION: ${{ steps.bumpVersion.outputs.NEW_VERSION }}

steps:
- name: Validate actor
uses: ./.github/actions/composite/validateActor
with:
OS_BOTIFY_TOKEN: ${{ secrets.OS_BOTIFY_COMMIT_TOKEN }}

- name: Run turnstyle
uses: softprops/turnstyle@49108bdfa571e62371bd2c3094893c547ab3fc03
with:
Expand Down
25 changes: 6 additions & 19 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,7 @@ concurrency:
cancel-in-progress: true

jobs:
validateActor:
runs-on: ubuntu-latest
timeout-minutes: 90
outputs:
IS_DEPLOYER: ${{ fromJSON(steps.isUserDeployer.outputs.IS_DEPLOYER) || github.actor == 'OSBotify' || github.actor == 'os-botify[bot]' }}
steps:
- name: Check if user is deployer
id: isUserDeployer
run: |
if gh api /orgs/Expensify/teams/mobile-deployers/memberships/${{ github.actor }} --silent; then
echo "IS_DEPLOYER=true" >> "$GITHUB_OUTPUT"
else
echo "IS_DEPLOYER=false" >> "$GITHUB_OUTPUT"
fi
env:
GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }}

prep:
needs: validateActor
if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }}
runs-on: ubuntu-latest
outputs:
APP_VERSION: ${{ steps.getAppVersion.outputs.VERSION }}
Expand All @@ -41,6 +22,12 @@ jobs:
with:
token: ${{ secrets.OS_BOTIFY_TOKEN }}

- name: Validate actor
id: validateActor
uses: ./.github/actions/composite/validateActor
with:
OS_BOTIFY_TOKEN: ${{ secrets.OS_BOTIFY_COMMIT_TOKEN }}

- name: Setup git for OSBotify
uses: ./.github/actions/composite/setupGitForOSBotifyApp
id: setupGitForOSBotify
Expand Down
84 changes: 35 additions & 49 deletions .github/workflows/testBuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,56 +14,49 @@ env:
PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }}

jobs:
validateActor:
prep:
runs-on: ubuntu-latest
outputs:
READY_TO_BUILD: ${{ fromJSON(steps.isExpensifyEmployee.outputs.IS_EXPENSIFY_EMPLOYEE) && fromJSON(steps.hasReadyToBuildLabel.outputs.HAS_READY_TO_BUILD_LABEL) }}
REF: ${{ github.event.pull_request.head.sha || steps.getHeadRef.outputs.REF }}
READY_TO_BUILD: ${{ steps.readyToBuild.outputs.READY_TO_BUILD }}
steps:
- name: Is Expensify employee
id: isExpensifyEmployee
run: |
if gh api /orgs/Expensify/teams/expensify-expensify/memberships/${{ github.actor }} --silent; then
echo "IS_EXPENSIFY_EMPLOYEE=true" >> "$GITHUB_OUTPUT"
else
echo "IS_EXPENSIFY_EMPLOYEE=false" >> "$GITHUB_OUTPUT"
fi
env:
GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }}
- name: Checkout
if: ${{ github.event_name == 'workflow_dispatch' }}
uses: actions/checkout@v4

- name: Validate that user is an Expensify employee
uses: ./.github/actions/composite/validateActor
with:
REQUIRE_APP_DEPLOYER: false
OS_BOTIFY_TOKEN: ${{ secrets.OS_BOTIFY_COMMIT_TOKEN }}

- id: hasReadyToBuildLabel
name: Set HAS_READY_TO_BUILD_LABEL flag
- name: Check if PR has Ready to Build label
id: readyToBuild
run: |
echo "HAS_READY_TO_BUILD_LABEL=$(gh pr view "${{ env.PULL_REQUEST_NUMBER }}" --repo Expensify/App --json labels --jq '.labels[].name' | grep -q 'Ready To Build' && echo 'true')" >> "$GITHUB_OUTPUT"
if [[ "$HAS_READY_TO_BUILD_LABEL" != 'true' ]]; then
echo "The 'Ready to Build' label is not attached to the PR #${{ env.PULL_REQUEST_NUMBER }}"
LABELS=$(gh pr view "${{ env.PULL_REQUEST_NUMBER }}" --repo Expensify/App --json labels --jq '.labels[].name')
if echo "$LABELS" | grep -q 'Ready To Build'; then
echo "::notice::✅ PR ${{ env.PULL_REQUEST_NUMBER }} has 'Ready to Build' label"
echo "READY_TO_BUILD=true" >> "$GITHUB_OUTPUT"
else
echo "::error::❌ PR ${{ env.PULL_REQUEST_NUMBER }} does not have 'Ready to Build' label"
echo "READY_TO_BUILD=false" >> "$GITHUB_OUTPUT"
exit 1
fi
env:
GITHUB_TOKEN: ${{ github.token }}

getBranchRef:
runs-on: ubuntu-latest
needs: validateActor
if: ${{ fromJSON(needs.validateActor.outputs.READY_TO_BUILD) }}
outputs:
REF: ${{ steps.getHeadRef.outputs.REF }}
steps:
- name: Checkout
if: ${{ github.event_name == 'workflow_dispatch' }}
uses: actions/checkout@v4

- name: Check if pull request number is correct
if: ${{ github.event_name == 'workflow_dispatch' }}
id: getHeadRef
run: |
set -e
echo "REF=$(gh pr view ${{ github.event.inputs.PULL_REQUEST_NUMBER }} --json headRefOid --jq '.headRefOid')" >> "$GITHUB_OUTPUT"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ github.token }}

postGitHubCommentBuildStarted:
runs-on: ubuntu-latest
needs: [validateActor, getBranchRef]
if: ${{ fromJSON(needs.validateActor.outputs.READY_TO_BUILD) }}
needs: [prep]
steps:
- name: Add build start comment
uses: actions/github-script@v7
Expand All @@ -81,12 +74,11 @@ jobs:
buildAndroid:
name: Build Android app for testing
uses: ./.github/workflows/buildAndroid.yml
if: ${{ fromJSON(needs.validateActor.outputs.READY_TO_BUILD) }}
needs: [validateActor, getBranchRef]
needs: [prep]
secrets: inherit
with:
type: adhoc
ref: ${{ github.event.pull_request.head.sha || needs.getBranchRef.outputs.REF }}
ref: ${{ needs.prep.outputs.REF }}
pull_request_number: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }}

uploadAndroid:
Expand Down Expand Up @@ -135,16 +127,15 @@ jobs:
iOS:
name: Build and deploy iOS for testing
needs: [validateActor, getBranchRef]
if: ${{ fromJSON(needs.validateActor.outputs.READY_TO_BUILD) }}
needs: [prep]
env:
DEVELOPER_DIR: /Applications/Xcode_16.2.0.app/Contents/Developer
runs-on: macos-15-xlarge
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || needs.getBranchRef.outputs.REF }}
ref: ${{ needs.prep.outputs.REF }}

- name: Configure MapBox SDK
run: ./scripts/setup-mapbox-sdk.sh ${{ secrets.MAPBOX_SDK_DOWNLOAD_TOKEN }}
Expand Down Expand Up @@ -224,14 +215,13 @@ jobs:

desktop:
name: Build and deploy Desktop for testing
needs: [validateActor, getBranchRef]
if: ${{ fromJSON(needs.validateActor.outputs.READY_TO_BUILD) }}
needs: [prep]
runs-on: macos-14-large
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || needs.getBranchRef.outputs.REF }}
ref: ${{ needs.prep.outputs.REF }}

- name: Create .env.adhoc file based on staging and add PULL_REQUEST_NUMBER env to it
run: |
Expand Down Expand Up @@ -273,14 +263,13 @@ jobs:

web:
name: Build and deploy Web
needs: [validateActor, getBranchRef]
if: ${{ fromJSON(needs.validateActor.outputs.READY_TO_BUILD) }}
needs: [prep]
runs-on: ubuntu-latest-xl
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || needs.getBranchRef.outputs.REF }}
ref: ${{ needs.prep.outputs.REF }}

- name: Create .env.adhoc file based on staging and add PULL_REQUEST_NUMBER env to it
run: |
Expand All @@ -307,18 +296,16 @@ jobs:
postGithubComment:
runs-on: ubuntu-latest
name: Post a GitHub comment with app download links for testing
needs: [validateActor, getBranchRef, uploadAndroid, iOS, desktop, web]
if: ${{ always() }}
needs: [prep, uploadAndroid, iOS, desktop, web]
if: ${{ always() && needs.prep.outputs.READY_TO_BUILD == 'true' }}
steps:
- name: Checkout
uses: actions/checkout@v4
if: ${{ fromJSON(needs.validateActor.outputs.READY_TO_BUILD) }}
with:
ref: ${{ github.event.pull_request.head.sha || needs.getBranchRef.outputs.REF }}
ref: ${{ needs.prep.outputs.REF }}

- name: Download Artifact
uses: actions/download-artifact@v4
if: ${{ fromJSON(needs.validateActor.outputs.READY_TO_BUILD) }}

- name: Read JSONs with iOS paths
id: get_ios_path
Expand All @@ -332,7 +319,6 @@ jobs:
echo "ios_path=$ios_path" >> "$GITHUB_OUTPUT"
- name: Publish links to apps for download
if: ${{ fromJSON(needs.validateActor.outputs.READY_TO_BUILD) }}
uses: ./.github/actions/javascript/postTestBuildComment
with:
PR_NUMBER: ${{ env.PULL_REQUEST_NUMBER }}
Expand Down
Loading

0 comments on commit 528a734

Please sign in to comment.