diff --git a/.github/workflows/ok-to-test.yml b/.github/workflows/ok-to-test.yml new file mode 100644 index 0000000..a9600c6 --- /dev/null +++ b/.github/workflows/ok-to-test.yml @@ -0,0 +1,25 @@ +# If someone with write access comments "/ok-to-test" on a pull request, emit a repository_dispatch event +name: Ok To Test + +on: + issue_comment: + types: [created] + +jobs: + ok-to-test: + runs-on: ubuntu-latest + # required permissions for adding reactions to the pull request comments + permissions: + pull-requests: write + # Only run for PRs, not issue comments + if: ${{ github.event.issue.pull_request }} + steps: + - name: Slash Command Dispatch + uses: peter-evans/slash-command-dispatch@v3 + with: + token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} + reaction-token: ${{ secrets.GITHUB_TOKEN }} + issue-type: pull-request + commands: ok-to-test + # The repository permission level required by the user to dispatch commands. Only allows 1Password collaborators to run this. + permission: write diff --git a/.github/workflows/test-fork.yml b/.github/workflows/test-fork.yml new file mode 100644 index 0000000..2d0e3c4 --- /dev/null +++ b/.github/workflows/test-fork.yml @@ -0,0 +1,206 @@ +on: + repository_dispatch: + types: [ok-to-test-command] +name: Run acceptance tests [fork] + +jobs: + test-with-output-secrets: + if: | + github.event_name == 'repository_dispatch' && + github.event.client_payload.slash_command.args.named.sha != '' && + contains( + github.event.client_payload.pull_request.head.sha, + github.event.client_payload.slash_command.args.named.sha + ) + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + auth: [connect, service-account] + exclude: + - os: macos-latest + auth: connect + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.client_payload.pull_request.head.sha }} + - name: Launch 1Password Connect instance + if: ${{ matrix.auth == 'connect' }} + env: + OP_CONNECT_CREDENTIALS: ${{ secrets.OP_CONNECT_CREDENTIALS }} + run: | + echo "$OP_CONNECT_CREDENTIALS" > 1password-credentials.json + docker compose -f tests/fixtures/docker-compose.yml up -d && sleep 10 + - name: Configure Service account + if: ${{ matrix.auth == 'service-account' }} + uses: ./configure + with: + service-account-token: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} + - name: Configure 1Password Connect + if: ${{ matrix.auth == 'connect' }} + uses: ./configure # 1password/load-secrets-action/configure@ + with: + connect-host: http://localhost:8080 + connect-token: ${{ secrets.OP_CONNECT_TOKEN }} + - name: Load secrets + id: load_secrets + uses: ./ # 1password/load-secrets-action@ + with: + export-env: false + env: + SECRET: op://acceptance-tests/test-secret/password + SECRET_IN_SECTION: op://acceptance-tests/test-secret/test-section/password + MULTILINE_SECRET: op://acceptance-tests/multiline-secret/notesPlain + - name: Assert test secret values + env: + SECRET: ${{ steps.load_secrets.outputs.SECRET }} + SECRET_IN_SECTION: ${{ steps.load_secrets.outputs.SECRET_IN_SECTION }} + MULTILINE_SECRET: ${{ steps.load_secrets.outputs.MULTILINE_SECRET }} + run: ./tests/assert-env-set.sh + test-with-export-env: + if: | + github.event_name == 'repository_dispatch' && + github.event.client_payload.slash_command.args.named.sha != '' && + contains( + github.event.client_payload.pull_request.head.sha, + github.event.client_payload.slash_command.args.named.sha + ) + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + auth: [connect, service-account] + exclude: + - os: macos-latest + auth: connect + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.client_payload.pull_request.head.sha }} + - name: Launch 1Password Connect instance + if: ${{ matrix.auth == 'connect' }} + env: + OP_CONNECT_CREDENTIALS: ${{ secrets.OP_CONNECT_CREDENTIALS }} + run: | + echo "$OP_CONNECT_CREDENTIALS" > 1password-credentials.json + docker compose -f tests/fixtures/docker-compose.yml up -d && sleep 10 + - name: Configure Service account + if: ${{ matrix.auth == 'service-account' }} + uses: ./configure + with: + service-account-token: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} + - name: Configure 1Password Connect + if: ${{ matrix.auth == 'connect' }} + uses: ./configure # 1password/load-secrets-action/configure@ + with: + connect-host: http://localhost:8080 + connect-token: ${{ secrets.OP_CONNECT_TOKEN }} + - name: Load secrets + id: load_secrets + uses: ./ # 1password/load-secrets-action@ + env: + SECRET: op://acceptance-tests/test-secret/password + SECRET_IN_SECTION: op://acceptance-tests/test-secret/test-section/password + MULTILINE_SECRET: op://acceptance-tests/multiline-secret/notesPlain + - name: Assert test secret values + run: ./tests/assert-env-set.sh + - name: Remove secrets + uses: ./ # 1password/load-secrets-action@ + with: + unset-previous: true + - name: Assert removed secrets + run: ./tests/assert-env-unset.sh + test-references-with-ids: + if: | + github.event_name == 'repository_dispatch' && + github.event.client_payload.slash_command.args.named.sha != '' && + contains( + github.event.client_payload.pull_request.head.sha, + github.event.client_payload.slash_command.args.named.sha + ) + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + auth: [connect, service-account] + exclude: + - os: macos-latest + auth: connect + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.client_payload.pull_request.head.sha }} + - name: Launch 1Password Connect instance + if: ${{ matrix.auth == 'connect' }} + env: + OP_CONNECT_CREDENTIALS: ${{ secrets.OP_CONNECT_CREDENTIALS }} + run: | + echo "$OP_CONNECT_CREDENTIALS" > 1password-credentials.json + docker compose -f tests/fixtures/docker-compose.yml up -d && sleep 10 + - name: Configure Service account + if: ${{ matrix.auth == 'service-account' }} + uses: ./configure + with: + service-account-token: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} + - name: Configure 1Password Connect + if: ${{ matrix.auth == 'connect' }} + uses: ./configure # 1password/load-secrets-action/configure@ + with: + connect-host: http://localhost:8080 + connect-token: ${{ secrets.OP_CONNECT_TOKEN }} + - name: Load secrets + id: load_secrets + uses: ./ # 1password/load-secrets-action@ + with: + export-env: false + env: + SECRET: op://v5pz6venw4roosmkzdq2nhpv6u/hrgkzhrlvscomepxlgafb2m3ca/password + SECRET_IN_SECTION: op://v5pz6venw4roosmkzdq2nhpv6u/hrgkzhrlvscomepxlgafb2m3ca/Section_tco6nsqycj6jcbyx63h5isxcny/doxu3mhkozcznnk5vjrkpdqayy + MULTILINE_SECRET: op://v5pz6venw4roosmkzdq2nhpv6u/ghtz3jvcc6dqmzc53d3r3eskge/notesPlain + - name: Assert test secret values + env: + SECRET: ${{ steps.load_secrets.outputs.SECRET }} + SECRET_IN_SECTION: ${{ steps.load_secrets.outputs.SECRET_IN_SECTION }} + MULTILINE_SECRET: ${{ steps.load_secrets.outputs.MULTILINE_SECRET }} + run: ./tests/assert-env-set.sh + update-checks: + # required permissions for updating the status of the pull request checks + permissions: + pull-requests: write + checks: write + runs-on: ubuntu-latest + if: ${{ always() }} + strategy: + matrix: + job-name: + [ + test-with-output-secrets, + test-with-export-env, + test-references-with-ids, + ] + needs: + [test-with-output-secrets, test-with-export-env, test-references-with-ids] + steps: + - uses: actions/github-script@v6 + env: + job: ${{ matrix.job-name }} + ref: ${{ github.event.client_payload.pull_request.head.sha }} + conclusion: ${{ needs[format('{0}', matrix.job-name )].result }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { data: checks } = await github.rest.checks.listForRef({ + ...context.repo, + ref: process.env.ref + }); + + const check = checks.check_runs.filter(c => c.name === process.env.job); + + const { data: result } = await github.rest.checks.update({ + ...context.repo, + check_run_id: check[0].id, + status: 'completed', + conclusion: process.env.conclusion + }); + + return result; diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 099d309..004e015 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ jobs: unit-tests: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: node-version: 20 @@ -16,6 +16,7 @@ jobs: - run: npm test test-with-output-secrets: + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository strategy: matrix: os: [ubuntu-latest, macos-latest] @@ -25,7 +26,7 @@ jobs: auth: connect runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Launch 1Password Connect instance if: ${{ matrix.auth == 'connect' }} env: @@ -60,6 +61,7 @@ jobs: MULTILINE_SECRET: ${{ steps.load_secrets.outputs.MULTILINE_SECRET }} run: ./tests/assert-env-set.sh test-with-export-env: + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository strategy: matrix: os: [ubuntu-latest, macos-latest] @@ -69,7 +71,7 @@ jobs: auth: connect runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Launch 1Password Connect instance if: ${{ matrix.auth == 'connect' }} env: @@ -104,6 +106,7 @@ jobs: - name: Assert removed secrets run: ./tests/assert-env-unset.sh test-references-with-ids: + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository strategy: matrix: os: [ubuntu-latest, macos-latest] @@ -113,7 +116,7 @@ jobs: auth: connect runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Launch 1Password Connect instance if: ${{ matrix.auth == 'connect' }} env: