Compare commits

...

43 Commits

Author SHA1 Message Date
Volodymyr Zotov
9fd72bcae7 Point to the feature branch to run tests 2025-08-14 11:43:38 -05:00
Volodymyr Zotov
4c8b833188 Make latest build 2025-08-14 11:40:05 -05:00
Volodymyr Zotov
b10aa9ed81 Fix tests 2025-08-14 11:39:57 -05:00
Volodymyr Zotov
b9110a4b5b Rename version input to cli-version 2025-08-14 10:58:58 -05:00
Volodymyr Zotov
438a01224c Merge pull request #114 from 1Password/vzt/change-default-export-env
Set `export-env` input to `false` by default
2025-08-14 10:01:11 -05:00
Volodymyr Zotov
ba891d4bf2 Update readme 2025-08-14 09:59:24 -05:00
Volodymyr Zotov
909c7e01f1 Fix formatting 2025-08-13 17:41:42 -05:00
Volodymyr Zotov
1c443d83da Update README.md to show examples of using as step outputs and env vars 2025-08-13 17:35:23 -05:00
Volodymyr Zotov
867fee7815 Set export-env input to false by default 2025-08-13 17:03:58 -05:00
Volodymyr Zotov
7914f19c4d Merge pull request #113 from 1Password/vzt/bump-op-cli-installer
Bump op-cli-installer version
2025-08-13 16:48:44 -05:00
Volodymyr Zotov
25aa72f51b Point to the latest op-cli-installer commit from main 2025-08-13 16:29:10 -05:00
Volodymyr Zotov
2fa8a509ca Point to the latest main for acceptance tests 2025-08-13 16:08:37 -05:00
Volodymyr Zotov
f30ae37660 Bump to the latest op-cli-installer version that set's defaults 2025-08-13 15:40:06 -05:00
Volodymyr Zotov
29afdd3b50 Merge pull request #112 from 1Password/vzt/set-default-cli-version
Set default for `version` input
2025-08-13 15:11:49 -05:00
Volodymyr Zotov
c03c0b6bbe Set default for version input 2025-08-13 14:16:47 -05:00
Volodymyr Zotov
a8d5f2a285 Merge pull request #109 from 1Password/vzt/use-op-cli-installer
Use op cli installer to enable Windows support
2025-08-13 12:56:35 -05:00
Volodymyr Zotov
f5fc2382af Treat module as commonjs 2025-08-13 12:06:22 -05:00
Volodymyr Zotov
596d8007a1 Introduce build:all command that bundles both configure and load-secrets-action. Remove type: "module" from package.json so ncc builds CommonJS configure action which is required 2025-08-13 11:59:45 -05:00
Volodymyr Zotov
c9ae724dfd Use latest commit hash for op-cli-installer package 2025-08-08 19:31:32 -05:00
Volodymyr Zotov
40b6ef7b57 Remove verify cli version step from a job to reduce complexity.
This should be properly tested in op-cli-installer package. Current test will confirm that secrets are loaded correctly.
2025-08-08 19:28:20 -05:00
Volodymyr Zotov
a4866d442c Remove bash script 2025-08-05 16:13:17 -05:00
Volodymyr Zotov
10084cd57d Re-build configure action as commonjs 2025-08-05 11:49:35 -05:00
Volodymyr Zotov
d6b7427345 Change configure action type to commonjs 2025-08-05 11:47:12 -05:00
Volodymyr Zotov
96de656797 Re-write configure action in JS 2025-08-05 11:45:36 -05:00
Volodymyr Zotov
c0724d8845 Add more tests to check that action works correctly with provided stable or beta version 2025-08-05 11:45:36 -05:00
Volodymyr Zotov
3a62b7cf63 Use op-cli-installer package to install CLI 2025-08-05 10:37:09 -05:00
Eduard Filip
43fd9cdb84 Merge pull request #103 from 1Password/eddy/fix-dependabot-alerts
Fix Dependabot alerts
2025-07-15 16:03:02 +02:00
Eddy Filip
73195c1d43 Fix Dependabot alerts 2025-07-14 18:19:51 +02:00
Eduard Filip
85e0e789db Merge pull request #100 from 1Password/fix/fork-workflow
In #97 it was missed to adjust the reusable workflow to pull changes from the forked commit. Instead, now we pull from base repository, which doesn't contain the external contributor's changes.

