Skip to content

Commit

Permalink
Merge pull request #5397 from microsoft/feat/bundle-dependencies
Browse files Browse the repository at this point in the history
feat/bundle dependencies
  • Loading branch information
baywet authored Sep 12, 2024
2 parents 57d4428 + bea4e59 commit 420ac54
Show file tree
Hide file tree
Showing 13 changed files with 311 additions and 80 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- 📢📢📢 The Visual Studio Code extension is now generally available!. [#5368](https://github.com/microsoft/kiota/issues/5368)
- Fixed a stack overflow in the core generator caused by circular comparisons. [#5369](https://github.com/microsoft/kiota/issues/5369)
- Fixed a bug where collection/array of primitive types members for union/intersection types would be ignored. [#5283](https://github.com/microsoft/kiota/issues/5283)
- Updated dependencies command and view to reflect the availability of bundles. [#5317](https://github.com/microsoft/kiota/issues/5317)
- Fixed a when generating a plugin when only an operation is selected in the root node in the extension. [#5300](https://github.com/microsoft/kiota/issues/5300)
- Fixed a bug where function descriptions in plugin manifest defaults to path summary instead of description. [#5301](https://github.com/microsoft/kiota/issues/5301)
- Fixed a bug where TypeScript would not properly build URIs with uppercase first characters query parameter names.[#5382](https://github.com/microsoft/kiota/issues/5382)
Expand Down
51 changes: 43 additions & 8 deletions scripts/update-versions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ function Retry-Command {
}
}

function Get-QueryName {
Param(
$dependency
)
$dependency.QueryName ?? $dependency.Name
}

# Read the appsettings.json file
$mainSettings = Join-Path -Path $PSScriptRoot -ChildPath "..\src\kiota\appsettings.json"
$appSettings = Get-Content -Path $mainSettings -Raw | ConvertFrom-Json
Expand All @@ -113,62 +120,90 @@ foreach ($languageName in ($appSettings.Languages | Get-Member -MemberType NoteP
$language = $appSettings.Languages.$languageName
if ($languageName -eq "CSharp" -or $languageName -eq "CLI") {
foreach ($dependency in $language.Dependencies) {
if ($null -ne $dependency.MaximumVersion -and $dependency.MaximumVersion -eq $dependency.Version) {
Write-Information "Skipping $($dependency.Name) as it's already at the maximum version"
continue
}
Retry-Command -ScriptBlock {
$latestVersion = Get-LatestNugetVersion -packageId $dependency.Name
$latestVersion = Get-LatestNugetVersion -packageId (Get-QueryName -dependency $dependency)
Write-Information "Updating $($dependency.Name) from $($dependency.Version) to $latestVersion"
$dependency.Version = $latestVersion
}
}
}
elseif ($languageName -eq "Go") {
foreach ($dependency in $language.Dependencies) {
if ($null -ne $dependency.MaximumVersion -and $dependency.MaximumVersion -eq $dependency.Version) {
Write-Information "Skipping $($dependency.Name) as it's already at the maximum version"
continue
}
Retry-Command -ScriptBlock {
$latestVersion = Get-LatestGithubRelease -packageId $dependency.Name
$latestVersion = Get-LatestGithubRelease -packageId (Get-QueryName -dependency $dependency)
Write-Information "Updating $($dependency.Name) from $($dependency.Version) to $latestVersion"
$dependency.Version = $latestVersion
}
}
}
elseif ($languageName -eq "TypeScript") {
foreach ($dependency in $language.Dependencies) {
if ($null -ne $dependency.MaximumVersion -and $dependency.MaximumVersion -eq $dependency.Version) {
Write-Information "Skipping $($dependency.Name) as it's already at the maximum version"
continue
}
Retry-Command -ScriptBlock {
$latestVersion = Get-LatestNpmVersion -packageId $dependency.Name
$latestVersion = Get-LatestNpmVersion -packageId (Get-QueryName -dependency $dependency)
Write-Information "Updating $($dependency.Name) from $($dependency.Version) to $latestVersion"
$dependency.Version = $latestVersion
}
}
}
elseif ($languageName -eq "Java") {
foreach ($dependency in $language.Dependencies) {
if ($null -ne $dependency.MaximumVersion -and $dependency.MaximumVersion -eq $dependency.Version) {
Write-Information "Skipping $($dependency.Name) as it's already at the maximum version"
continue
}
Retry-Command -ScriptBlock {
$latestVersion = Get-LatestMavenVersion -packageId $dependency.Name.Replace("jakarta.annotation:jakarta.annotation-api", "jakarta/annotation.jakarta|annotation-api")
$latestVersion = Get-LatestMavenVersion -packageId (Get-QueryName -dependency $dependency)
Write-Information "Updating $($dependency.Name) from $($dependency.Version) to $latestVersion"
$dependency.Version = $latestVersion
}
}
}
elseif ($languageName -eq "PHP") {
foreach ($dependency in $language.Dependencies) {
if ($null -ne $dependency.MaximumVersion -and $dependency.MaximumVersion -eq $dependency.Version) {
Write-Information "Skipping $($dependency.Name) as it's already at the maximum version"
continue
}
Retry-Command -ScriptBlock {
$latestVersion = Get-LatestComposerVersion -packageId $dependency.Name
$latestVersion = Get-LatestComposerVersion -packageId (Get-QueryName -dependency $dependency)
Write-Information "Updating $($dependency.Name) from $($dependency.Version) to $latestVersion"
$dependency.Version = $latestVersion
}
}
}
elseif ($languageName -eq "Python") {
foreach ($dependency in $language.Dependencies) {
if ($null -ne $dependency.MaximumVersion -and $dependency.MaximumVersion -eq $dependency.Version) {
Write-Information "Skipping $($dependency.Name) as it's already at the maximum version"
continue
}
Retry-Command -ScriptBlock {
$latestVersion = Get-LatestPypiVersion -packageId $dependency.Name
$latestVersion = Get-LatestPypiVersion -packageId (Get-QueryName -dependency $dependency)
Write-Information "Updating $($dependency.Name) from $($dependency.Version) to $latestVersion"
$dependency.Version = $latestVersion
}
}
}
elseif ($languageName -eq "Ruby") {
foreach ($dependency in $language.Dependencies) {
if ($null -ne $dependency.MaximumVersion -and $dependency.MaximumVersion -eq $dependency.Version) {
Write-Information "Skipping $($dependency.Name) as it's already at the maximum version"
continue
}
Retry-Command -ScriptBlock {
$latestVersion = Get-LatestRubygemVersion -packageId $dependency.Name
$latestVersion = Get-LatestRubygemVersion -packageId (Get-QueryName -dependency $dependency)
Write-Information "Updating $($dependency.Name) from $($dependency.Version) to $latestVersion"
$dependency.Version = $latestVersion
}
Expand All @@ -180,5 +215,5 @@ foreach ($languageName in ($appSettings.Languages | Get-Member -MemberType NoteP
}

# Write the updated appsettings.json file
$appSettings | ConvertTo-Json -Depth 100 | Set-Content -Path $mainSettings
$appSettings | ConvertTo-Json -Depth 100 | Set-Content -Path $mainSettings -NoNewLine

25 changes: 25 additions & 0 deletions src/Kiota.Builder/LanguageInformation.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using Kiota.Builder.Extensions;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Interfaces;
Expand Down Expand Up @@ -72,13 +73,23 @@ public record LanguageDependency : IOpenApiSerializable
{
public string Name { get; set; } = string.Empty;
public string Version { get; set; } = string.Empty;
[JsonPropertyName("Type")]
public DependencyType? DependencyType
{
get; set;
}
private const string TypePropertyName = "type";
public void SerializeAsV2(IOpenApiWriter writer) => SerializeAsV3(writer);
public void SerializeAsV3(IOpenApiWriter writer)
{
ArgumentNullException.ThrowIfNull(writer);
writer.WriteStartObject();
writer.WriteProperty(nameof(Name).ToFirstCharacterLowerCase(), Name);
writer.WriteProperty(nameof(Version).ToFirstCharacterLowerCase(), Version);
if (DependencyType is not null)
{
writer.WriteProperty(TypePropertyName, DependencyType.ToString());
}
writer.WriteEndObject();
}
public static LanguageDependency Parse(IOpenApiAny source)
Expand All @@ -93,6 +104,10 @@ public static LanguageDependency Parse(IOpenApiAny source)
{
extension.Version = versionValue.Value;
}
if (rawObject.TryGetValue(TypePropertyName, out var typeValue) && typeValue is OpenApiString typeStringValue && Enum.TryParse<DependencyType>(typeStringValue.Value, true, out var parsedTypeValue))
{
extension.DependencyType = parsedTypeValue;
}
return extension;
}
}
Expand All @@ -103,3 +118,13 @@ public enum LanguageMaturityLevel
Preview,
Stable
}

public enum DependencyType
{
Abstractions,
Serialization,
Authentication,
Http,
Bundle,
Additional
}
12 changes: 12 additions & 0 deletions src/kiota/Handlers/BaseKiotaCommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,18 @@ protected void DisplayInfoHint(GenerationLanguage language, string path, string
DisplayHint("Hint: use the info command to get the list of dependencies you need to add to your project.",
$"Example: kiota info {sourceArg} -l {language}");
}
protected void DisplayDependenciesHint(GenerationLanguage generationLanguage)
{
DisplayHint("Legend:",
"- Abstractions dependencies define the core concepts of the language. Required at build time.",
"- Authentication dependencies implement authentication providers. Optional at runtime.",
"- Additional dependencies are required in addition to the abstractions or bundle. Required at build time.",
"- Bundle dependencies include abstractions, serialization and HTTP dependencies for simpler management.",
"- HTTP dependencies implement the request adapter with a specific HTTP client. Required at runtime.",
"- Serialization dependencies implement serialization and deserialization for a given format. Required at runtime.");
DisplayHint("Hint: use the --dependency-type argument to filter the dependencies by type.",
$"Example: kiota info -l {generationLanguage} --dependency-type serialization");
}
protected void DisplayInstallHint(LanguageInformation languageInformation, List<LanguageDependency> languageDependencies)
{
if (!string.IsNullOrEmpty(languageInformation.DependencyInstallCommand) && languageDependencies.Count > 0)
Expand Down
25 changes: 21 additions & 4 deletions src/kiota/Handlers/KiotaInfoCommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ public required Option<bool> JsonOption
{
get; init;
}
public required Option<DependencyType[]> DependencyTypesOption
{
get; init;
}

public override async Task<int> InvokeAsync(InvocationContext context)
{
Expand All @@ -48,6 +52,7 @@ public override async Task<int> InvokeAsync(InvocationContext context)
string searchTerm = context.ParseResult.GetValueForOption(SearchTermOption) ?? string.Empty;
string version = context.ParseResult.GetValueForOption(VersionOption) ?? string.Empty;
bool json = context.ParseResult.GetValueForOption(JsonOption);
DependencyType[] dependencyTypes = context.ParseResult.GetValueForOption(DependencyTypesOption) ?? [];
GenerationLanguage? language = context.ParseResult.GetValueForOption(GenerationLanguage);
CancellationToken cancellationToken = context.BindingContext.GetService(typeof(CancellationToken)) is CancellationToken token ? token : CancellationToken.None;
var (loggerFactory, logger) = GetLoggerAndFactory<KiotaBuilder>(context);
Expand Down Expand Up @@ -95,7 +100,7 @@ public override async Task<int> InvokeAsync(InvocationContext context)
return 1;
#endif
}
ShowLanguageInformation(language.Value, instructions, json);
ShowLanguageInformation(language.Value, instructions, json, dependencyTypes);
return 0;
}
}
Expand All @@ -113,7 +118,7 @@ private void ShowLanguagesTable()
var layout = new StackLayoutView { view };
console.Append(layout);
}
private void ShowLanguageInformation(GenerationLanguage language, LanguagesInformation informationSource, bool json)
private void ShowLanguageInformation(GenerationLanguage language, LanguagesInformation informationSource, bool json, DependencyType[] dependencyTypes)
{
if (informationSource.TryGetValue(language.ToString(), out var languageInformation))
{
Expand All @@ -122,17 +127,29 @@ private void ShowLanguageInformation(GenerationLanguage language, LanguagesInfor
DisplayInfo($"The language {language} is currently in {languageInformation.MaturityLevel} maturity level.",
"After generating code for this language, you need to install the following packages:");
var orderedDependencies = languageInformation.Dependencies.OrderBy(static x => x.Name).Select(static x => x).ToList();
var filteredDependencies = (dependencyTypes.ToHashSet(), orderedDependencies.Any(static x => x.DependencyType is DependencyType.Bundle)) switch
{
//if the user requested a specific type, we filter the dependencies
({ Count: > 0 }, _) => orderedDependencies.Where(x => x.DependencyType is null || dependencyTypes.Contains(x.DependencyType.Value)).ToList(),
//otherwise we display only the bundle dependencies
(_, true) => orderedDependencies.Where(static x => x.DependencyType is DependencyType.Bundle or DependencyType.Authentication or DependencyType.Additional).ToList(),
//otherwise we display all dependencies
_ => orderedDependencies
};
var view = new TableView<LanguageDependency>()
{
Items = orderedDependencies,
Items = filteredDependencies,
};
view.AddColumn(static x => x.Name, "Package Name");
view.AddColumn(static x => x.Version, "Version");
if (orderedDependencies.Any(static x => x.DependencyType is not null))
view.AddColumn(static x => x.DependencyType?.ToString(), "Type");
var console = new SystemConsole();
using var terminal = new SystemConsoleTerminal(console);
var layout = new StackLayoutView { view };
console.Append(layout);
DisplayInstallHint(languageInformation, orderedDependencies);
DisplayDependenciesHint(language);
DisplayInstallHint(languageInformation, filteredDependencies);
}
else
{
Expand Down
1 change: 1 addition & 0 deletions src/kiota/KiotaConfigurationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public static void BindConfiguration(this KiotaConfiguration configObject, IConf
{
Version = dependency[nameof(LanguageDependency.Version)] ?? string.Empty,
Name = dependency[nameof(LanguageDependency.Name)] ?? string.Empty,
DependencyType = dependency["Type"] is string typeValue && !string.IsNullOrEmpty(typeValue) && Enum.TryParse<DependencyType>(typeValue, true, out var dt) ? dt : null,
});
}
configObject.Languages.Add(section.Key, lngInfo);
Expand Down
15 changes: 15 additions & 0 deletions src/kiota/KiotaHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ private static Command GetInfoCommand()
var clearCacheOption = GetClearCacheOption(defaultGenerationConfiguration.ClearCache);
var searchTermOption = GetSearchKeyOption();
var languageOption = new Option<GenerationLanguage?>("--language", "The target language for the dependencies instructions.");
var dependencyTypesOption = GetDependencyTypesOption();
var jsonOption = new Option<bool>("--json", "Generate a plain and machine-parsable json output.");
languageOption.AddAlias("-l");
AddEnumValidator(languageOption, "language");
Expand All @@ -120,6 +121,7 @@ private static Command GetInfoCommand()
searchTermOption,
languageOption,
jsonOption,
dependencyTypesOption,
};
infoCommand.Handler = new KiotaInfoCommandHandler
{
Expand All @@ -131,9 +133,22 @@ private static Command GetInfoCommand()
SearchTermOption = searchTermOption,
GenerationLanguage = languageOption,
JsonOption = jsonOption,
DependencyTypesOption = dependencyTypesOption,
};
return infoCommand;
}
private static Option<DependencyType[]> GetDependencyTypesOption()
{
var dependencyTypesOption = new Option<DependencyType[]>("--dependency-type", "The type of dependency to display instructions for.")
{
IsRequired = false,
Arity = ArgumentArity.ZeroOrMore,
};
dependencyTypesOption.AddAlias("--dt");
dependencyTypesOption.SetDefaultValue(Array.Empty<DependencyType>());
dependencyTypesOption.AddCompletions(Enum.GetNames<DependencyType>());
return dependencyTypesOption;
}
private static Option<string> GetSearchKeyOption()
{
var option = new Option<string>("--search-key", () => string.Empty, "The API search key to display the description for. Use the search command to get the key.");
Expand Down
Loading

0 comments on commit 420ac54

Please sign in to comment.