Merge pull request #5 from 1Password/feature/add-cli

Add the op CLI in the script
This commit is contained in:
volodymyrZotov
2022-08-30 10:53:31 +03:00
committed by GitHub
12 changed files with 2739 additions and 171 deletions

View File

@@ -2,7 +2,7 @@ on: push
name: Run acceptance tests
jobs:
test:
use-connect-without-export-env:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
@@ -18,34 +18,145 @@ jobs:
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://v5pz6venw4roosmkzdq2nhpv6u/hrgkzhrlvscomepxlgafb2m3ca/password
SECRET_IN_SECTION: op://v5pz6venw4roosmkzdq2nhpv6u/hrgkzhrlvscomepxlgafb2m3ca/test-section/password
UNMASKED_VALUE: op://v5pz6venw4roosmkzdq2nhpv6u/hrgkzhrlvscomepxlgafb2m3ca/test-section/username
- name: Load multiline secret
uses: ./ # 1password/load-secrets-action@<version>
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:
MULTILINE_SECRET: op://v5pz6venw4roosmkzdq2nhpv6u/ghtz3jvcc6dqmzc53d3r3eskge/notesPlain
- name: Print environment variables with masked secrets
run: printenv
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
use-connect-with-export-env:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Launch 1Password Connect instance
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 1Password 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: true
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: Print environment variables with secrets removed
run: printenv
- name: Assert removed secrets
run: ./tests/assert-env-unset.sh
- name: Load secrets by vault and item titles
use-connect-with-references-with-id:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Launch 1Password Connect instance
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 1Password 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://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
use-service-account-without-export-env:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Load secrets
id: load_secrets
uses: ./ # 1password/load-secrets-action@<version>
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
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: Print environment variables with masked secrets
run: printenv
- name: Assert test secret values again
- 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
use-service-account-with-export-env:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Load secrets
id: load_secrets
uses: ./ # 1password/load-secrets-action@<version>
with:
export-env: true
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
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
use-service-account-with-references-with-id:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Load secrets
id: load_secrets
uses: ./ # 1password/load-secrets-action@<version>
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
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
run-on-macos-12:
runs-on: macos-12
steps:
- uses: actions/checkout@v2
- name: Load secrets
id: load_secrets
uses: ./ # 1password/load-secrets-action@<version>
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
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

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
node_modules/

155
README.md
View File

@@ -1,11 +1,28 @@
# Load Secrets from 1Password - GitHub Action
The action to load secrets from [1Password Connect](https://1password.com/secrets/) into GitHub Actions.
This action loads secrets from 1Password into GitHub Actions using [1Password Connect](https://1password.com/secrets/) or a Service Account.
Specify right from your workflow YAML which secrets from 1Password should be loaded into your job, and the action will make them available as environment variables for the next steps.
## Usage
You can configure the action to use either 1Password Connect instance or a 1Password Service Account. Service Accounts are currently in Beta and are only available to select users.
If you provide `OP_CONNECT_HOST` and `OP_CONNECT_TOKEN` variables, the Connect instance will be used to load secrets. Make sure [1Password Connect](https://support.1password.com/secrets-automation/#step-2-deploy-a-1password-connect-server) is deployed in your infrastructure.
If you provide `OP_SERVICE_ACCOUNT_TOKEN` variable, the service account will be used to load secrets.
**_Note_**: If all environment variables have been set, the Connect credentials will take precedence over the provided service account token. You must unset the Connect environment variables to ensure the action uses the service account token.
There are two ways that secrets can be loaded:
- [use the secrets from the action's ouput](#use-secrets-from-the-actions-output)
- [export secrets as environment variables](#export-secrets-as-environment-variables)
### Use secrets from the action's output
This method allows for you to use the loaded secrets as an output from the step: `steps.step-id.outputs.secret-name`. You will need to set an id for the step that uses this action to be able to access its outputs. For more details, , see [`outputs.<output_id>`](https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#outputsoutput_id).
```yml
on: push
jobs:
@@ -15,6 +32,7 @@ jobs:
- uses: actions/checkout@v2
- name: Load secret
id: op-load-secret
uses: 1password/load-secrets-action@v1
env:
OP_CONNECT_HOST: <Your Connect instance URL>
@@ -22,9 +40,10 @@ jobs:
SECRET: op://app-cicd/hello-world/secret
- name: Print masked secret
run: echo "Secret: $SECRET"
run: echo "Secret: ${{ steps.op-load-secret.outputs.SECRET }}"
# Prints: Secret: ***
```
<details>
<summary><b>Longer usage example</b></summary>
@@ -41,13 +60,87 @@ jobs:
- name: Configure 1Password Connect
uses: 1password/load-secrets-action/configure@v1
with:
# Persist the 1Password Connect URL for next steps. You can also persist
# the Connect token using input `connect-token`, but keep in mind that
# Persist the 1Password Connect URL for next steps. You can also persist
# the Connect token using input `connect-token`, but keep in mind that
# every single step in the job would then be able to access the token.
connect-host: https://1password.acme.com
- name: Load Docker credentials
id: load-docker-credentials
uses: 1password/load-secrets-action@v1
env:
OP_CONNECT_TOKEN: ${{ secrets.OP_CONNECT_TOKEN }}
DOCKERHUB_USERNAME: op://app-cicd/docker/username
DOCKERHUB_TOKEN: op://app-cicd/docker/token
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ steps.load-docker-credentials.outputs.DOCKERHUB_USERNAME }}
password: ${{ steps.load-docker-credentials.outputs.DOCKERHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v2
with:
push: true
tags: acme/app:latest
```
</details>
### Export secrets as environment variables
This method, allows the action to access the loaded secrets as environment variables. These environment variables are accessible at a job level.
```yml
on: push
jobs:
hello-world:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Load secret
uses: 1password/load-secrets-action@v1
with:
# Export loaded secrets as environment variables
export-env: true
env:
OP_CONNECT_HOST: <Your Connect instance URL>
OP_CONNECT_TOKEN: ${{ secrets.OP_CONNECT_TOKEN }}
SECRET: op://app-cicd/hello-world/secret
- name: Print masked secret
run: echo "Secret: $SECRET"
# Prints: Secret: ***
```
<details>
<summary><b>Longer usage example</b></summary>
```yml
on: push
name: Deploy app
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Configure 1Password Connect
uses: 1password/load-secrets-action/configure@v1
with:
# Persist the 1Password Connect URL for next steps. You can also persist
# the Connect token using input `connect-token`, but keep in mind that
# every single step in the job would then be able to access the token.
connect-host: https://1password.acme.com
- name: Load Docker credentials
uses: 1password/load-secrets-action@v1
with:
# Export loaded secrets as environment variables
export-env: true
env:
OP_CONNECT_TOKEN: ${{ secrets.OP_CONNECT_TOKEN }}
DOCKERHUB_USERNAME: op://app-cicd/docker/username
@@ -71,6 +164,8 @@ jobs:
- name: Load AWS credentials
uses: 1password/load-secrets-action@v1
with:
# Export loaded secrets as environment variables
export-env: true
# Remove local copies of the Docker credentials, which are not needed anymore
unset-previous: true
env:
@@ -79,16 +174,18 @@ jobs:
AWS_SECRET_ACCESS_KEY: op://app-cicd/aws/secret-access-key
- name: Deploy app
# This script expects AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY to be set, which was
# This script expects AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY to be set, which was
# done automatically by the step above
run: ./deploy.sh
```
</details>
## Action Inputs
| Name | Default | Description |
|---|---|---|
| Name | Default | Description |
| ---------------- | ------- | ---------------------------------------------------------------------------------- |
| `export-env` | `false` | Export the loaded secrets as environment variables |
| `unset-previous` | `false` | Whether to unset environment variables populated by 1Password in earlier job steps |
## Secrets Reference Syntax
@@ -100,23 +197,23 @@ These reference URIs have the following syntax:
> `op://<vault>/<item>[/<section>]/<field>`
So for example, the reference URI `op://app-cicd/aws/secret-access-key` would be interpreted as:
* **Vault:** `app-cicd`
* **Item:** `aws`
* **Section:** default section
* **Field:** `secret-access-key`
- **Vault:** `app-cicd`
- **Item:** `aws`
- **Section:** default section
- **Field:** `secret-access-key`
## Masking
Similar to regular GitHub repository secrets, secret fields from 1Password will automatically be masked from the GitHub Actions logs too.
A 1Password field is considered 'secret' when it's marked as concealed (which shows as `•••••••` in the 1Password GUI) or when it's a secure note.
Similar to regular GitHub repository secrets, fields from 1Password will automatically be masked from the GitHub Actions logs too.
So if one of these values accidentally gets printed, it'll get replaced with `***`.
This means that a username or port field for example will not get masked.
## 1Password Configuration
## 1Password Connect Configuration
To use the action, you need to have a [1Password Connect](https://support.1password.com/secrets-automation/#step-1-set-up-a-secrets-automation-workflow) instance deployed somewhere.
To configure the action with your Connect URL and a Connect token, you can set the `OP_CONNECT_HOST` and `OP_CONNECT_TOKEN` variables.
To use the action with Connect, you need to have a [1Password Connect](https://support.1password.com/secrets-automation/#step-1-set-up-a-secrets-automation-workflow) instance deployed somewhere.
To configure the action with your Connect host and token, set the `OP_CONNECT_HOST` and `OP_CONNECT_TOKEN` environment variables.
To configure the action with your service account token, set the `OP_SERVICE_ACCOUNT_TOKEN` environment variable.
**_ Note: _** Service Accounts are currently in Beta and are only available to select users.
If you're using the `load-secrets` action more than once in a single job, you can use the `configure` action to avoid duplicate configuration:
@@ -133,7 +230,6 @@ jobs:
with:
connect-host: <Your Connect instance URL>
connect-token: ${{ secrets.OP_CONNECT_TOKEN }}
- name: Load secret
uses: 1password/load-secrets-action@v1
env:
@@ -142,11 +238,24 @@ jobs:
### `configure` Action Inputs
| Name | Default | Environment variable | Description |
|---|---|---|---|
| `connect-host` | | `OP_CONNECT_HOST` | Your 1Password Connect instance URL |
| `connect-token` | | `OP_CONNECT_TOKEN` | Token to authenticate to your 1Password Connect instance |
| Name | Default | Environment variable | Description |
| ----------------------- | ------- | -------------------------- | -------------------------------------------------------- |
| `connect-host` | | `OP_CONNECT_HOST` | Your 1Password Connect instance URL |
| `connect-token` | | `OP_CONNECT_TOKEN` | Token to authenticate to your 1Password Connect instance |
| `service-account-token` | | `OP_SERVICE_ACCOUNT_TOKEN` | Your 1Password service account token |
## Supported Runners
You can run the action on Linux and macOS runners. Windows is currently not supported.
## Security
1Password requests you practice responsible disclosure if you discover a vulnerability.
Please file requests via [**BugCrowd**](https://bugcrowd.com/agilebits).
For information about security practices, please visit our [Security homepage](https://bugcrowd.com/agilebits).
## Getting help
If you find yourself stuck, visit our [**Support Page**](https://support.1password.com/) for help.

View File

@@ -8,11 +8,9 @@ inputs:
unset-previous:
description: Whether to unset environment variables populated by 1Password in earlier job steps
default: false
export-env:
description: Export the secrets as environment variables
default: false
runs:
using: composite
steps:
- shell: bash
env:
INPUT_UNSET_PREVIOUS: ${{ inputs.unset-previous }}
run: |
${{ github.action_path }}/entrypoint.sh
using: 'node16'
main: 'dist/index.js'

View File

@@ -1,11 +1,13 @@
name: Configure 1Password Connect
description: Persist 1Password Connect host and token for use in next steps.
name: Configure 1Password Connect and service account
description: Persist 1Password Connect host, token and service account for use in next steps.
author: 1Password
inputs:
connect-host:
description: Your 1Password Connect instance URL
connect-token:
description: Token to authenticate to your 1Password Connect instance
service-account-token:
description: Your 1Password service account token
runs:
using: composite
steps:
@@ -13,5 +15,6 @@ runs:
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

View File

@@ -14,3 +14,8 @@ 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

1954
dist/index.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,153 +2,118 @@
# shellcheck disable=SC2046,SC2001,SC2086
set -e
if [ -z "$OP_CONNECT_TOKEN" ] || [ -z "$OP_CONNECT_HOST" ]; then
echo "\$OP_CONNECT_TOKEN and \$OP_CONNECT_HOST must be set"
exit 1
fi
readonly CONNECT="CONNECT"
readonly SERVICE_ACCOUNT="SERVICE_ACCOUNT"
auth_type=$CONNECT
managed_variables_var="OP_MANAGED_VARIABLES"
IFS=',' read -r -a managed_variables <<< "$(printenv $managed_variables_var)"
IFS=','
# Unset all secrets managed by 1Password if `unset-previous` is set.
if [ "$INPUT_UNSET_PREVIOUS" == "true" ]; then
echo "Unsetting previous values..."
unset_prev_secrets() {
if [ "$INPUT_UNSET_PREVIOUS" == "true" ]; then
echo "Unsetting previous values..."
# Find environment variables that are managed by 1Password.
for env_var in "${managed_variables[@]}"; do
echo "Unsetting $env_var"
unset $env_var
# Find environment variables that are managed by 1Password.
for env_var in "${managed_variables[@]}"; do
echo "Unsetting $env_var"
unset $env_var
echo "$env_var=" >> $GITHUB_ENV
echo "$env_var=" >> $GITHUB_ENV
# Keep the masks, just in case.
done
# Keep the masks, just in case.
done
managed_variables=()
fi
curl_headers=(-H "Content-Type: application/json" -H "Authorization: Bearer $OP_CONNECT_TOKEN")
# Iterate over environment varables to find 1Password references, load the secret values,
# and make them available as environment variables in the next steps.
IFS=$'\n'
for possible_ref in $(printenv | grep "=op://" | grep -v "^#"); do
env_var=$(echo "$possible_ref" | cut -d '=' -f1)
ref=$(printenv $env_var)
if [[ ! $ref == "op://"* ]]; then
echo "Not really a reference: $ref"
continue
managed_variables=()
fi
}
path=$(echo $ref | sed -e "s/^op:\/\///")
if [ $(echo "$path" | tr -cd '/' | wc -c) -lt 2 ]; then
echo "Expected path to be in format op://<vault>/<item>[/<section>]/<field>: $ref"
continue
# Install op-cli
install_op_cli() {
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
curl -sSfLo op.zip "https://cache.agilebits.com/dist/1P/op2/pkg/v2.7.1-beta.01/op_linux_amd64_v2.7.1-beta.01.zip"
unzip -od /usr/local/bin/ op.zip && rm op.zip
elif [[ "$OSTYPE" == "darwin"* ]]; then
curl -sSfLo op.pkg "https://cache.agilebits.com/dist/1P/op2/pkg/v2.7.1-beta.01/op_apple_universal_v2.7.1-beta.01.pkg"
sudo installer -pkg op.pkg -target /usr/local/bin/ && rm op.pkg
fi
}
echo "Populating variable: $env_var"
populating_secret() {
ref=$(printenv $1)
vault=""
item=""
section=""
field=""
i=0
IFS="/"
for component in $path; do
((i+=1))
case "$i" in
1) vault=$component ;;
2) item=$component ;;
3) section=$component ;;
4) field=$component ;;
esac
done
unset IFS
# If field is not set, it may have wrongfully been interpreted as the section.
if [ -z "$field" ]; then
field="$section"
section=""
fi
if [[ $(echo -n $(echo $vault | grep "^[a-z0-9]*$") | wc -c) -ne 26 ]]; then
echo "Getting vault ID from vault name: $vault"
vault=$(curl -sSf "${curl_headers[@]}" "$OP_CONNECT_HOST/v1/vaults?filter=name%20eq%20%22$vault%22" | jq -r '.[0] | .id')
if [ -z "$vault" ]; then
echo "Could not find vault ID for vault: $vault"
exit 1
fi
fi
if [[ $(echo -n $(echo $item | grep "^[a-z0-9]*$") | wc -c) -ne 26 ]]; then
echo "Getting item ID from vault $vault..."
item=$(curl -sSf "${curl_headers[@]}" "$OP_CONNECT_HOST/v1/vaults/$vault/items?filter=title%20eq%20%22$item%22" | jq -r '.[0] | .id')
if [ -z "$item" ]; then
echo "Could not find item ID for item: $item"
exit 1
fi
fi
echo "Loading item $item from vault $vault..."
item_json=$(curl -sSf "${curl_headers[@]}" "$OP_CONNECT_HOST/v1/vaults/$vault/items/$item")
jq_field_selector=".id == \"$field\" or .label == \"$field\""
jq_section_selector=".section == null"
# If the reference contains a section, edit the jq selector to take that into account.
if [ -n "$section" ]; then
echo "Looking for section: $section"
section_id=$(echo "$item_json" | jq -r ".sections[] | select(.id == \"$section\" or .label == \"$section\") | .id")
jq_section_selector=".section.id == \"$section_id\""
fi
jq_secret_selector="$jq_section_selector and ($jq_field_selector)"
echo "Looking for field: $field"
secret_field_json=$(echo "$item_json" | jq -r "first(.fields[] | select($jq_secret_selector))")
field_type=$(echo "$secret_field_json" | jq -r '.type')
field_purpose=$(echo "$secret_field_json" | jq -r '.purpose')
secret_value=$(echo "$secret_field_json" | jq -r '.value')
echo "Populating variable: $1"
secret_value=$(op read $ref)
if [ -z "$secret_value" ]; then
echo "Could not find or access secret $ref"
exit 1
fi
# If the field is marked as concealed or is a note, register a mask
# for the secret to prevent accidental log exposure.
if [ "$field_type" == "CONCEALED" ] || [ "$field_purpose" == "NOTES" ]; then
# To support multiline secrets, escape percent signs and add a mask per line.
escaped_mask_value=$(echo "$secret_value" | sed -e 's/%/%25/g')
IFS=$'\n'
for line in $escaped_mask_value; do
if [ "${#line}" -lt 3 ]; then
# To avoid false positives and unreadable logs, omit mask for lines that are too short.
continue
fi
echo "::add-mask::$line"
done
unset IFS
# Register a mask for the secret to prevent accidental log exposure.
# To support multiline secrets, escape percent signs and add a mask per line.
escaped_mask_value=$(echo "$secret_value" | sed -e 's/%/%25/g')
IFS=$'\n'
for line in $escaped_mask_value; do
if [ "${#line}" -lt 3 ]; then
# To avoid false positives and unreadable logs, omit mask for lines that are too short.
continue
fi
echo "::add-mask::$line"
done
unset IFS
if [ "$INPUT_EXPORT_ENV" == "true" ]; then
# To support multiline secrets, we'll use the heredoc syntax to populate the environment variables.
# As the heredoc identifier, we'll use a randomly generated 64-character string,
# so that collisions are practically impossible.
random_heredoc_identifier=$(openssl rand -hex 16)
{
# Populate env var, using heredoc syntax with generated identifier
echo "$env_var<<${random_heredoc_identifier}"
echo "$secret_value"
echo "${random_heredoc_identifier}"
} >> $GITHUB_ENV
echo "GITHUB_ENV: $(cat $GITHUB_ENV)"
else
# Prepare the secret_value to be outputed properly (especially multiline secrets)
secret_value=$(echo "$secret_value" | awk -v ORS='%0A' '1')
echo "::set-output name=$env_var::$secret_value"
fi
# To support multiline secrets, we'll use the heredoc syntax to populate the environment variables.
# As the heredoc identifier, we'll use a randomly generated 64-character string,
# so that collisions are practically impossible.
random_heredoc_identifier=$(openssl rand -hex 16)
{
# Populate env var, using heredoc syntax with generated identifier
echo "$env_var<<${random_heredoc_identifier}"
echo "$secret_value"
echo "${random_heredoc_identifier}"
} >> $GITHUB_ENV
managed_variables+=("$env_var")
done
unset IFS
}
# Load environment variables using op cli. Iterate over them to find 1Password references, load the secret values,
# and make them available as environment variables in the next steps.
extract_secrets() {
IFS=$'\n'
for env_var in $(op env ls); do
populating_secret $env_var
done
}
read -r -a managed_variables <<< "$(printenv $managed_variables_var)"
if [ -z "$OP_CONNECT_TOKEN" ] || [ -z "$OP_CONNECT_HOST" ]; then
if [ -z "$OP_SERVICE_ACCOUNT_TOKEN" ]; then
echo "(\$OP_CONNECT_TOKEN and \$OP_CONNECT_HOST) or \$OP_SERVICE_ACCOUNT_TOKEN must be set"
exit 1
fi
auth_type=$SERVICE_ACCOUNT
fi
printf "Authenticated with %s \n" $auth_type
unset_prev_secrets
install_op_cli
extract_secrets
unset IFS
# Add extra env var that lists which secrets are managed by 1Password so that in a later step
# these can be unset again.
managed_variables_str=$(IFS=','; echo "${managed_variables[*]}")

351
package-lock.json generated Normal file
View File

@@ -0,0 +1,351 @@
{
"name": "load-secrets-action",
"version": "1.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "load-secrets-action",
"version": "1.1.0",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.5.0",
"@actions/exec": "^1.1.0"
},
"devDependencies": {
"@vercel/ncc": "^0.30.0",
"typescript": "^4.4.2"
}
},
"node_modules/@actions/core": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.5.0.tgz",
"integrity": "sha512-eDOLH1Nq9zh+PJlYLqEMkS/jLQxhksPNmUGNBHfa4G+tQmnIhzpctxmchETtVGyBOvXgOVVpYuE40+eS4cUnwQ=="
},
"node_modules/@actions/exec": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.0.tgz",
"integrity": "sha512-LImpN9AY0J1R1mEYJjVJfSZWU4zYOlEcwSTgPve1rFQqK5AwrEs6uWW5Rv70gbDIQIAUwI86z6B+9mPK4w9Sbg==",
"dependencies": {
"@actions/io": "^1.0.1"
}
},
"node_modules/@actions/io": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.1.tgz",
"integrity": "sha512-Qi4JoKXjmE0O67wAOH6y0n26QXhMKMFo7GD/4IXNVcrtLjUlGjGuVys6pQgwF3ArfGTQu0XpqaNr0YhED2RaRA=="
},
"node_modules/@cspotcode/source-map-consumer": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
"integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==",
"dev": true,
"engines": {
"node": ">= 12"
}
},
"node_modules/@cspotcode/source-map-support": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.6.1.tgz",
"integrity": "sha512-DX3Z+T5dt1ockmPdobJS/FAsQPW4V4SrWEhD2iYQT2Cb2tQsiMnYxrcUH9By/Z3B+v0S5LMBkQtV/XOBbpLEOg==",
"dev": true,
"dependencies": {
"@cspotcode/source-map-consumer": "0.8.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@tsconfig/node10": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz",
"integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==",
"dev": true
},
"node_modules/@tsconfig/node12": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz",
"integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==",
"dev": true
},
"node_modules/@tsconfig/node14": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz",
"integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==",
"dev": true
},
"node_modules/@tsconfig/node16": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz",
"integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==",
"dev": true
},
"node_modules/@types/node": {
"version": "16.7.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.10.tgz",
"integrity": "sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA==",
"dev": true
},
"node_modules/@vercel/ncc": {
"version": "0.30.0",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.30.0.tgz",
"integrity": "sha512-16ePj2GkwjomvE0HLL5ny+d+sudOwvZNYW8vjpMh3cyWdFxoMI8KSQiolVxeHBULbU1C5mVxLK5nL9NtnnpIew==",
"dev": true,
"bin": {
"ncc": "dist/ncc/cli.js"
}
},
"node_modules/acorn": {
"version": "8.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz",
"integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/acorn-walk": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.1.1.tgz",
"integrity": "sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w==",
"dev": true,
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
},
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true,
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"node_modules/ts-node": {
"version": "10.2.1",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.2.1.tgz",
"integrity": "sha512-hCnyOyuGmD5wHleOQX6NIjJtYVIO8bPP8F2acWkB4W06wdlkgyvJtubO/I9NkI88hCFECbsEgoLc0VNkYmcSfw==",
"dev": true,
"dependencies": {
"@cspotcode/source-map-support": "0.6.1",
"@tsconfig/node10": "^1.0.7",
"@tsconfig/node12": "^1.0.7",
"@tsconfig/node14": "^1.0.0",
"@tsconfig/node16": "^1.0.2",
"acorn": "^8.4.1",
"acorn-walk": "^8.1.1",
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"yn": "3.1.1"
},
"bin": {
"ts-node": "dist/bin.js",
"ts-node-cwd": "dist/bin-cwd.js",
"ts-node-script": "dist/bin-script.js",
"ts-node-transpile-only": "dist/bin-transpile.js",
"ts-script": "dist/bin-script-deprecated.js"
},
"engines": {
"node": ">=12.0.0"
},
"peerDependencies": {
"@swc/core": ">=1.2.50",
"@swc/wasm": ">=1.2.50",
"@types/node": "*",
"typescript": ">=2.7"
},
"peerDependenciesMeta": {
"@swc/core": {
"optional": true
},
"@swc/wasm": {
"optional": true
}
}
},
"node_modules/typescript": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz",
"integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=4.2.0"
}
},
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true,
"engines": {
"node": ">=6"
}
}
},
"dependencies": {
"@actions/core": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.5.0.tgz",
"integrity": "sha512-eDOLH1Nq9zh+PJlYLqEMkS/jLQxhksPNmUGNBHfa4G+tQmnIhzpctxmchETtVGyBOvXgOVVpYuE40+eS4cUnwQ=="
},
"@actions/exec": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.0.tgz",
"integrity": "sha512-LImpN9AY0J1R1mEYJjVJfSZWU4zYOlEcwSTgPve1rFQqK5AwrEs6uWW5Rv70gbDIQIAUwI86z6B+9mPK4w9Sbg==",
"requires": {
"@actions/io": "^1.0.1"
}
},
"@actions/io": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.1.tgz",
"integrity": "sha512-Qi4JoKXjmE0O67wAOH6y0n26QXhMKMFo7GD/4IXNVcrtLjUlGjGuVys6pQgwF3ArfGTQu0XpqaNr0YhED2RaRA=="
},
"@cspotcode/source-map-consumer": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
"integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==",
"dev": true
},
"@cspotcode/source-map-support": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.6.1.tgz",
"integrity": "sha512-DX3Z+T5dt1ockmPdobJS/FAsQPW4V4SrWEhD2iYQT2Cb2tQsiMnYxrcUH9By/Z3B+v0S5LMBkQtV/XOBbpLEOg==",
"dev": true,
"requires": {
"@cspotcode/source-map-consumer": "0.8.0"
}
},
"@tsconfig/node10": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz",
"integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==",
"dev": true
},
"@tsconfig/node12": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz",
"integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==",
"dev": true
},
"@tsconfig/node14": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz",
"integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==",
"dev": true
},
"@tsconfig/node16": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz",
"integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==",
"dev": true
},
"@types/node": {
"version": "16.7.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.10.tgz",
"integrity": "sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA==",
"dev": true
},
"@vercel/ncc": {
"version": "0.30.0",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.30.0.tgz",
"integrity": "sha512-16ePj2GkwjomvE0HLL5ny+d+sudOwvZNYW8vjpMh3cyWdFxoMI8KSQiolVxeHBULbU1C5mVxLK5nL9NtnnpIew==",
"dev": true
},
"acorn": {
"version": "8.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz",
"integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==",
"dev": true
},
"acorn-walk": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.1.1.tgz",
"integrity": "sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w==",
"dev": true
},
"arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
},
"create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
"diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true
},
"make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"ts-node": {
"version": "https://registry.npmjs.org/ts-node/-/ts-node-10.2.1.tgz",
"integrity": "sha512-hCnyOyuGmD5wHleOQX6NIjJtYVIO8bPP8F2acWkB4W06wdlkgyvJtubO/I9NkI88hCFECbsEgoLc0VNkYmcSfw==",
"dev": true,
"requires": {
"@cspotcode/source-map-support": "0.6.1",
"@tsconfig/node10": "^1.0.7",
"@tsconfig/node12": "^1.0.7",
"@tsconfig/node14": "^1.0.0",
"@tsconfig/node16": "^1.0.2",
"acorn": "^8.4.1",
"acorn-walk": "^8.1.1",
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"yn": "3.1.1"
}
},
"typescript": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz",
"integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==",
"dev": true
},
"yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true
}
}
}