I've also improved the way we reference the reusable workflow to ensure we're using a trusted reusable workflow that won't change often.
2025-03-05 17:11:01 +01:00
Eddy Filip
39cf694bee Reference the reusable workflow from main
This is a safer approach since the main branch is protected. Therefore any chages to the reusable workflow will be intentional.
2025-03-05 10:25:55 +01:00
Eddy Filip
39b7248332 Add checking out from forked head 2025-03-05 10:25:52 +01:00
Eduard Filip
a5e5c78980 Merge pull request #97 from 1Password/feat/run-e2e-test-on-fork
Currently an external contributor can't have the acceptance tests run on their PR because pull_request doesn't give access to the secrets needed for them.

Therefore, in this PR we create a new workflow that is identical to the one for existing acceptance tests, with the following differences:

This workflow can be triggered with the command /ok-to-test sha="<contributor's latest commit sha>" by one of this repo's maintainers.
After the acceptance tests finish, their result will be updated to the PR's list of checks.
2025-03-04 13:57:05 +01:00
Eddy Filip
7d16183347 Add fork workflow for acceptance tests
This file contains the same acceptance test jobs with the following differences:
- They only run if the `ok-to-test` command triggered the workflow and a sha has been passed.
- They checkout from the external contributor's commit.

Lastly, this workflow contains an extra job which updates the status in the PR based on the jobs executed. The result of a job is the parent result of all the matrix variants executed as part of it.
2025-03-04 11:01:13 +01:00
Eddy Filip
0cbceff209 Add ok-to-test command
This command will trigger an end-to-end workflow with the external contributor's code.
2025-03-04 11:01:09 +01:00
Eddy Filip
fec5c39dcc Add condition to run tests only on maintainer's branches 2025-03-04 11:01:06 +01:00
Eduard Filip
a525a84c53 Refactor acceptance tests (#99)
This workflow is the acceptance tests executed based on the following inputs:
- secret references
- whether the secrets are provided as a step output or environment variables.
2025-03-03 14:49:37 +01:00
Eduard Filip
6483669c68 Fix workflow branch syntax (#90)
In a previous PR we used `branch` syntax to trigger the pipeline when a push on `main` was made. This was a mistake and `branches` is the correct syntax that achieves this.
2024-12-18 14:35:57 +01:00
Eduard Filip
06962f2427 Switch to new lint packages (#89)
In Oct 2023, @1password/front-end-style has been rewritten into 3 smaller packages:
- @1password/eslint-config
- @1password/prettier-config
- @1password/stylelint-config

These 3 new packages have the same configurations as the previous package, with the benefits of being up-to-date and better organized. In the case of this GitHub Action, we only need the first two. The last one is dedicated to CSS stylling, which is not used in this action. Therefore, we will replace the deprecated @1password/front-end-style with the following packages:
- @1password/eslint-config
- @1password/prettier-config
2024-12-18 14:35:41 +01:00
Eduard Filip
3e2909a6b2 Add lint to workflow (#88)
* Add lint in workflow

This will check for code formatting, as well as for any ES lint issues.

* Format code

run `npm run check:write`

* Run lint and fix errors

Run `npm run lint` and then fix the errors shown.
2024-12-17 11:05:12 +01:00
Eduard Filip
734cd437f8 Make workflow targets more specific (#87)
This ensures that:
- Acceptance tests ar run on Pull requests
- Lint is run on `main`
- The workflows are executed only once on PRs
2024-12-17 11:04:57 +01:00
Eduard Filip
555e0c6a63 Update bug bounty process (#86)
* Update bug bounty process

* Fix docker compose command
2024-12-12 18:14:15 +01:00
Eduard Filip
0a309926fa Fix Developer Slack workspace link (#76) 2024-07-12 14:19:55 +02:00
Eduard Filip
a51c02d593 Run 1Password/check-signed-commits-action for PRs (#73)
Add the 1Password/check-signed-commits-action that will leave a handy comment if a PR contains commits that are not signed.
2024-05-28 19:34:06 +02:00
21 changed files with 39602 additions and 7136 deletions

116
.github/workflows/acceptance-test.yml vendored Normal file
View File

@@ -0,0 +1,116 @@
name: Acceptance test
on:
workflow_call:
inputs:
secret:
required: true
type: string
secret-in-section:
required: true
type: string
multiline-secret:
required: true
type: string
export-env:
required: true
type: boolean
cli-version:
required: false
type: string
default: "latest"
os:
required: true
type: string
default: "ubuntu-latest"
auth:
required: true
type: string
jobs:
acceptance-test:
runs-on: ${{ inputs.os }}
steps:
- name: Base checkout
uses: actions/checkout@v4
if: |
github.event_name != 'repository_dispatch' &&
(
github.ref == 'refs/heads/main' ||
(
github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository
)
)
- name: Fork based /ok-to-test checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.client_payload.pull_request.head.sha }}
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
)
- name: Launch 1Password Connect instance
if: ${{ inputs.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: ${{ inputs.auth == 'service-account' }}
uses: ./configure
with:
service-account-token: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
- name: Verify Service Account env var is set
if: ${{ inputs.auth == 'service-account' }}
shell: bash
run: |
if [ -z "${OP_SERVICE_ACCOUNT_TOKEN}" ]; then
echo "OP_SERVICE_ACCOUNT_TOKEN environment variable is not set" >&2
exit 1
fi
- name: Configure 1Password Connect
if: ${{ inputs.auth == 'connect' }}
uses: ./configure # 1password/load-secrets-action/configure@<version>
with:
connect-host: http://localhost:8080
connect-token: ${{ secrets.OP_CONNECT_TOKEN }}
- name: Verify Connect env vars are set
if: ${{ inputs.auth == 'connect' }}
run: |
if [ -z "$OP_CONNECT_HOST" ] || [ -z "$OP_CONNECT_TOKEN" ]; then
echo "OP_CONNECT_HOST or OP_CONNECT_TOKEN environment variables are not set" >&2
exit 1
fi
- name: Load secrets
id: load_secrets
uses: ./ # 1password/load-secrets-action@<version>
with:
cli-version: ${{ inputs.cli-version }}
export-env: ${{ inputs.export-env }}
env:
SECRET: ${{ inputs.secret }}
SECRET_IN_SECTION: ${{ inputs.secret-in-section }}
MULTILINE_SECRET: ${{ inputs.multiline-secret }}
- name: Assert test secret values [step output]
if: ${{ !inputs.export-env }}
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
- name: Assert test secret values [exported env]
if: ${{ inputs.export-env }}
run: ./tests/assert-env-set.sh
- name: Remove secrets [exported env]
if: ${{ inputs.export-env }}
uses: ./ # 1password/load-secrets-action@<version>
with:
unset-previous: true
- name: Assert removed secrets [exported env]
if: ${{ inputs.export-env }}
run: ./tests/assert-env-unset.sh

View File

@@ -1,4 +1,7 @@
on: pull_request on:
push:
branches: [main]
pull_request:
name: Lint name: Lint
jobs: jobs:
@@ -11,3 +14,16 @@ jobs:
with: with:
ignore_paths: >- ignore_paths: >-
.husky .husky
- name: Setup Node.js
id: setup-node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install Dependencies
id: install
run: npm ci
- name: Check formatting
run: npm run format:check
- name: Check lint
run: npm run lint

25
.github/workflows/ok-to-test.yml vendored Normal file
View File

@@ -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
permissions:
pull-requests: write # For adding reactions to the pull request comments
contents: write # For executing the repository_dispatch event
# 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.GITHUB_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

View File

@@ -0,0 +1,13 @@
name: Check signed commits in PR
on: pull_request_target
jobs:
build:
name: Check signed commits in PR
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Check signed commits in PR
uses: 1Password/check-signed-commits-action@v1

92
.github/workflows/test-fork.yml vendored Normal file
View File

@@ -0,0 +1,92 @@
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
)
uses: 1password/load-secrets-action/.github/workflows/acceptance-test.yml@main
secrets: inherit
with:
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
export-env: false
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
)
uses: 1password/load-secrets-action/.github/workflows/acceptance-test.yml@main
secrets: inherit
with:
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
export-env: true
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
)
uses: 1password/load-secrets-action/.github/workflows/acceptance-test.yml@main
secrets: inherit
with:
secret: op://v5pz6venw4roosmkzdq2nhpv6u/hrgkzhrlvscomepxlgafb2m3ca/password
secret-in-section: op://v5pz6venw4roosmkzdq2nhpv6u/hrgkzhrlvscomepxlgafb2m3ca/Section_tco6nsqycj6jcbyx63h5isxcny/doxu3mhkozcznnk5vjrkpdqayy
multiline-secret: op://v5pz6venw4roosmkzdq2nhpv6u/ghtz3jvcc6dqmzc53d3r3eskge/notesPlain
export-env: false
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;

View File

@@ -1,4 +1,7 @@
on: push on:
push:
branches: [main]
pull_request:
name: Run acceptance tests name: Run acceptance tests
jobs: jobs:
@@ -13,134 +16,85 @@ jobs:
- run: npm test - run: npm test
test-with-output-secrets: test-with-output-secrets:
if: |
github.ref == 'refs/heads/main' ||
(
github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository
)
uses: 1password/load-secrets-action/.github/workflows/acceptance-test.yml@vzt/rename-version-input # TODO: temporary point to this branch so tests can run with update input
secrets: inherit
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest] os: [ubuntu-latest, macos-latest, windows-latest]
cli-version: [latest, latest-beta, 2.30.0, 2.30.0-beta.03]
auth: [connect, service-account] auth: [connect, service-account]
exclude: exclude:
- os: macos-latest - os: macos-latest
auth: connect auth: connect
runs-on: ${{ matrix.os }} - os: windows-latest
steps: auth: connect
- uses: actions/checkout@v3
- 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@<version>
with:
connect-host: http://localhost:8080
connect-token: ${{ secrets.OP_CONNECT_TOKEN }}
- name: Load secrets
id: load_secrets
uses: ./ # 1password/load-secrets-action@<version>
with: with:
os: ${{ matrix.os }}
cli-version: ${{ matrix.cli-version }}
auth: ${{ matrix.auth }}
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
export-env: false 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: test-with-export-env:
if: |
github.ref == 'refs/heads/main' ||
(
github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository
)
uses: 1password/load-secrets-action/.github/workflows/acceptance-test.yml@vzt/rename-version-input # TODO: temporary point to this branch so tests can run with update input
secrets: inherit
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest] os: [ubuntu-latest, macos-latest, windows-latest]
cli-version: [latest, latest-beta, 2.30.0, 2.30.0-beta.03]
auth: [connect, service-account] auth: [connect, service-account]
exclude: exclude:
- os: macos-latest - os: macos-latest
auth: connect auth: connect
runs-on: ${{ matrix.os }} - os: windows-latest
steps: auth: connect
- uses: actions/checkout@v3
- 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: with:
service-account-token: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} os: ${{ matrix.os }}
- name: Configure 1Password Connect cli-version: ${{ matrix.cli-version }}
if: ${{ matrix.auth == 'connect' }} auth: ${{ matrix.auth }}
uses: ./configure # 1password/load-secrets-action/configure@<version> secret: op://acceptance-tests/test-secret/password
with: secret-in-section: op://acceptance-tests/test-secret/test-section/password
connect-host: http://localhost:8080 multiline-secret: op://acceptance-tests/multiline-secret/notesPlain
connect-token: ${{ secrets.OP_CONNECT_TOKEN }} export-env: true
- name: Load secrets
id: load_secrets
uses: ./ # 1password/load-secrets-action@<version>
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@<version>
with:
unset-previous: true
- name: Assert removed secrets
run: ./tests/assert-env-unset.sh
test-references-with-ids: test-references-with-ids:
if: |
github.ref == 'refs/heads/main' ||
(
github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository
)
uses: 1password/load-secrets-action/.github/workflows/acceptance-test.yml@vzt/rename-version-input # TODO: temporary point to this branch so tests can run with update input
secrets: inherit
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest] os: [ubuntu-latest, macos-latest, windows-latest]
cli-version: [latest, latest-beta, 2.30.0, 2.30.0-beta.03]
auth: [connect, service-account] auth: [connect, service-account]
exclude: exclude:
- os: macos-latest - os: macos-latest
auth: connect auth: connect
runs-on: ${{ matrix.os }} - os: windows-latest
steps: auth: connect
- uses: actions/checkout@v3
- 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@<version>
with:
connect-host: http://localhost:8080
connect-token: ${{ secrets.OP_CONNECT_TOKEN }}
- name: Load secrets
id: load_secrets
uses: ./ # 1password/load-secrets-action@<version>
with: with:
os: ${{ matrix.os }}
cli-version: ${{ matrix.cli-version }}
auth: ${{ matrix.auth }}
secret: op://v5pz6venw4roosmkzdq2nhpv6u/hrgkzhrlvscomepxlgafb2m3ca/password
secret-in-section: op://v5pz6venw4roosmkzdq2nhpv6u/hrgkzhrlvscomepxlgafb2m3ca/Section_tco6nsqycj6jcbyx63h5isxcny/doxu3mhkozcznnk5vjrkpdqayy
multiline-secret: op://v5pz6venw4roosmkzdq2nhpv6u/ghtz3jvcc6dqmzc53d3r3eskge/notesPlain
export-env: false 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

View File

@@ -3,6 +3,7 @@
Thank you for your interest in contributing to the 1Password load-secrets-action project 👋! Before you start, please take a moment to read through this guide to understand our contribution process. Thank you for your interest in contributing to the 1Password load-secrets-action project 👋! Before you start, please take a moment to read through this guide to understand our contribution process.
## Testing ## Testing
Unit tests can be run with `npm run test`. Unit tests can be run with `npm run test`.
After following the steps below for signing commits, you can test against your PR with these steps: After following the steps below for signing commits, you can test against your PR with these steps:
@@ -13,7 +14,9 @@ After following the steps below for signing commits, you can test against your P
```yaml ```yaml
uses: 1Password/load-secrets-action@<branch-name> uses: 1Password/load-secrets-action@<branch-name>
``` ```
OR OR
```yaml ```yaml
uses: 1Password/load-secrets-action@<commit-hash> uses: 1Password/load-secrets-action@<commit-hash>
``` ```

View File

@@ -23,16 +23,40 @@ Read more on the [1Password Developer Portal](https://developer.1password.com/do
## ✨ Quickstart ## ✨ Quickstart
### Export secrets as a step's output (recommended)
```yml ```yml
on: push on: push
jobs: jobs:
hello-world: hello-world:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Load secret - name: Load secret
uses: 1password/load-secrets-action@v2 id: load_secret
uses: 1password/load-secrets-action@v3
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
SECRET: op://app-cicd/hello-world/secret
- name: Print masked secret
run: 'echo "Secret: ${{ steps.load_secrets.outputs.SECRET }}"'
# Prints: Secret: ***
```
### Export secrets as env variables
```yml
on: push
jobs:
hello-world:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Load secret
uses: 1password/load-secrets-action@v3
with: with:
# Export loaded secrets as environment variables # Export loaded secrets as environment variables
export-env: true export-env: true
@@ -48,13 +72,11 @@ jobs:
## 💙 Community & Support ## 💙 Community & Support
- File an [issue](https://github.com/1Password/load-secrets-action/issues) for bugs and feature requests. - File an [issue](https://github.com/1Password/load-secrets-action/issues) for bugs and feature requests.
- Join the [Developer Slack workspace](https://join.slack.com/t/1password-devs/shared_invite/zt-1halo11ps-6o9pEv96xZ3LtX_VE0fJQA). - Join the [Developer Slack workspace](https://developer.1password.com/joinslack).
- Subscribe to the [Developer Newsletter](https://1password.com/dev-subscribe/). - Subscribe to the [Developer Newsletter](https://1password.com/dev-subscribe/).
## 🔐 Security ## 🔐 Security
1Password requests you practice responsible disclosure if you discover a vulnerability. 1Password requests you practice responsible disclosure if you discover a vulnerability.
Please file requests via [**BugCrowd**](https://bugcrowd.com/agilebits). Please file requests by sending an email to bugbounty@agilebits.com.
For information about security practices, please visit the [1Password Bug Bounty Program](https://bugcrowd.com/agilebits).

View File

@@ -10,7 +10,10 @@ inputs:
default: "false" default: "false"
export-env: export-env:
description: Export the secrets as environment variables description: Export the secrets as environment variables
default: "true" default: "false"
cli-version:
description: Specify which 1Password CLI version to install. Defaults to "latest".
default: "latest"
runs: runs:
using: "node20" using: "node20"
main: "dist/index.js" main: "dist/index.js"

View File

@@ -9,12 +9,5 @@ inputs:
service-account-token: service-account-token:
description: Your 1Password service account token description: Your 1Password service account token
runs: runs:
using: composite using: "node20"
steps: main: "dist/index.js"
- shell: bash
env:
INPUT_CONNECT_HOST: ${{ inputs.connect-host }}
INPUT_CONNECT_TOKEN: ${{ inputs.connect-token }}
INPUT_SERVICE_ACCOUNT_TOKEN: ${{ inputs.service-account-token }}
run: |
${{ github.action_path }}/entrypoint.sh

27588
configure/dist/index.js vendored Normal file

File diff suppressed because one or more lines are too long

3
configure/dist/package.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"type": "commonjs"
}

View File

@@ -1,21 +0,0 @@
#!/bin/bash
# shellcheck disable=SC2086
set -e
# Capture Connect configuration in $GITHUB_ENV, giving (optional) inputs
# precendence over OP_CONNECT_* environment variables.
OP_CONNECT_HOST="${INPUT_CONNECT_HOST:-$OP_CONNECT_HOST}"
if [ -n "$OP_CONNECT_HOST" ]; then
echo "OP_CONNECT_HOST=$OP_CONNECT_HOST" >> $GITHUB_ENV
fi
OP_CONNECT_TOKEN="${INPUT_CONNECT_TOKEN:-$OP_CONNECT_TOKEN}"
if [ -n "$OP_CONNECT_TOKEN" ]; then
echo "OP_CONNECT_TOKEN=$OP_CONNECT_TOKEN" >> $GITHUB_ENV
fi
OP_SERVICE_ACCOUNT_TOKEN="${INPUT_SERVICE_ACCOUNT_TOKEN:-$OP_SERVICE_ACCOUNT_TOKEN}"
if [ -n "$OP_SERVICE_ACCOUNT_TOKEN" ]; then
echo "OP_SERVICE_ACCOUNT_TOKEN=$OP_SERVICE_ACCOUNT_TOKEN" >> $GITHUB_ENV
fi

27
configure/index.js Normal file
View File

@@ -0,0 +1,27 @@
const core = require("@actions/core");
const configure = () => {
const OP_CONNECT_HOST =
core.getInput("connect-host", { required: false }) ||
process.env.OP_CONNECT_HOST;
const OP_CONNECT_TOKEN =
core.getInput("connect-token", { required: false }) ||
process.env.OP_CONNECT_TOKEN;
const OP_SERVICE_ACCOUNT_TOKEN =
core.getInput("service-account-token", { required: false }) ||
process.env.OP_SERVICE_ACCOUNT_TOKEN;
if (OP_CONNECT_HOST) {
core.exportVariable("OP_CONNECT_HOST", OP_CONNECT_HOST);
}
if (OP_CONNECT_TOKEN) {
core.exportVariable("OP_CONNECT_TOKEN", OP_CONNECT_TOKEN);
}
if (OP_SERVICE_ACCOUNT_TOKEN) {
core.exportVariable("OP_SERVICE_ACCOUNT_TOKEN", OP_SERVICE_ACCOUNT_TOKEN);
}
};
configure();

12443
dist/index.js vendored

File diff suppressed because one or more lines are too long

2
dist/package.json vendored
View File

@@ -1,3 +1,3 @@
{ {
"type": "module" "type": "commonjs"
} }

View File

@@ -1,46 +0,0 @@
#!/bin/bash
set -e
# Install op-cli
install_op_cli() {
# Create a temporary directory where the CLI is installed
OP_INSTALL_DIR="$(mktemp -d)"
if [[ ! -d "$OP_INSTALL_DIR" ]]; then
echo "Install dir $OP_INSTALL_DIR not found"
exit 1
fi
echo "::debug::OP_INSTALL_DIR: ${OP_INSTALL_DIR}"
# Get the latest stable version of the CLI
CLI_VERSION="v$(curl https://app-updates.agilebits.com/check/1/0/CLI2/en/2.0.0/N -s | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+')"
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
# Get runner's architecture
ARCH=$(uname -m)
if [[ "$(getconf LONG_BIT)" = 32 ]]; then
ARCH="386"
elif [[ "$ARCH" == "x86_64" ]]; then
ARCH="amd64"
elif [[ "$ARCH" == "aarch64" ]]; then
ARCH="arm64"
fi
if [[ "$ARCH" != "386" ]] && [[ "$ARCH" != "amd64" ]] && [[ "$ARCH" != "arm" ]] && [[ "$ARCH" != "arm64" ]]; then
echo "Unsupported architecture for the 1Password CLI: $ARCH."
exit 1
fi
curl -sSfLo op.zip "https://cache.agilebits.com/dist/1P/op2/pkg/${CLI_VERSION}/op_linux_${ARCH}_${CLI_VERSION}.zip"
unzip -od "$OP_INSTALL_DIR" op.zip && rm op.zip
elif [[ "$OSTYPE" == "darwin"* ]]; then
curl -sSfLo op.pkg "https://cache.agilebits.com/dist/1P/op2/pkg/${CLI_VERSION}/op_apple_universal_${CLI_VERSION}.pkg"
pkgutil --expand op.pkg temp-pkg
tar -xvf temp-pkg/op.pkg/Payload -C "$OP_INSTALL_DIR"
rm -rf temp-pkg && rm op.pkg
else
echo "Operating system not supported yet for this GitHub Action: $OSTYPE."
exit 1
fi
}
install_op_cli

5928
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,13 +2,14 @@
"name": "load-secrets-action", "name": "load-secrets-action",
"version": "2.0.0", "version": "2.0.0",
"description": "Load Secrets from 1Password", "description": "Load Secrets from 1Password",
"type": "module",
"main": "dist/index.js", "main": "dist/index.js",
"directories": { "directories": {
"test": "tests" "test": "tests"
}, },
"scripts": { "scripts": {
"build": "ncc build ./src/index.ts", "build": "ncc build ./src/index.ts",
"build:configure": "ncc build ./configure/index.js -o ./configure/dist",
"build:all": "npm run build && npm run build:configure",
"format": "prettier --ignore-path ./config/.prettierignore", "format": "prettier --ignore-path ./config/.prettierignore",
"format:check": "npm run format -- --check ./", "format:check": "npm run format -- --check ./",
"format:write": "npm run format -- --write ./", "format:write": "npm run format -- --write ./",
@@ -41,10 +42,12 @@
"dependencies": { "dependencies": {
"@1password/op-js": "^0.1.11", "@1password/op-js": "^0.1.11",
"@actions/core": "^1.10.1", "@actions/core": "^1.10.1",
"@actions/exec": "^1.1.1" "@actions/exec": "^1.1.1",
"op-cli-installer": "github:1Password/op-cli-installer#e6c1c758bc3339e5fe9b06255728039f688f73fa"
}, },
"devDependencies": { "devDependencies": {
"@1password/front-end-style": "^6.0.1", "@1password/eslint-config": "^4.3.1",
"@1password/prettier-config": "^1.2.0",
"@types/jest": "^29.5.12", "@types/jest": "^29.5.12",
"@types/node": "^20.11.30", "@types/node": "^20.11.30",
"@vercel/ncc": "^0.38.1", "@vercel/ncc": "^0.38.1",
@@ -55,7 +58,7 @@
"typescript": "^5.4.2" "typescript": "^5.4.2"
}, },
"eslintConfig": { "eslintConfig": {
"extends": "./node_modules/@1password/front-end-style/eslintrc.yml", "extends": "@1password/eslint-config",
"ignorePatterns": [ "ignorePatterns": [
"coverage/" "coverage/"
], ],
@@ -63,5 +66,5 @@
"project": "./tsconfig.json" "project": "./tsconfig.json"
} }
}, },
"prettier": "./node_modules/@1password/front-end-style/prettierrc.json" "prettier": "@1password/prettier-config"
} }

View File

@@ -1,8 +1,6 @@
import path from "path";
import url from "url";
import * as core from "@actions/core"; import * as core from "@actions/core";
import * as exec from "@actions/exec";
import { validateCli } from "@1password/op-js"; import { validateCli } from "@1password/op-js";
import { installCliOnGithubActionRunner } from "op-cli-installer";
import { loadSecrets, unsetPrevious, validateAuth } from "./utils"; import { loadSecrets, unsetPrevious, validateAuth } from "./utils";
const loadSecretsAction = async () => { const loadSecretsAction = async () => {
@@ -46,21 +44,9 @@ const installCLI = async (): Promise<void> => {
// If there's no CLI installed, then validateCli will throw an error, which we will use // If there's no CLI installed, then validateCli will throw an error, which we will use
// as an indicator that we need to execute the installation script. // as an indicator that we need to execute the installation script.
await validateCli().catch(async () => { await validateCli().catch(async () => {
const currentFile = url.fileURLToPath(import.meta.url); // defaults to `latest` if not provided
const currentDir = path.dirname(currentFile); const cliVersion = core.getInput("cli-version");
const parentDir = path.resolve(currentDir, ".."); await installCliOnGithubActionRunner(cliVersion);
// Execute bash script
const cmdOut = await exec.getExecOutput(
`sh -c "` + parentDir + `/install_cli.sh"`,
);
// Add path to 1Password CLI to $PATH
const outArr = cmdOut.stdout.split("\n");
if (outArr[0] && process.env.PATH) {
const cliPath = outArr[0]?.replace(/^(::debug::OP_INSTALL_DIR: )/, "");
core.addPath(cliPath);
}
}); });
}; };

View File

@@ -39,24 +39,24 @@ describe("validateAuth", () => {
}); });
it("should throw an error when no config is provided", () => { it("should throw an error when no config is provided", () => {
expect(validateAuth).toThrowError(authErr); expect(validateAuth).toThrow(authErr);
}); });
it("should throw an error when partial Connect config is provided", () => { it("should throw an error when partial Connect config is provided", () => {
process.env[envConnectHost] = testConnectHost; process.env[envConnectHost] = testConnectHost;
expect(validateAuth).toThrowError(authErr); expect(validateAuth).toThrow(authErr);
}); });
it("should be authenticated as a Connect client", () => { it("should be authenticated as a Connect client", () => {
process.env[envConnectHost] = testConnectHost; process.env[envConnectHost] = testConnectHost;
process.env[envConnectToken] = testConnectToken; process.env[envConnectToken] = testConnectToken;
expect(validateAuth).not.toThrowError(authErr); expect(validateAuth).not.toThrow(authErr);
expect(core.info).toHaveBeenCalledWith("Authenticated with Connect."); expect(core.info).toHaveBeenCalledWith("Authenticated with Connect.");
}); });
it("should be authenticated as a service account", () => { it("should be authenticated as a service account", () => {
process.env[envServiceAccountToken] = testServiceAccountToken; process.env[envServiceAccountToken] = testServiceAccountToken;
expect(validateAuth).not.toThrowError(authErr); expect(validateAuth).not.toThrow(authErr);
expect(core.info).toHaveBeenCalledWith( expect(core.info).toHaveBeenCalledWith(
"Authenticated with Service account.", "Authenticated with Service account.",
); );
@@ -66,7 +66,7 @@ describe("validateAuth", () => {
process.env[envServiceAccountToken] = testServiceAccountToken; process.env[envServiceAccountToken] = testServiceAccountToken;
process.env[envConnectHost] = testConnectHost; process.env[envConnectHost] = testConnectHost;
process.env[envConnectToken] = testConnectToken; process.env[envConnectToken] = testConnectToken;
expect(validateAuth).not.toThrowError(authErr); expect(validateAuth).not.toThrow(authErr);
expect(core.warning).toHaveBeenCalled(); expect(core.warning).toHaveBeenCalled();
expect(core.info).toHaveBeenCalledWith("Authenticated with Connect."); expect(core.info).toHaveBeenCalledWith("Authenticated with Connect.");
}); });