Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(amazonq): Add support for complex workspaces for /dev and /doc. #5411

Merged
merged 1 commit into from
Mar 12, 2025

Conversation

ctidd
Copy link
Contributor

@ctidd ctidd commented Feb 26, 2025

This provides multi-content-root workspace support for /dev and /doc.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

Description

Problem:

Q does not support multi-root workspaces for /dev, /doc, and related features.

Solution:

This change starts by adding a Workspace construct for uploads involving the FeatureDevSessionContext, which detects the IDE workspace's root directory as the common ancestor of the workspace's "content roots", to serve as the root of the addressable workspace filesystem layout. Then, when choosing what files to upload, files within this tree which are members of the workspace's content roots are included. This broadens /dev and /doc to support a multi-content-root workspace as a single working tree, while continuing to respect content roots of the workspace and not uploading extraneous content.

The change itself is straightforward, identifying the common ancestor and basing further work on that root. From here, a few changes unravel:

  1. Problem: We need to add support for .gitignore in subdirectories (across ProjectContext and FeatureDev). Otherwise, we would confuse users with project-level .gitignore configurations, and it makes sense to fully support subdirectory .gitignore configurations rather than treat projects as a special case. Solution: I've removed nearly all custom gitignore parsing for FeatureDev, offloading the work to the IDE's VCS manager for more native gitignore support.
  2. Problem: We need to require that uploaded files are part of a project "content root" directory, and not simply included because they are under the common ancestor directory (which would otherwise over-include ancillary directories that are not content roots as members of the IDE workspace). Solution: Filter uploaded content based on content roots. This matches the handling already performed by ProjectContextProvider, moving incrementally in the direction of common handling of workspaces across features. (Note: /test and /review appear to use guessModuleDir in their own independent context implementations, and so would continue to have minor symptoms for complex workspaces after these changes. I have not touched these areas.)
  3. Problem: ProjectContextProvider had a dependency on FeatureDevSessionContext for its own ignore rules. Solution: I've reworked this implementation so that ProjectContextProvider and FeatureDevSessionContext now depend on a simplified shared primitive, which should be easier to audit and understand than the use-case specific rules that were inside FeatureDevSessionContext. However, FeatureDevSessionContext is kept in a global location to be consumed by /doc. (Removing this /doc -> /dev coupling is deeper than I was willing to go with these changes as broad as they already are.)

Additional granular changes to behavior:

  1. Problem: We had inconsistent behaviors when auto build for /dev was enabled vs disabled. Overzealous filtering of file types was applied when it was not enabled. Solution: Now, filtering is applied based on what was previously the more permissive behavior of the two. Now, in both cases, only .gitignore and a few additional artifact-exclusion filters are applied (e.g. .git, node_modules, etc).

Checklist

  • My code follows the code style of this project
  • I have added tests to cover my changes
  • [TODO] A short description of the change has been added to the CHANGELOG if the change is customer-facing in the IDE.
  • I have added metrics for my changes (if required)

License

I confirm that my contribution is made under the terms of the Apache 2.0 license.

@ctidd ctidd force-pushed the ctidd/multiroot branch 2 times, most recently from 185a18e to 342b5a4 Compare March 9, 2025 11:33
@ctidd ctidd changed the title feat(amazonq): Add support for multi-project workspaces. feat(amazonq): Add support for complex workspaces for /dev and /doc. Mar 9, 2025
@ctidd ctidd force-pushed the ctidd/multiroot branch 2 times, most recently from 138964f to 8854f88 Compare March 9, 2025 11:52
import software.aws.toolkits.jetbrains.services.amazonq.QConstants.MAX_FILE_SIZE_BYTES
import software.aws.toolkits.jetbrains.utils.isDevFile
import software.aws.toolkits.resources.AwsCoreBundle
import software.aws.toolkits.telemetry.AmazonqTelemetry

Check warning

Code scanning / QDJVMC

Usage of redundant or deprecated syntax or deprecated symbols Warning

Remove deprecated symbol import
import software.aws.toolkits.jetbrains.services.amazonq.QConstants.MAX_FILE_SIZE_BYTES
import software.aws.toolkits.jetbrains.utils.isDevFile
import software.aws.toolkits.resources.AwsCoreBundle
import software.aws.toolkits.telemetry.AmazonqTelemetry

