Upgrading

Contents

This page covers what changes between major versions and what to do about it. The full record, including every non-breaking change, is in CHANGELOG.md.

Secret Config follows Semantic Versioning. Breaking changes are confined to major releases: within a minor or patch release the meaning of a key, the return type of a call, the default value of an option, and the supported Ruby version all stay put.

Upgrading to v2

v2 is where the accumulated breaking changes land. None of them require a change to how settings are stored, so the store itself does not need to be migrated. The work is in application code.

Ruby 3.2 is the minimum

The gemspec previously declared Ruby 2.3, but CI has only ever tested 3.2 and later. This makes the supported version match what is actually tested.

key? now consults environment variables

key? read the in-memory cache directly, which meant it disagreed with [] and fetch, both of which have always honored an environment variable override. It now returns true for a key that is supplied only by an environment variable, whenever SecretConfig.check_env_var? is true.

export MYSQL_REPLICA_HOST=replica.example.net
SecretConfig.key?("mysql/replica_host")
# v1: false
# v2: true

What to do: code that used key? to ask specifically whether the central store holds a key gets a different answer now. Set SecretConfig.check_env_var = false to restore the old meaning.

Most uses are unaffected, because most are asking “is a value available”, which is what it now answers.

Env-var-only keys are no longer cached

Reading a key that exists only as an environment variable used to write it into the in-memory copy. That had two consequences: key? changed its answer partway through a process, and the key leaked into configuration output once anything had read it.

The memoization is gone. Two things follow:

Overrides of keys that are in the store are still applied at load time, so those still need a refresh! to pick up a change. That has not changed.

What to do: usually nothing. Code that relied on reading an env-var-only key to make it show up in configuration needs another approach.

fetch calls a block even without a default:

The missing-key check ran before the block was considered, so a block on its own raised MissingMandatoryKey and was only ever reached when a default: was also supplied, which it then took precedence over. The block is now called whenever the key is missing:

SecretConfig.fetch("mysql/port") { 3306 }
# v1: raises MissingMandatoryKey
# v2: 3306

What to do: code that relies on fetch(key) { ... } raising must drop the block to keep raising. This is worth grepping for, since v1 code would only have written a bare block by mistake.

$(random) is renamed to __generate__

A single character separated $(random) from the ${random} interpolation, and the two behave very differently: $(random) is materialized once during a CLI import and persisted, whereas ${random} is re-evaluated on every startup and refresh. Confusing them produces an application whose password changes on every restart.

# Before
mysql:
  password: $(random)

# After
mysql:
  password: __generate__

$(random) still works in v2, but prints a deprecation warning on stderr and will be removed in the next major release. It does not accept a per-key size.

--random_size is deprecated

It set one size for every generated value in an import, so two keys needing different sizes meant two separate imports. Supply the size on the value instead:

mysql:
  password: __generate__        # 32 bytes
  api_key:  __generate__:64     # 64 bytes

The flag still works, and still sets the default for a bare __generate__, but warns when supplied.

Silencing the deprecation warnings

While migrating, set SECRET_CONFIG_SILENCE_DEPRECATIONS to any value to suppress both warnings:

export SECRET_CONFIG_SILENCE_DEPRECATIONS=1

New in v2

Not breaking, but worth adopting:

Upgrading to v1.0

No breaking changes. v1.0.0 fixed the handling of a nil default on fetch.

Upgrading to v0.10

${...} replaces %{...}

String interpolation changed from % to $. Change every interpolated value before upgrading, since the old form is not recognized afterwards:

# Before
logger:
  file_name: /var/log/my_application_%{date}.log

# After
logger:
  file_name: /var/log/my_application_${date}.log

An export, a search and replace, and an import is the quickest way through it for a store of any size. See Command Line.

Upgrading to v0.9

The command line program was renamed

secret_config became secret-config, with an underscore changed to a hyphen, and its arguments were reworked to be consistent across operations. Any script or runbook calling the old name needs updating, and the arguments should be checked rather than assumed:

secret-config --help

Next steps