Repository navigation
fix(legacy): clarify why certain functions are not available on fixed plans - #50
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the legacy resources:build:get command’s error output when the Flexible Resources (Sizing) API is unavailable, aiming to clarify that the attempted functionality isn’t available on fixed plans and to point users to Fixed documentation.
Changes:
- Expanded the “flexible resources API is not enabled” error into a multi-line message.
- Added wording indicating the command is not available on fixed plans and included a Fixed docs URL.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ions The "flexible resources API is not enabled" error is shared by all the resources:* commands, so move it to ResourcesUtil and use it everywhere instead of only in resources:build:get. A disabled sizing API does not by itself mean the project is on Upsun Fixed, so the Fixed note is now only shown when the project's organization has the "fixed" type. If the organization cannot be loaded (e.g. the user has no access to it), the note is skipped. The docs link uses the docs.upsun.com/anchors/fixed/ redirect, like other Fixed links in the CLI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1237c90 to
a1adb08
Compare
There was a problem hiding this comment.
Note
Reviewed — No blocking findings · 🔵 3 minor points · ⚪ 1 nitpick
🔍 Full review · 7 files reviewed
🔵 Minor points
legacy/src/Service/ResourcesUtil.php:58—$project->getProperty('organization', false)sits outside the try/catch and uses the client's default lazyLoad=true, so when the Project object in hand has noorganizationkey (e.g. a project resource reconstructed without that property) the getter calls ensureFull(), issuing an HTTP GET whose failure (network error, 403) escapes as an uncaught exception — the user gets a stack trace instead of the "The flexible resources API is not enabled" message the command was about to print. The rest of the codebase avoids this by passing the third argument: Api.php:1444 usesgetProperty('organization', false, false). Moving the call inside the try (and/or disabling lazy loading) keeps the error path non-fatal.legacy/src/Service/ResourcesUtil.php:49— The note hardcodes the brand string "Upsun Fixed" and the URLhttps://docs.upsun.com/anchors/fixed/, while every other product name and documentation link in the legacy CLI comes from config (service.name,service.docs_url,service.resources_help_url, e.g. legacy/config.yaml:72). A vendorized build (make vendor-snapshot, which supplies its own embedded config) therefore prints Upsun branding and an upsun.com link to users of a differently branded CLI.legacy/src/Service/ResourcesUtil.php:63—isFixedProject()callsApi::getOrganizationById()without checkingapi.organizations, unlike every other organization call site in the legacy CLI (Selector.php:1038, Api.php:1434, AccessApi.php:30, WelcomeCommand.php:98). With a config where organizations are disabled, each failedresources:*command now issues a pointless/organizations/{id}request whose failure is silently swallowed, adding latency to the error path.
⚪ Nitpick
integration-tests/resources_sizing_disabled_test.go:92— The negative assertion matches the bare substring "fixed" anywhere in lowercased stderr, so any unrelated future wording (a hint containing "fixed plan", a docs URL with the/anchors/fixed/path segment used throughout this repo's configs) fails the flexible/inaccessible cases for the wrong reason. AssertingNotContains(stderr, fixedNote)and the URL would test the actual behaviour.
Verification
- All five resources commands now call
writeSizingApiDisabledError, and each already has (or newly gained, in BuildResourcesGetCommand) aResourcesUtilconstructor argument autowired by legacy/config/services.yaml. isFixedProjecttreats a missing organization, afalsereturn fromgetOrganizationById(404 path in the mock and the real client) and a thrown exception all as not-Fixed, so the note is skipped rather than crashing.- The test's mock org type values 'fixed'/'flexible' match the constants in internal/api/organization.go and the
typeproperty the PHP code compares. - Each test case builds its own cmdFactory, so the per-case HOME (and the CLI's organization cache) is not shared between the fixed, flexible and inaccessible cases.
The diff adds integration-tests/resources_sizing_disabled_test.go, covering all five commands for Fixed, Flexible and inaccessible orgs; it runs in the integration-test CI job (make integration-test, which builds the CLI and phar first), and the PHP change is covered only by the legacy-php job's php-cs-fixer/phpstan lints — there is no PHP unit test for ResourcesUtil::writeSizingApiDisabledError.
Review details
- Commit: a1adb08
- Model: claude-opus-5
Review 1 of 10 for this pull request · View the full run
Since #118, the metrics commands find the resources overview URL via the "resources_overview" link from GET {environment}/observability/, instead of the environment's "#observability-pipeline" link. TestMetricsLatest (#165) was written against the old lookup, so it failed on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Note
Reviewed — No new issues found · 4 still open (1 nitpick)
🔁 Incremental · 1 file reviewed
Outstanding from earlier reviews:
- 🔵
legacy/src/Service/ResourcesUtil.php:58: An advisory lookup can turn a clean error message into a crash. — ResourcesUtil::isFixedProject still calls getProperty('organization', false) with default lazyLoad, outside any try/catch. (first raised) - 🔵
legacy/src/Service/ResourcesUtil.php:49: Vendor-branded builds leak Upsun branding in an error message. — The note still hardcodes "Upsun Fixed" and https://docs.upsun.com/anchors/fixed/ instead of config values. (first raised) - 🔵
legacy/src/Service/ResourcesUtil.php:63: Unguarded org request on a config where the Organizations API is off. — getOrganizationById() is still called without checking the api.organizations config flag. (first raised) - ⚪
integration-tests/resources_sizing_disabled_test.go:92: Over-broad assertion can fail on unrelated message changes. — The negative case still asserts NotContains on the bare substring "fixed" in lowercased stderr. (first raised)
Verification
- The new
/observability/mock handler returns aresources_overviewHAL link, which is exactly what MetricsCommandBase::getResourcesOverviewUrl() reads (legacy/src/Command/Metrics/MetricsCommandBase.php:118-138). - The entrypoint path is registered with the trailing slash the PHP client requests (
rtrim(uri,'/') . '/observability/'), so the chi route matches. - The overview handler is registered under a distinct, longer static path than the entrypoint, so the two chi routes do not shadow each other.
- Dropping the
#observability-pipelineenv link no longer leaves the test relying on a link the command base no longer consults.
This increment only adapts integration-tests/metrics_test.go to the new observability entrypoint discovery; it is exercised by the integration-test job in .github/workflows/ci.yml (make integration-test), which also runs the PR's resources_sizing_disabled_test.go.
Review 2 of 10 for this pull request · View the full run
Address review feedback on the sizing API error: - Read the docs link from a new service.fixed_docs_url config key, and drop the "Upsun" brand from the message, so vendor builds without the key show no Fixed note. - Skip the organization lookup when api.organizations is disabled. - Read the project's organization without lazy loading, so a missing property cannot trigger an uncaught API request. - Assert on the note and URL in the test, rather than any "fixed" text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Migrated from platformsh/legacy-cli#1598 (original author: @matthiaz).
A user on a Fixed plan saw
The flexible resources API is not enabled for the project ...and tried to enable it. This adds a note pointing to the Fixed docs.On top of the original commits:
resources:*commands (get,set,size:list,build:get,build:set), so it now lives inResourcesUtiland is used by all of them.fixedtype. If the organization can't be loaded, the note is skipped.service.fixed_docs_urlconfig key, set tohttps://docs.upsun.com/anchors/fixed/for Upsun. Without it (e.g. vendor builds) no note is shown.Example (Fixed org):
🤖 Generated with Claude Code