Skip to content

[Feature Request] Optional items whose resolver cannot authenticate resolve to undefined, and lazy plugin functions in untaken branches #1147

Description

@timche

Description

Let an @optional item whose resolver cannot run come out as undefined (with a warning) instead of failing the whole load, as an opt-in. And let a plugin function that is not loaded sit in a branch that never runs.

Motivation

In a public repository, contributors and CI jobs have no access to the maintainers' 1Password, but the maintainers want signing credentials to come from it. Two things stand in the way, both reproduced on 1.21.0:

  1. An @optional item whose value is op() fails the load when there is no token and no app:
# @plugin(@varlock/1password-plugin)
# @initOp(token=$OP_TOKEN, allowAppAuth=false, useCliWithServiceAccount=true)
# @defaultSensitive=false
# ---
# @type=opServiceAccountToken @internal @optional
OP_TOKEN=
# @optional @sensitive
SIGNING_PASSWORD=op("op://Vault/Item/password")
⛔ SIGNING_PASSWORD  🔐sensitive
   └ undefined
   - error resolving value: SchemaError: op(): Unable to authenticate with 1Password
  1. Gating it with if() does not help when the plugin is only imported where it can authenticate:
# @type=boolean
SIGN=false
# @optional @sensitive
SIGNING_PASSWORD=if($SIGN, op("op://Vault/Item/password"))
   - Unknown resolver function: op()

The workaround is to put every op() reference in separate files, imported only when a flag is set (enabled=...), and to make every script set the right flag. It works, but it's a file per use case and a flag per script, just to stop lookups from running where they can't.

Proposed Solution

  • Opt-in per item or per plugin instance, e.g. @optional={onResolveError=undefined} or @initOp(..., optionalOnAuthFailure=true): an optional item whose resolver fails for a missing credential resolves to undefined and prints a warning. Required items still fail as today, so @required=forEnv(production) (or a flag) keeps releases strict.
  • Resolve function names lazily, so a plugin function in an if() branch that is not taken does not error when the plugin is not loaded.

Alternatives

  • Separate files per use case, imported behind flags (what we do now).
  • --filter per script to scope resolution, which moves the same bookkeeping into every script.

Additional Information

Typical case: code-signing credentials for an open-source app, where builds without credentials are expected to produce unsigned output.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions