Skip to content

Commit

Permalink
Merge branch 'feature/q-lsp' into samgst/lsp-fileUtil
Browse files Browse the repository at this point in the history
  • Loading branch information
samgst-amazon authored Feb 28, 2025
2 parents e090401 + 6bfc0e5 commit 43417c3
Show file tree
Hide file tree
Showing 22 changed files with 542 additions and 84 deletions.
20 changes: 20 additions & 0 deletions .changes/3.57.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"date" : "2025-02-28",
"version" : "3.57",
"entries" : [ {
"type" : "bugfix",
"description" : "Fix suggestion not visible in remote for 2024.3"
}, {
"type" : "bugfix",
"description" : "/test: update capability card text"
}, {
"type" : "bugfix",
"description" : "Amazon Q /doc: update workspace too large error message"
}, {
"type" : "bugfix",
"description" : "Amazon Q /doc: Fix uploading file method throwing incorrect workspace too large error message"
}, {
"type" : "bugfix",
"description" : "/transform: skip running tests locally when user chooses to do so"
} ]
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# _3.57_ (2025-02-28)
- **(Bug Fix)** Fix suggestion not visible in remote for 2024.3
- **(Bug Fix)** /test: update capability card text
- **(Bug Fix)** Amazon Q /doc: update workspace too large error message
- **(Bug Fix)** Amazon Q /doc: Fix uploading file method throwing incorrect workspace too large error message
- **(Bug Fix)** /transform: skip running tests locally when user chooses to do so

# _3.56_ (2025-02-20)
- **(Feature)** Amazon Q /doc: support making changes to architecture diagrams

Expand Down
8 changes: 8 additions & 0 deletions buildspec/windowsTestsForAmazonQ.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ env:
phases:
install:
commands:
# force install java21 while we work through path issues
- |
$javaName = "C:\Program Files\Amazon Corretto" | ForEach-Object {
ls $_ | Where-Object {$_ -Like "jdk*"} | Sort-Object -Descending -Property Name | Select-Object -first 1 -expandproperty Name
}
$JAVA_HOME = "C:\Program Files\Amazon Corretto\$javaName"
- |
if(-Not($Env:CODE_COV_TOKEN -eq $null)) {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
Expand All @@ -21,6 +27,8 @@ phases:
# See https://github.com/NuGet/NuGet.Client/pull/4259
$Env:NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY = "3,1000"
$Env:JAVA_HOME = $JAVA_HOME
if ($Env:CODEARTIFACT_DOMAIN_NAME -and $Env:CODEARTIFACT_REPO_NAME) {
$Env:CODEARTIFACT_URL=aws codeartifact get-repository-endpoint --domain $Env:CODEARTIFACT_DOMAIN_NAME --repository $Env:CODEARTIFACT_REPO_NAME --format maven --query repositoryEndpoint --output text
# $Env:CODEARTIFACT_NUGET_URL=aws codeartifact get-repository-endpoint --domain $Env:CODEARTIFACT_DOMAIN_NAME --repository $Env:CODEARTIFACT_REPO_NAME --format nuget --query repositoryEndpoint --output text
Expand Down
8 changes: 8 additions & 0 deletions buildspec/windowsTestsForCore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ env:
phases:
install:
commands:
# force install java21 while we work through path issues
- |
$javaName = "C:\Program Files\Amazon Corretto" | ForEach-Object {
ls $_ | Where-Object {$_ -Like "jdk*"} | Sort-Object -Descending -Property Name | Select-Object -first 1 -expandproperty Name
}
$JAVA_HOME = "C:\Program Files\Amazon Corretto\$javaName"
- |
if(-Not($Env:CODE_COV_TOKEN -eq $null)) {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
Expand All @@ -21,6 +27,8 @@ phases:
# See https://github.com/NuGet/NuGet.Client/pull/4259
$Env:NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY = "3,1000"
$Env:JAVA_HOME = $JAVA_HOME
if ($Env:CODEARTIFACT_DOMAIN_NAME -and $Env:CODEARTIFACT_REPO_NAME) {
$Env:CODEARTIFACT_URL=aws codeartifact get-repository-endpoint --domain $Env:CODEARTIFACT_DOMAIN_NAME --repository $Env:CODEARTIFACT_REPO_NAME --format maven --query repositoryEndpoint --output text
# $Env:CODEARTIFACT_NUGET_URL=aws codeartifact get-repository-endpoint --domain $Env:CODEARTIFACT_DOMAIN_NAME --repository $Env:CODEARTIFACT_REPO_NAME --format nuget --query repositoryEndpoint --output text
Expand Down
8 changes: 8 additions & 0 deletions buildspec/windowsTestsForToolkit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ env:
phases:
install:
commands:
# force install java21 while we work through path issues
- |
$javaName = "C:\Program Files\Amazon Corretto" | ForEach-Object {
ls $_ | Where-Object {$_ -Like "jdk*"} | Sort-Object -Descending -Property Name | Select-Object -first 1 -expandproperty Name
}
$JAVA_HOME = "C:\Program Files\Amazon Corretto\$javaName"
- |
if(-Not($Env:CODE_COV_TOKEN -eq $null)) {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
Expand All @@ -21,6 +27,8 @@ phases:
# See https://github.com/NuGet/NuGet.Client/pull/4259
$Env:NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY = "3,1000"
$Env:JAVA_HOME = $JAVA_HOME
if ($Env:CODEARTIFACT_DOMAIN_NAME -and $Env:CODEARTIFACT_REPO_NAME) {
$Env:CODEARTIFACT_URL=aws codeartifact get-repository-endpoint --domain $Env:CODEARTIFACT_DOMAIN_NAME --repository $Env:CODEARTIFACT_REPO_NAME --format maven --query repositoryEndpoint --output text
# $Env:CODEARTIFACT_NUGET_URL=aws codeartifact get-repository-endpoint --domain $Env:CODEARTIFACT_DOMAIN_NAME --repository $Env:CODEARTIFACT_REPO_NAME --format nuget --query repositoryEndpoint --output text
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# SPDX-License-Identifier: Apache-2.0

# Toolkit Version
toolkitVersion=3.57-SNAPSHOT
toolkitVersion=3.58-SNAPSHOT

# Publish Settings
publishToken=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import software.aws.toolkits.core.utils.getLogger
import software.aws.toolkits.core.utils.info
import software.aws.toolkits.core.utils.warn
import software.aws.toolkits.jetbrains.isDeveloperMode
import software.aws.toolkits.jetbrains.services.amazonq.lsp.auth.DefaultAuthCredentialsService
import software.aws.toolkits.jetbrains.services.amazonq.lsp.encryption.JwtEncryptionManager
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.createExtendedClientMetadata
import software.aws.toolkits.jetbrains.services.telemetry.ClientMetadata
Expand Down Expand Up @@ -303,6 +304,8 @@ private class AmazonQServerInstance(private val project: Project, private val cs
}
languageServer.initialized(InitializedParams())
}

DefaultAuthCredentialsService(project, encryptionManager, this)
}

override fun dispose() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package software.aws.toolkits.jetbrains.services.amazonq.lsp.artifacts

import com.intellij.util.io.createDirectories
import com.intellij.util.text.SemVer
import org.jetbrains.annotations.VisibleForTesting
import software.aws.toolkits.core.utils.deleteIfExists
import software.aws.toolkits.core.utils.error
import software.aws.toolkits.core.utils.exists
Expand Down Expand Up @@ -45,9 +46,23 @@ class ArtifactHelper(private val lspArtifactsPath: Path = DEFAULT_ARTIFACT_PATH,
}

fun deleteOlderLspArtifacts(manifestVersionRanges: ArtifactManager.SupportedManifestVersionRange) {
val validVersions = getAllLocalLspArtifactsWithinManifestRange(manifestVersionRanges)

// Keep the latest 2 versions, delete others
validVersions.drop(2).forEach { (folder, _) ->
try {
folder.toFile().deleteRecursively()
logger.info { "Deleted older LSP artifact: ${folder.fileName}" }
} catch (e: Exception) {
logger.error(e) { "Failed to delete older LSP artifact: ${folder.fileName}" }
}
}
}

fun getAllLocalLspArtifactsWithinManifestRange(manifestVersionRanges: ArtifactManager.SupportedManifestVersionRange): List<Pair<Path, SemVer>> {
val localFolders = getSubFolders(lspArtifactsPath)

val validVersions = localFolders
return localFolders
.mapNotNull { localFolder ->
SemVer.parseFromText(localFolder.fileName.toString())?.let { semVer ->
if (semVer in manifestVersionRanges.startVersion..manifestVersionRanges.endVersion) {
Expand All @@ -58,16 +73,6 @@ class ArtifactHelper(private val lspArtifactsPath: Path = DEFAULT_ARTIFACT_PATH,
}
}
.sortedByDescending { (_, semVer) -> semVer }

// Keep the latest 2 versions, delete others
validVersions.drop(2).forEach { (folder, _) ->
try {
folder.toFile().deleteRecursively()
logger.info { "Deleted older LSP artifact: ${folder.fileName}" }
} catch (e: Exception) {
logger.error(e) { "Failed to delete older LSP artifact: ${folder.fileName}" }
}
}
}

fun getExistingLspArtifacts(versions: List<ManifestManager.Version>, target: ManifestManager.VersionTarget?): Boolean {
Expand Down Expand Up @@ -103,23 +108,27 @@ class ArtifactHelper(private val lspArtifactsPath: Path = DEFAULT_ARTIFACT_PATH,
logger.info { "Attempt ${currentAttempt.get()} of $maxDownloadAttempts to download LSP artifacts" }

try {
if (downloadLspArtifacts(temporaryDownloadPath, target)) {
if (downloadLspArtifacts(temporaryDownloadPath, target) && target != null && !target.contents.isNullOrEmpty()) {
moveFilesFromSourceToDestination(temporaryDownloadPath, downloadPath)
target.contents
.mapNotNull { it.filename }
.forEach { filename -> extractZipFile(downloadPath.resolve(filename), downloadPath) }
logger.info { "Successfully downloaded and moved LSP artifacts to $downloadPath" }
return
}
} catch (e: Exception) {
logger.error(e) { "Failed to download/move LSP artifacts on attempt ${currentAttempt.get()}" }
temporaryDownloadPath.toFile().deleteRecursively()

if (currentAttempt.get() >= maxDownloadAttempts) {
throw LspException("Failed to download LSP artifacts after $maxDownloadAttempts attempts", LspException.ErrorCode.DOWNLOAD_FAILED)
}
downloadPath.toFile().deleteRecursively()
}
}
if (currentAttempt.get() >= maxDownloadAttempts) {
throw LspException("Failed to download LSP artifacts after $maxDownloadAttempts attempts", LspException.ErrorCode.DOWNLOAD_FAILED)
}
}

private fun downloadLspArtifacts(downloadPath: Path, target: ManifestManager.VersionTarget?): Boolean {
@VisibleForTesting
internal fun downloadLspArtifacts(downloadPath: Path, target: ManifestManager.VersionTarget?): Boolean {
if (target == null || target.contents.isNullOrEmpty()) {
logger.warn { "No target contents available for download" }
return false
Expand Down Expand Up @@ -166,7 +175,8 @@ class ArtifactHelper(private val lspArtifactsPath: Path = DEFAULT_ARTIFACT_PATH,
}
}

private fun validateFileHash(filePath: Path, expectedHash: String?): Boolean {
@VisibleForTesting
internal fun validateFileHash(filePath: Path, expectedHash: String?): Boolean {
if (expectedHash == null) return false
val contentHash = generateSHA384Hash(filePath)
return "sha384:$contentHash" == expectedHash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
package software.aws.toolkits.jetbrains.services.amazonq.lsp.artifacts

import com.intellij.util.text.SemVer
import org.assertj.core.util.VisibleForTesting
import org.jetbrains.annotations.VisibleForTesting
import software.aws.toolkits.core.utils.error
import software.aws.toolkits.core.utils.getLogger
import software.aws.toolkits.core.utils.info
import software.aws.toolkits.jetbrains.services.amazonq.project.manifest.ManifestManager

class ArtifactManager {
class ArtifactManager(
private val manifestFetcher: ManifestFetcher = ManifestFetcher(),
private val artifactHelper: ArtifactHelper = ArtifactHelper(),
manifestRange: SupportedManifestVersionRange?,
) {

data class SupportedManifestVersionRange(
val startVersion: SemVer,
Expand All @@ -21,20 +25,7 @@ class ArtifactManager {
val inRangeVersions: List<ManifestManager.Version>,
)

private val manifestFetcher: ManifestFetcher
private val artifactHelper: ArtifactHelper
private val manifestVersionRanges: SupportedManifestVersionRange

// Primary constructor with config
constructor(
manifestFetcher: ManifestFetcher = ManifestFetcher(),
artifactFetcher: ArtifactHelper = ArtifactHelper(),
manifestRange: SupportedManifestVersionRange?,
) {
manifestVersionRanges = manifestRange ?: DEFAULT_VERSION_RANGE
this.manifestFetcher = manifestFetcher
this.artifactHelper = artifactFetcher
}
private val manifestVersionRanges: SupportedManifestVersionRange = manifestRange ?: DEFAULT_VERSION_RANGE

// Secondary constructor with no parameters
constructor() : this(ManifestFetcher(), ArtifactHelper(), null)
Expand All @@ -57,7 +48,11 @@ class ArtifactManager {
this.artifactHelper.removeDelistedVersions(lspVersions.deListedVersions)

if (lspVersions.inRangeVersions.isEmpty()) {
// No versions are found which are in the given range.
// No versions are found which are in the given range. Fallback to local lsp artifacts.
val localLspArtifacts = this.artifactHelper.getAllLocalLspArtifactsWithinManifestRange(manifestVersionRanges)
if (localLspArtifacts.isNotEmpty()) {
return
}
throw LspException("Language server versions not found in manifest.", LspException.ErrorCode.NO_COMPATIBLE_LSP_VERSION)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class LspException(message: String, private val errorCode: ErrorCode, cause: Thr
HASH_MISMATCH,
TARGET_NOT_FOUND,
NO_COMPATIBLE_LSP_VERSION,
UNZIP_FAILED,
}

override fun toString(): String = buildString {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@ import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.text.StringUtil
import com.intellij.util.io.DigestUtil
import com.intellij.util.system.CpuArch
import software.aws.toolkits.core.utils.createParentDirectories
import software.aws.toolkits.core.utils.exists
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.StandardCopyOption
import java.security.MessageDigest
import java.util.zip.ZipFile
import kotlin.io.path.isDirectory
import kotlin.io.path.listDirectoryEntries

Expand Down Expand Up @@ -66,3 +71,26 @@ fun moveFilesFromSourceToDestination(sourceDir: Path, targetDir: Path) {
throw IllegalStateException("Failed to move files from $sourceDir to $targetDir", e)
}
}

fun extractZipFile(zipFilePath: Path, destDir: Path) {
if (!zipFilePath.exists()) {
throw FileNotFoundException("Zip file not found: $zipFilePath")
}

try {
ZipFile(zipFilePath.toFile()).use { zipFile ->
zipFile.entries()
.asSequence()
.filterNot { it.isDirectory }
.map { zipEntry ->
val destPath = destDir.resolve(zipEntry.name)
destPath.createParentDirectories()
FileOutputStream(destPath.toFile()).use { targetFile ->
zipFile.getInputStream(zipEntry).copyTo(targetFile)
}
}.toList()
}
} catch (e: Exception) {
throw LspException("Failed to extract zip file: ${e.message}", LspException.ErrorCode.UNZIP_FAILED, cause = e)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

package software.aws.toolkits.jetbrains.services.amazonq.lsp.artifacts

import org.assertj.core.util.VisibleForTesting
import org.jetbrains.annotations.VisibleForTesting
import software.aws.toolkits.core.utils.deleteIfExists
import software.aws.toolkits.core.utils.error
import software.aws.toolkits.core.utils.exists
Expand Down
Loading

0 comments on commit 43417c3

Please sign in to comment.