37
package.json Normal file
View File

@@ -0,0 +1,37 @@
{
"name": "load-secrets-action",
"version": "1.1.0",
"description": "Load Secrets from 1Password",
"main": "dist/index.js",
"directories": {
"test": "tests"
},
"scripts": {
"build": "ncc build src/index.ts"
},
"repository": {
"type": "git",
"url": "git+https://github.com/1Password/load-secrets-action.git"
},
"keywords": [
"actions",
"1password",
"load secrets",
"connect"
],
"author": "1Password",
"license": "MIT",
"bugs": {
"url": "https://github.com/1Password/load-secrets-action/issues"
},
"homepage": "https://github.com/1Password/load-secrets-action#readme",
"dependencies": {
"@actions/core": "^1.5.0",
"@actions/exec": "^1.1.0"
},
"devDependencies": {
"@types/node": "^16.7.10",
"@vercel/ncc": "^0.30.0",
"typescript": "^4.4.2"
}
}

21
src/index.ts Normal file
View File

@@ -0,0 +1,21 @@
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import path from 'path';
async function run(): Promise<void> {
try {
const parentDir = path.resolve(__dirname, '..');
// Get action inputs
process.env.INPUT_UNSET_PREVIOUS = core.getInput('unset-previous');
process.env.INPUT_EXPORT_ENV = core.getInput('export-env');
// Execute bash script
await exec.exec(`sh -c "` + parentDir + `/entrypoint.sh"`);
} catch (error: any) {
core.setFailed(error.message);
}
}
run();

13
tsconfig.json Normal file
View File

@@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"noImplicitAny": true,
"esModuleInterop": true
},
"exclude": ["node_modules"]
}