Check warning

Code scanning / QDJVMC

Usage of redundant or deprecated syntax or deprecated symbols Warning

'AmazonqTelemetry' is deprecated. Use type-safe metric builders
@ctidd ctidd force-pushed the ctidd/multiroot branch 2 times, most recently from 43f93d6 to 494314e Compare March 9, 2025 20:07
@ctidd ctidd linked an issue Mar 11, 2025 that may be closed by this pull request
@ctidd ctidd force-pushed the ctidd/multiroot branch from 494314e to bf817f3 Compare March 11, 2025 04:38
@ctidd ctidd requested review from rli and neilk-aws March 11, 2025 04:53
@ctidd ctidd marked this pull request as ready for review March 11, 2025 04:54
@ctidd ctidd requested review from a team as code owners March 11, 2025 04:54

private suspend fun createTemporaryZipFileAsync(block: suspend (FileSystem) -> Unit): Path = withContext(getCoroutineBgContext()) {
// Don't use Files.createTempFile since the file must not be created for ZipFS to work
val tempFilePath: Path = Paths.get(FileUtils.getTempDirectory().absolutePath, "${UUID.randomUUID()}.zip")
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's better to create specific folder in the temp location and store zip there.
Also how is the zip file deleted after upload ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the existing impl, so I'm confident in how it works already. It just looks new here because the file is moved.

@@ -967,7 +966,7 @@ class DocController(
message = message("amazonqDoc.prompt.choose_folder_to_continue")
)

val selectedFolder = selectFolder(context.project, currentSourceFolder)
val selectedFolder = selectFolder(context.project, workspaceRoot)
Copy link
Contributor

Choose a reason for hiding this comment

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

should it be session.context.selectionRoot instead ?

Copy link
Contributor Author

@ctidd ctidd Mar 11, 2025

Choose a reason for hiding this comment

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

This is a small change in behavior, which handles a niche case slightly more in line with a workspace-oriented view. This behavior changes when a user selects a folder, and then triggers folder selection again.

  • Before: The file tree is opened on the current source folder to select new source folder.
  • Now: The file tree is opened on the workspace root to select a new source folder. (Like it was for the initial selection.)

This is a more workspace-oriented behavior (i.e. "select what you want") instead of nudging the user toward a folder inside their selected working folder, when the user selects a different folder multiple times.

@ctidd ctidd force-pushed the ctidd/multiroot branch 2 times, most recently from bd75d40 to 24a65dc Compare March 11, 2025 21:27
@ctidd ctidd force-pushed the ctidd/multiroot branch 2 times, most recently from ffbc9d8 to ce0e40c Compare March 11, 2025 23:39
import kotlin.io.path.deleteExisting
import kotlin.io.path.exists

class WorkspaceTest : LightPlatformTestCase() {
Copy link
Contributor

Choose a reason for hiding this comment

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

generally we've been trying to move to junit5 but ok


// This function checks for existence of `devfile.yaml` in customer's repository, currently only `devfile.yaml` is supported for this feature.
fun checkForDevFile(): Boolean {
val devFile = File(addressableRoot.toString(), "devfile.yaml")
Copy link
Contributor

Choose a reason for hiding this comment

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

devfile.yml is also valid according to spec

Comment on lines +141 to +150
val filesToIncludeFlow = channelFlow {
// chunk with some reasonable number because we don't actually need a new job for each file
files.chunked(50).forEach { chunk ->
launch {
for (file in chunk) {
send(file)
}
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

i see that this is the existing impl, but the flow seems superfluous for what is being accomplished here

val additionalGlobalIgnoreRulesForStrictSources =
additionalGlobalIgnoreRules +
listOf(
// FIXME: It is incredibly brittle that this source of truth is a "telemetry" component
Copy link
Contributor

Choose a reason for hiding this comment

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

+1

@ctidd ctidd force-pushed the ctidd/multiroot branch from ce0e40c to 27b2aac Compare March 12, 2025 17:20
@rli rli merged commit 3f3726b into aws:main Mar 12, 2025
3 of 11 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.

/dev feature only works on one module, not all in workspace
4 participants