Skip to content

Add support for integration test with juju secrets#786

Merged
cbartz merged 21 commits intomainfrom
feat/juju-secret-config
Apr 21, 2026
Merged

Add support for integration test with juju secrets#786
cbartz merged 21 commits intomainfrom
feat/juju-secret-config

Conversation

@yhaliaw
Copy link
Copy Markdown
Collaborator

@yhaliaw yhaliaw commented Apr 17, 2026

Applicable spec:

Overview

This pull request introduces new configuration options to allow sensitive credentials (the GitHub token and OpenStack clouds.yaml) to be supplied securely via Juju secrets, rather than plaintext config. When these secret-based options are set, they take precedence over the previous plaintext options, which remain for compatibility. The implementation ensures that credential changes are handled securely and trigger proper runner flushes, and includes corresponding updates to documentation and tests.

Secret-based credential support:

  • Added token-secret-id and openstack-clouds-yaml-secret-id config options, allowing the GitHub token and OpenStack clouds.yaml to be provided via Juju secrets. These take precedence over the plaintext token and openstack-clouds-yaml options, which are now considered compatibility fallbacks. (charmcraft.yaml, docs/changelog.md, [1] [2] [3]
  • Updated validation logic in GithubConfig.from_charm and OpenStack config parsing to retrieve and validate secrets, raising clear errors if secrets are missing or malformed. (src/charm_state.py, [1] [2] [3] [4]

Runner lifecycle and config change handling:

  • Include the new secret-based options, ensuring that credential rotations via secrets are detected and handled securely. (src/charm.py, [1] [2] [3] [4]

Testing and integration:

  • Updated test helpers and integration fixtures to support the new secret-based configuration options, and removed direct usage of plaintext config. (tests/integration/conftest.py, tests/integration/helpers/common.py, [1] [2] [3] [4]

Documentation:

  • Added a changelog entry describing the new secret-based configuration options and their precedence over legacy plaintext options. (docs/changelog.md, docs/changelog.mdR5-R8)

Rationale

Prevent leaking secrets in the integration test in the workflow.

Juju Events Changes

Module Changes

Library Changes

Checklist

  • The charm style guide was applied.
  • The contributing guide was applied.
  • The changes are compliant with ISD054 - Managing Charm Complexity
  • The documentation for charmhub is updated.
  • The PR is tagged with appropriate label (urgent, trivial, complex).
  • The changelog is updated with changes that affects the users of the charm.
  • The application version number is updated in github-runner-manager/pyproject.toml.

yhaliaw and others added 5 commits April 17, 2026 13:10
Jubilant's Juju.deploy() does not accept a log argument; passing it
raised TypeError during integration test fixture setup.
Add an entry for the new token-secret-id and
openstack-clouds-yaml-secret-id options and note that the plaintext
token and openstack-clouds-yaml options remain as compatibility
fallbacks.
…et-id options

The latest/edge charm predates the token-secret-id and
openstack-clouds-yaml-secret-id config options, so the upgrade test
cannot deploy the legacy revision with the new fixtures. Re-enable once
a release containing these options has been promoted to latest/edge.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Juju secret-backed configuration options so integration tests (and charm users) can supply the GitHub token and OpenStack clouds.yaml via Juju user secrets rather than plaintext config.

Changes:

  • Added token-secret-id and openstack-clouds-yaml-secret-id config options (with secret content key parsing and precedence over plaintext).
  • Updated unit tests and integration deploy helper to create/grant secrets and use the new config options.
  • Updated charm stored config-change detection and documented the user-facing change in the changelog.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/charm_state.py Adds secret-ID config constants and resolves token/OpenStack YAML from Juju secrets with precedence and validation.
src/charm.py Tracks new secret-id config values in StoredState and triggers runner flush when they change.
charmcraft.yaml Exposes the new config options and clarifies plaintext options as compatibility fallbacks.
docs/changelog.md Documents the new secret-backed configuration options and precedence behavior.
tests/unit/test_charm_state.py Adds unit tests for secret-based token and OpenStack clouds parsing, including precedence and missing-field errors.
tests/unit/test_charm.py Extends config-changed flush/no-flush parameterization to include the new secret-id options.
tests/integration/helpers/common.py Updates integration deployment helper to create/grant secrets for token and OpenStack clouds and clear plaintext config by default.
tests/integration/conftest.py Removes log=False from a deploy call used in integration fixtures.
tests/integration/test_charm_upgrade.py Skips the upgrade test until latest/edge includes the newly added config options.

Comment thread src/charm_state.py
Comment thread src/charm_state.py Outdated
Comment thread tests/integration/helpers/common.py
Comment thread charmcraft.yaml Outdated
cbartz and others added 2 commits April 17, 2026 17:53
The error raised when neither a GitHub token nor App auth is configured
only referenced the plaintext `token` option, which is misleading now
that `token-secret-id` is a valid alternative source of the token.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Comment thread tests/integration/test_charm_upgrade.py
Comment thread src/charm_state.py Outdated
Comment thread tests/integration/helpers/common.py
cbartz added 4 commits April 17, 2026 19:04
…t skip

Jubilant logs the config passed to deploy, so reverting to the plaintext
token/openstack-clouds-yaml options to cover the upgrade path would leak
the GitHub token into test logs. Record this in the skip reason.
When the clouds.yaml comes from a Juju secret, a YAML parse or
validation failure now blames `openstack-clouds-yaml-secret-id` instead
of the plaintext config option, so operators look at the right place.
The per-option branching in _on_config_changed tripped the C901
complexity threshold after new secret-id options were added. Replace
the repeated if-blocks with a table-driven loop over (config_key,
stored_attr) pairs and apply black/isort fixes.
Mirror the token path: let deploy_github_runner_charm own the clouds
secret creation through a dedicated `openstack_clouds_yaml` parameter
instead of sniffing the plaintext value out of the caller's config dict
and then clearing it. Removes the clear/update/clear dance and the
lingering plaintext in the deploy config mapping.
The secret-id config constant holds a config option name, not a secret.
Add the same `# nosec` marker used for the other `*-secret-id` and
token constants so bandit stops flagging it as a hardcoded password.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Comment thread src/charm.py
Comment thread src/charm_state.py
Comment thread src/charm_state.py
Comment thread src/charm_state.py
cbartz and others added 5 commits April 17, 2026 22:03
- Flush runners on plaintext openstack-clouds-yaml changes so the
  behavior matches the existing token/secret-id paths; operators get
  the same reconcile regardless of which config option they use.
- When the YAML parsed from the Juju secret is invalid, name the secret
  in the error instead of pointing operators at the plaintext option.
- Cover the SecretNotFoundError branches for both token-secret-id and
  openstack-clouds-yaml-secret-id with unit tests.
Tracking the plaintext option for auto-flush would persist the OpenStack
credentials to .unit-state.db on disk, which contradicts the direction
of this PR (moving secrets into Juju secrets). Operators who want
automatic flush on credential rotation should use
openstack-clouds-yaml-secret-id.
yaml.YAMLError and pydantic TypeError messages embed a snippet of the
offending input. When the source is a Juju secret, that snippet is
decrypted secret content that must not land in juju debug-log. Drop
`%s exc` from the log call and use `raise ... from None` so the
chained cause isn't printed by `logger.exception` in catch_charm_errors.

The plaintext branch has the same leak shape but is pre-existing
behavior; not changing it here.
@yhaliaw yhaliaw marked this pull request as ready for review April 20, 2026 05:03
@cbartz cbartz enabled auto-merge (squash) April 20, 2026 07:44
yhaliaw and others added 3 commits April 20, 2026 16:14
Fork creation currently fails because the fine-grained PAT is scoped to
the canonical org while the fork lands in a personal namespace. To be
revisited once integration tests migrate to GitHub App auth.
@cbartz cbartz merged commit fdfe2a5 into main Apr 21, 2026
115 of 135 checks passed
@cbartz cbartz deleted the feat/juju-secret-config branch April 21, 2026 10:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants