Skip to content

feat(cloudformation): harden language server install, caching, cleanup, and startup recovery - #8856

Merged
dnemec-aws merged 11 commits into
aws:masterfrom
satyakigh:cfn-lsp
Sep 24, 2026
Merged

dnemec-aws merged 11 commits into
aws:masterfrom
satyakigh:cfn-lsp

Conversation

@satyakigh

@satyakigh satyakigh commented Aug 19, 2026 •

Copy link
Copy Markdown
Contributor

Problem

The CloudFormation language server installer did not recover from common failures: one failed manifest or bundle request aborted startup with no retry, downloads were written without size or hash verification, ZIP entries were extracted without a path-traversal check, a partial install was reused on the next start with no recovery short of deleting the cache by hand, and the manifest lived only in globalState, so an offline start had no fallback to an installed version. The logic was spread across a ManifestProvider hierarchy, a GitHub-releases adapter, and CloudFormation-specific target remapping.

Solution

Install and cache. Select the highest compatible, non-delisted version with a target for the current platform and arch (win32, darwin, linux, linuxglib2.28). Fetch the manifest and bundle with three retries and exponential backoff, accepting only HTTP 200. Cache the parsed manifest atomically at <cache>/aws/language-servers/<name>/manifest.json; when offline, fall back to that file, then to the highest complete installed version. Verify size and hashes before writing, preflight every ZIP entry for traversal, extract one entry at a time with POSIX bits preserved, and validate the server and required files after extraction and again after post-install. A failed install is removed and an installed version is used instead; hash and no-compatible-version failures propagate. After a successful resolve, keep the active version plus the highest complete fallback and remove the rest.

Startup recovery. LspLauncher starts the client and, if the process fails to start, invalidates the resolved installation and retries once. Known install error codes surface a user-facing message. Restart and deactivation dispose the client session explicitly, and the status bar command is registered once.

Structure. The ManifestProvider hierarchy and GitHub-releases adapter are replaced by a ResolveManifest function. Channel selection (alpha/beta/prod) lives only in the CloudFormation adapter via CFN_LSP_ENVIRONMENT (automation defaults to beta, otherwise prod). CFN_LSP_BUNDLE points at a local server bundle; SettingsLspServerProvider applies only in debug and automation. Fetching goes through cross-fetch so VS Code proxy settings apply. Launch configuration moves into lspClientConfig.ts, where the server runs with its own directory as cwd. Dead Amazon Q-era helpers and types in shared/lsp are removed.

Behavior changes

  • Storage moves from <cache>/aws/toolkits/language-servers/ to <cache>/aws/language-servers/, shared with the other AWS Toolkits so one download serves every IDE. The first start after upgrade re-downloads the server; the legacy directory is not removed yet.
  • Debug instances no longer default to the alpha channel; set CFN_LSP_ENVIRONMENT=alpha to opt in.
  • clientId is forwarded only when CloudFormation telemetry is enabled and the id is not anonymous.
  • The document selector now also matches **/*.yml.

Tradeoffs made deliberately

  • No conditional (ETag/304) manifest request. The manifest is fetched once per activation and is a few tens of KB from a CDN, so a 304 saves only the body while still paying the round trip. Dropping it removes a second piece of state (globalState ETag + body) that previously turned a 304 with no local body into a setup failure. The on-disk manifest.json is now the single cache and offline fallback.
  • Cleanup can remove a version another window or IDE is running. Only versions that are neither the active one nor the highest complete fallback are removed, so this needs two newer versions installed after that process started while it is still running. Loaded code is unaffected by unlinking; the exposed lazy read is the server's cfn-lint assets, which fail closed to "restart the language server". This client shows a Restart Server action if the server exits, and the restart re-resolves. Lock files or open-file checks would need every consumer to cooperate and would leak versions after a crash.

CI

.github/workflows/jscpd.json threshold 3.0% → 3.2%. jscpd 5.3.2 fixed an off-by-one that undercounted every clone by one line, so the same 548 clones now measure 3.12% on this branch and 3.17% on master (2.99% under the old count). None of them touch files in this PR, and filterDuplicates.js reports 0 new clones.


  • Treat all work as PUBLIC. Private feature/x branches will not be squash-merged at release time.
  • Your code changes must meet the guidelines in CONTRIBUTING.md.
  • License: I confirm that my contribution is made under the terms of the Apache 2.0 license.

@satyakigh
satyakigh requested a review from a team August 19, 2026 05:52
@amazon-inspector-ohio

Copy link
Copy Markdown

⏳ I'm reviewing this pull request for security vulnerabilities and code quality issues. I'll provide an update when I'm done

@github-actions

Copy link
Copy Markdown
  • This pull request implements a feat or fix, so it must include a changelog entry (unless the fix is for an unreleased feature). Review the changelog guidelines.
    • Note: beta or "experiment" features that have active users should announce fixes in the changelog.
    • If this is not a feature or fix, use an appropriate type from the title guidelines. For example, telemetry-only changes should use the telemetry type.

@amazon-inspector-ohio

Copy link
Copy Markdown

✅ I finished the code review, and didn't find any security or code quality issues.

…ion, caching, cleanup, and startup recovery while simplifying the installer abstraction layer
@satyakigh satyakigh changed the title feat(cloudformation): Harden CloudFormation language-server installat… feat(cloudformation): harden language server install, caching, cleanup, and startup recovery Sep 10, 2026
Comment thread packages/core/src/shared/lsp/manifestResolver.ts
Comment thread packages/core/src/shared/lsp/utils/cleanup.ts
Comment thread .github/workflows/node.js.yml Outdated
@dnemec-aws
dnemec-aws disabled auto-merge September 24, 2026 21:14
@dnemec-aws
dnemec-aws merged commit 240370a into aws:master Sep 24, 2026
28 of 29 checks passed
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.

3 participants