Compare commits

..

9 Commits

Author SHA1 Message Date
Dustin Ruetz
2722cfb5c8 feat(release.config.cjs): specify exported semantic-release object as GlobalConfig type
Some checks failed
Release / Release (push) Has been cancelled
Run acceptance tests / unit-tests (push) Has been cancelled
Run acceptance tests / test-with-output-secrets (connect, ubuntu-latest) (push) Has been cancelled
Run acceptance tests / test-with-output-secrets (service-account, macos-latest) (push) Has been cancelled
Run acceptance tests / test-with-output-secrets (service-account, ubuntu-latest) (push) Has been cancelled
Run acceptance tests / test-with-export-env (connect, ubuntu-latest) (push) Has been cancelled
Run acceptance tests / test-with-export-env (service-account, macos-latest) (push) Has been cancelled
Run acceptance tests / test-with-export-env (service-account, ubuntu-latest) (push) Has been cancelled
Run acceptance tests / test-references-with-ids (connect, ubuntu-latest) (push) Has been cancelled
Run acceptance tests / test-references-with-ids (service-account, macos-latest) (push) Has been cancelled
Run acceptance tests / test-references-with-ids (service-account, ubuntu-latest) (push) Has been cancelled
2024-04-04 21:17:49 -04:00
Dustin Ruetz
0b5bf555f1 fix: Git repo URL protocols (use SSH in package.json and HTTPS in release.config.cjs) 2024-04-04 21:16:10 -04:00
Dustin Ruetz
cca0f55ece docs: clarify code comments 2024-04-04 21:14:15 -04:00
Dustin Ruetz
baa29d5bd0 feat(release.config.cjs): initial configuration file for semantic-release 2024-04-04 16:34:09 -04:00
Dustin Ruetz
7ffac7f68a fix(package.json): switch 'repository.url' to HTTPS syntax 2024-04-04 16:28:41 -04:00
Dustin Ruetz
1b0b59a7a7 test: run release.yml workflow on push to this working branch 2024-04-03 18:36:21 -04:00
Dustin Ruetz
da98918135 test: run release.yml workflow on pull_request 2024-04-03 17:28:11 -04:00
Dustin Ruetz
e99f0139fe feat(.github/workflows): testing initial Release workflow file 2024-04-03 17:23:56 -04:00
Dustin Ruetz
82b420f3b7 fix(package.json): switch 'repository.url' to SSH syntax 2024-04-03 17:22:55 -04:00
23 changed files with 7184 additions and 39587 deletions

View File

@@ -1,116 +0,0 @@
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
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:
version: ${{ inputs.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,7 +1,4 @@
on: on: pull_request
push:
branches: [main]
pull_request:
name: Lint name: Lint
jobs: jobs:
@@ -14,16 +11,3 @@ 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

View File

@@ -1,25 +0,0 @@
# 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

@@ -1,13 +0,0 @@
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

44
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,44 @@
name: Release
on:
push:
branches:
# TODO: This branch is for PR testing purposes; update branch to "main" if we proceed with this PR.
- ruetz-automate-releases
# Specify that this "Release" workflow depends on the other workflows below completing successfully.
workflow_run:
workflows: ["Lint", "Run acceptance tests"]
types:
- completed
permissions:
contents: read # for checkout
jobs:
release:
name: Release
runs-on: ubuntu-latest
permissions:
contents: write # to be able to publish a GitHub release
issues: write # to be able to comment on released issues
pull-requests: write # to be able to comment on released pull requests
id-token: write # to enable use of OIDC for npm provenance
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "lts/*"
- name: Install dependencies
run: npm clean-install
- name: Verify the integrity of provenance attestations and registry signatures for installed dependencies
run: npm audit signatures
- name: Build codebase
run: npm run build
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npx semantic-release

View File

@@ -1,92 +0,0 @@
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,7 +1,4 @@
on: on: push
push:
branches: [main]
pull_request:
name: Run acceptance tests name: Run acceptance tests
jobs: jobs:
@@ -16,85 +13,134 @@ 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@main
secrets: inherit
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest]
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
- os: windows-latest runs-on: ${{ matrix.os }}
auth: connect steps:
with: - uses: actions/checkout@v3
os: ${{ matrix.os }} - name: Launch 1Password Connect instance
version: ${{ matrix.version }} if: ${{ matrix.auth == 'connect' }}
auth: ${{ matrix.auth }} env:
secret: op://acceptance-tests/test-secret/password OP_CONNECT_CREDENTIALS: ${{ secrets.OP_CONNECT_CREDENTIALS }}
secret-in-section: op://acceptance-tests/test-secret/test-section/password run: |
multiline-secret: op://acceptance-tests/multiline-secret/notesPlain echo "$OP_CONNECT_CREDENTIALS" > 1password-credentials.json
export-env: false 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:
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@main
secrets: inherit
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest]
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
- os: windows-latest runs-on: ${{ matrix.os }}
auth: connect steps:
with: - uses: actions/checkout@v3
os: ${{ matrix.os }} - name: Launch 1Password Connect instance
version: ${{ matrix.version }} if: ${{ matrix.auth == 'connect' }}
auth: ${{ matrix.auth }} env:
secret: op://acceptance-tests/test-secret/password OP_CONNECT_CREDENTIALS: ${{ secrets.OP_CONNECT_CREDENTIALS }}
secret-in-section: op://acceptance-tests/test-secret/test-section/password run: |
multiline-secret: op://acceptance-tests/multiline-secret/notesPlain echo "$OP_CONNECT_CREDENTIALS" > 1password-credentials.json
export-env: true 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>
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@main
secrets: inherit
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest]
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
- os: windows-latest runs-on: ${{ matrix.os }}
auth: connect steps:
with: - uses: actions/checkout@v3
os: ${{ matrix.os }} - name: Launch 1Password Connect instance
version: ${{ matrix.version }} if: ${{ matrix.auth == 'connect' }}
auth: ${{ matrix.auth }} env:
secret: op://v5pz6venw4roosmkzdq2nhpv6u/hrgkzhrlvscomepxlgafb2m3ca/password OP_CONNECT_CREDENTIALS: ${{ secrets.OP_CONNECT_CREDENTIALS }}
secret-in-section: op://v5pz6venw4roosmkzdq2nhpv6u/hrgkzhrlvscomepxlgafb2m3ca/Section_tco6nsqycj6jcbyx63h5isxcny/doxu3mhkozcznnk5vjrkpdqayy run: |
multiline-secret: op://v5pz6venw4roosmkzdq2nhpv6u/ghtz3jvcc6dqmzc53d3r3eskge/notesPlain echo "$OP_CONNECT_CREDENTIALS" > 1password-credentials.json
export-env: false 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:
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,7 +3,6 @@
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:
@@ -11,15 +10,13 @@ After following the steps below for signing commits, you can test against your P
1. Create or use an existing repo to run the `load-secrets` GitHub Action. 1. Create or use an existing repo to run the `load-secrets` GitHub Action.
2. In a workflow yaml file that uses the GitHub Action, modify the `uses: 1Password/load-secrets-action` line to be 2. In a workflow yaml file that uses the GitHub Action, modify the `uses: 1Password/load-secrets-action` line to be
```yaml ```yaml
uses: 1Password/load-secrets-action@<branch-name> uses: 1Password/load-secrets-action@<branch-name>
``` ```
OR
OR ```yaml
uses: 1Password/load-secrets-action@<commit-hash>
```yaml ```
uses: 1Password/load-secrets-action@<commit-hash>
```
3. Trigger the action, which now includes your changes. 3. Trigger the action, which now includes your changes.

View File

@@ -23,40 +23,16 @@ 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@v4 - uses: actions/checkout@v3
- name: Load secret - name: Load secret
id: load_secret uses: 1password/load-secrets-action@v2
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
@@ -72,11 +48,13 @@ 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://developer.1password.com/joinslack). - Join the [Developer Slack workspace](https://join.slack.com/t/1password-devs/shared_invite/zt-1halo11ps-6o9pEv96xZ3LtX_VE0fJQA).
- 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 by sending an email to bugbounty@agilebits.com. Please file requests via [**BugCrowd**](https://bugcrowd.com/agilebits).
For information about security practices, please visit the [1Password Bug Bounty Program](https://bugcrowd.com/agilebits).

View File

@@ -10,10 +10,7 @@ inputs:
default: "false" default: "false"
export-env: export-env:
description: Export the secrets as environment variables description: Export the secrets as environment variables
default: "false" default: "true"
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,5 +9,12 @@ inputs:
service-account-token: service-account-token:
description: Your 1Password service account token description: Your 1Password service account token
runs: runs:
using: "node20" using: composite
main: "dist/index.js" steps:
- 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

File diff suppressed because one or more lines are too long

View File

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

21
configure/entrypoint.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/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

View File

@@ -1,27 +0,0 @@
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();

12569
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": "commonjs" "type": "module"
} }

46
install_cli.sh Executable file
View File

@@ -0,0 +1,46 @@
#!/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

5890
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,14 @@
{ {
"name": "load-secrets-action", "name": "load-secrets-action",
"version": "3.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 ./",
@@ -25,7 +24,7 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/1Password/load-secrets-action.git" "url": "git@github.com:1Password/load-secrets-action.git"
}, },
"keywords": [ "keywords": [
"actions", "actions",
@@ -42,12 +41,10 @@
"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/eslint-config": "^4.3.1", "@1password/front-end-style": "^6.0.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",
@@ -58,7 +55,7 @@
"typescript": "^5.4.2" "typescript": "^5.4.2"
}, },
"eslintConfig": { "eslintConfig": {
"extends": "@1password/eslint-config", "extends": "./node_modules/@1password/front-end-style/eslintrc.yml",
"ignorePatterns": [ "ignorePatterns": [
"coverage/" "coverage/"
], ],
@@ -66,5 +63,5 @@
"project": "./tsconfig.json" "project": "./tsconfig.json"
} }
}, },
"prettier": "@1password/prettier-config" "prettier": "./node_modules/@1password/front-end-style/prettierrc.json"
} }

15
release.config.cjs Normal file
View File

@@ -0,0 +1,15 @@
/** @type {import('semantic-release').GlobalConfig} */
module.exports = {
// TODO: This branch is for PR testing purposes; update branch to "main" if we proceed with this PR.
branches: ["ruetz-automate-releases"],
// TODO: Remove `dryRun` configuration if we proceed with this PR.
dryRun: true,
plugins: [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/github",
],
// Use the `https` Git protocol here to prevent semantic-release from erroring
// on the SSH protocol used in `repository.url` in the package.json file.
repositoryUrl: "https://github.com/1Password/load-secrets-action.git",
};

View File

@@ -1,6 +1,8 @@
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 () => {
@@ -44,7 +46,21 @@ 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 () => {
await installCliOnGithubActionRunner(); const currentFile = url.fileURLToPath(import.meta.url);
const currentDir = path.dirname(currentFile);
const parentDir = path.resolve(currentDir, "..");
// 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).toThrow(authErr); expect(validateAuth).toThrowError(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).toThrow(authErr); expect(validateAuth).toThrowError(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.toThrow(authErr); expect(validateAuth).not.toThrowError(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.toThrow(authErr); expect(validateAuth).not.toThrowError(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.toThrow(authErr); expect(validateAuth).not.toThrowError(authErr);
expect(core.warning).toHaveBeenCalled(); expect(core.warning).toHaveBeenCalled();
expect(core.info).toHaveBeenCalledWith("Authenticated with Connect."); expect(core.info).toHaveBeenCalledWith("Authenticated with Connect.");
}); });