Skip to content

Move Tideways API key from global config to per-project config#82

Merged
peterjaap merged 2 commits into
mainfrom
fix/tideways-api-key-per-project
Apr 10, 2026
Merged

Move Tideways API key from global config to per-project config#82
peterjaap merged 2 commits into
mainfrom
fix/tideways-api-key-per-project

Conversation

@peterjaap
Copy link
Copy Markdown
Collaborator

@peterjaap peterjaap commented Apr 10, 2026

Summary

The Tideways API key is per Tideways project, so it cannot live in ~/.magebox/config.yaml — a developer with two Magento projects belonging to two Tideways projects needs two different keys. The previous implementation (merged as #77, released in v1.14.1) wrote a single machine-wide tideways.api_key to /etc/php/8.x/mods-available/tideways.ini, which either silently pinned all local projects to the same Tideways project or got shadowed by whatever project was most-recently-configured.

MageBox already has the right primitive: the .magebox.yaml php_ini map is rendered into each project's FPM pool config as php_admin_value (see internal/php/templates/pool.conf.tmpl:53-56), so per-project overrides of any PHP ini directive are a one-line YAML edit:

```yaml
php_ini:
tideways.api_key: your-project-specific-key
```

That's the right home for the API key — no new schema, no new command, it just works. This PR stops writing the key globally and surfaces the per-project location everywhere a user would look.

Changes

  • Global config schema: api_key is no longer prompted, stored, or written. Kept as a // Deprecated: field on `TidewaysCredentials` purely so legacy configs still unmarshal and can be detected via `HasLegacyTidewaysAPIKey()` for migration. `HasTidewaysCredentials` and `TIDEWAYS_API_KEY` env var handling removed.
  • Extension ini writes: `WriteAPIKeyToExtension` and `rewriteIniDirective` deleted from `internal/tideways/manager.go`. New `CleanLegacyExtensionDirectives` strips any stale `tideways.api_key` / `tideways.environment` lines that v1.14.1 wrote there. Nothing is written back except the cleaned file.
  • `tideways.Credentials` struct: `APIKey` removed. Also removed unused `Configured` bool + `IsFullyConfigured` method from `tideways.Status` (dead code once the `Configured` signal was based on the removed field).
  • `magebox tideways config`: now purely global — prompts for access token and daemon environment. On every run, calls `CleanLegacyExtensionDirectives` across all installed PHP versions. If a legacy `profiling.tideways.api_key` is found in `~/.magebox/config.yaml`, prints a migration warning and removes it on save. Reloads PHP-FPM only if the ini actually changed.
  • `magebox tideways status`: reads the project's `.magebox.yaml` via `config.LoadFromPath(cwd)` and reports whether `php_ini.tideways.api_key` is set for this project, with a YAML snippet in the warning when it isn't. Also surfaces the legacy-key warning when applicable.
  • Prompts and help text: the `tideways config --help` long description and interactive prompt explain the per-project vs global split up front and link to `https://app.tideways.io/o///installation`.

Tests

  • `internal/config/global_test.go`: drop `TIDEWAYS_API_KEY` env var cases from `TestGlobalConfig_TidewaysCredentials`, assert `GetTidewaysCredentials` never surfaces `APIKey`. New `TestGlobalConfig_HasLegacyTidewaysAPIKey` and `TestGlobalConfig_TidewaysLegacyAPIKeyStillUnmarshals` — the second writes a v1.14.1-shaped `config.yaml` to a tempdir, loads it, and verifies the migration path can detect the stale field.
  • `internal/tideways/manager_test.go`: replace the `rewriteIniDirective` suite (dead code) with an expanded `stripIniDirective` suite covering both directives, commented/uncommented, whitespace-prefixed comments, multiple occurrences, and empty files. Added `TestStripIniDirective_ComposedCleanup` exercising the two-step strip flow that `CleanLegacyExtensionDirectives` performs. Kept `TestRenderDaemonEnvironmentDropIn`.

All existing tests pass; lint clean.

Test plan

  • `make build` succeeds
  • `make lint` — 0 issues
  • `make test` — all packages pass
  • `./build/magebox tideways config --help` reflects the global-only framing
  • Fresh install: run `magebox tideways config` with an access token + environment, verify no `tideways.api_key` is written to `/etc/php/8.x/mods-available/tideways.ini`
  • Upgrade path: with a legacy `profiling.tideways.api_key` still in `~/.magebox/config.yaml` and a stale `tideways.api_key=` line in the extension ini, run `magebox tideways config` and verify: (a) the migration warning prints, (b) the global field is removed on save, (c) the extension ini is stripped, (d) PHP-FPM is reloaded
  • Add `php_ini.tideways.api_key` to a project's `.magebox.local.yaml`, run `magebox restart`, trigger a trace, verify it lands in the correct Tideways project under the `local_` environment
  • Run `magebox tideways status` inside and outside a project — the per-project key line should reflect the current project's `php_ini`

The Tideways API key is per *Tideways project*, so it cannot live in
~/.magebox/config.yaml — a developer with two Magento projects belonging
to two Tideways projects needs two different keys. The previous
implementation wrote a single machine-wide api_key to
/etc/php/8.x/mods-available/tideways.ini, which either silently pinned
all local projects to the same Tideways project or got shadowed by
whatever project was most-recently-configured.

MageBox already has the right primitive: the .magebox.yaml `php_ini`
map is rendered into each project's FPM pool config as `php_admin_value`
(see internal/php/templates/pool.conf.tmpl:53-56), so per-project
overrides of any PHP ini directive are a one-line yaml edit. The fix
is to stop writing api_key globally and tell users to set it there.

Changes:

- Drop `api_key` from the global config schema. The `APIKey` field on
  TidewaysCredentials is kept (marked Deprecated) purely so legacy
  configs still unmarshal and can be detected via
  HasLegacyTidewaysAPIKey() for a migration warning.
- Drop `HasTidewaysCredentials` and `TIDEWAYS_API_KEY` env var
  handling. Access token and environment remain as global settings.
- Remove WriteAPIKeyToExtension and rewriteIniDirective from the
  tideways manager — no more writes to the global extension ini. In
  their place, add CleanLegacyExtensionDirectives which strips any
  `tideways.api_key` / `tideways.environment` lines that older
  MageBox versions wrote there. Nothing is written back except the
  cleaned file.
- Remove APIKey from tideways.Credentials and the unused Configured
  bool + IsFullyConfigured method from tideways.Status.
- `magebox tideways config` is now global-only: prompts for access
  token and environment, calls CleanLegacyExtensionDirectives for
  every installed PHP version, writes the systemd drop-in for the
  daemon environment, imports the CLI token. If a legacy api_key is
  found in ~/.magebox/config.yaml, it prints a migration warning and
  removes it on save. Reloads PHP-FPM only when the ini was actually
  modified.
- `magebox tideways status` now reads the project's .magebox.yaml
  (via config.LoadFromPath) and reports whether php_ini.tideways.api_key
  is set for *this* project, with a yaml snippet in the warning when
  it isn't. Also surfaces the legacy-api-key warning.

Tests:

- global_test.go: drop TIDEWAYS_API_KEY env var cases, add
  TestGlobalConfig_HasLegacyTidewaysAPIKey, add
  TestGlobalConfig_TidewaysLegacyAPIKeyStillUnmarshals to verify old
  configs still round-trip so migration can detect them. Assert that
  GetTidewaysCredentials never surfaces APIKey.
- manager_test.go: replace rewriteIniDirective cases with an expanded
  stripIniDirective suite (both directives, commented/uncommented,
  whitespace prefix, multiple occurrences) plus a composed-cleanup
  case that exercises the two-step strip flow in
  CleanLegacyExtensionDirectives. Keep the systemd drop-in test.
When 'magebox tideways config' is run from inside a project that has no
tideways.api_key set in its merged php_ini map, prompt for the key and
write it to .magebox.local.yaml under php_ini.tideways.api_key.

.magebox.local.yaml is the right home: it is the personal override file
and typically gitignored, so the api_key (which is a secret) stays out
of the shared repo. Users who want to share the key with their team can
move it to .magebox.yaml manually afterward.

- New --project-api-key flag for non-interactive use (only applied when
  MageBox is actually inside a project).
- Interactive flow: if cwd is a project without the key already set,
  print the project name and ask for the key after the Environment
  prompt. Leaving it blank is a no-op — the command still prints a
  reminder with a yaml snippet.
- writeProjectTidewaysAPIKey uses LoadLocalConfig / SaveLocalConfig so
  existing php_ini entries (memory_limit, xdebug.mode, etc.) and the
  env section are preserved. Allocates the PHPINI map first if nil.
- After writing, print a reminder to run 'magebox restart' so the FPM
  pool picks up the new php_admin_value.
- Updated the config command's Long description to document both the
  global and project scopes, and dropped the now-stale final hint
  (\"Set the API key per project ...\") when we're actually inside a
  project — it's redundant with the prompt.

Tests: three cases covering creating a new .magebox.local.yaml, merging
into an existing one without clobbering other php_ini/env entries, and
handling an existing file with no php_ini section (nil map).
@peterjaap peterjaap merged commit 10f8d35 into main Apr 10, 2026
11 checks passed
@peterjaap peterjaap deleted the fix/tideways-api-key-per-project branch April 10, 2026 12:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant