Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/skills/upgrade-devproxy-version/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ Update `schemas/v<old>/` to `schemas/v<new>/` in:
- `DevProxy/config/microsoft-graph.json` - all `$schema` URLs
- `DevProxy/config/microsoft-graph-rate-limiting.json` - `$schema` URL
- `DevProxy/config/spo-csom-types.json` - `$schema` URL
- `DevProxy/config-templates/devproxyrc.json` - `$schema` URL
- `DevProxy/config-templates/devproxyrc.yaml` - `$schema` URL
- `DevProxy.Plugins/Mocking/MockResponsePlugin.cs` - hardcoded schema URL

**Category C: Installer Files** (format: `X.Y.Z` or `X.Y.Z-beta.N`)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,20 @@ done
echo ""
echo "Step 3: Updating schema URLs..."
# JSON files
for json in DevProxy/devproxyrc.json DevProxy/devproxy-errors.json DevProxy/config/*.json; do
for json in DevProxy/devproxyrc.json DevProxy/devproxy-errors.json DevProxy/config/*.json DevProxy/config-templates/*.json; do
if [[ -f "$WORKSPACE_ROOT/$json" ]]; then
sed -i '' "s|schemas/v$CURRENT_VERSION/|schemas/v$NEW_VERSION/|g" "$WORKSPACE_ROOT/$json"
echo " Updated: $json"
fi
done

for yaml in DevProxy/config-templates/*.yaml; do
if [[ -f "$WORKSPACE_ROOT/$yaml" ]]; then
sed -i '' "s|schemas/v$CURRENT_VERSION/|schemas/v$NEW_VERSION/|g" "$WORKSPACE_ROOT/$yaml"
echo " Updated: $yaml"
fi
done

# CS files with hardcoded schema URLs
MOCK_PLUGIN="$WORKSPACE_ROOT/DevProxy.Plugins/Mocking/MockResponsePlugin.cs"
if [[ -f "$MOCK_PLUGIN" ]]; then
Expand Down
81 changes: 8 additions & 73 deletions DevProxy/Commands/ConfigCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,6 @@ sealed class GitHubTreeItem
public string Type { get; set; } = string.Empty;
}

sealed class VisualStudioCodeSnippet
{
public string? Prefix { get; set; }
public string[]? Body { get; set; }
public string? Description { get; set; }
}

sealed class ConfigCommand : Command
{
private enum ConfigFileFormat
Expand All @@ -54,8 +47,8 @@ private enum ConfigFileFormat
private readonly ILogger _logger;
private readonly IProxyConfiguration _proxyConfiguration;
private readonly HttpClient _httpClient;
private readonly string snippetsBaseUrl = $"https://aka.ms/devproxy/snippets/v{ProxyUtils.NormalizeVersion(ProxyUtils.ProductVersion)}";
private readonly string configFileSnippetName = "ConfigFile";
private const string ConfigTemplatesFolder = "config-templates";

public ConfigCommand(
HttpClient httpClient,
IProxyConfiguration proxyConfiguration,
Expand Down Expand Up @@ -447,35 +440,13 @@ private async Task CreateConfigFileAsync(string name, ConfigFileFormat? format,
try
{
var selectedFormat = format ?? GetConfigFileFormatFromFileName(name);

var snippets = await DownloadSnippetsAsync(selectedFormat);
if (snippets is null)
{
return;
}

if (!snippets.TryGetValue(configFileSnippetName, out var snippet))
{
if (outputFormat == OutputFormat.Text)
{
_logger.LogError("Snippet {SnippetName} not found", configFileSnippetName);
}
return;
}

if (snippet.Body is null || snippet.Body.Length == 0)
{
if (outputFormat == OutputFormat.Text)
{
_logger.LogError("Snippet {SnippetName} is empty", configFileSnippetName);
}
return;
}

var snippetBody = GetSnippetBody(snippet.Body);
var templateFileName = selectedFormat == ConfigFileFormat.Yaml ? "devproxyrc.yaml" : "devproxyrc.json";
var templateFilePath = Path.Combine(AppContext.BaseDirectory, ConfigTemplatesFolder, templateFileName);
_logger.LogDebug("Reading config template from {TemplateFilePath}...", templateFilePath);
var template = await File.ReadAllTextAsync(templateFilePath);

var targetFileName = GetTargetFileName(name);
await File.WriteAllTextAsync(targetFileName, snippetBody);
await File.WriteAllTextAsync(targetFileName, template);

if (outputFormat == OutputFormat.Json)
{
Expand All @@ -494,7 +465,7 @@ private async Task CreateConfigFileAsync(string name, ConfigFileFormat? format,
{
if (outputFormat == OutputFormat.Text)
{
_logger.LogError(ex, "Error downloading config");
_logger.LogError(ex, "Error creating config");
}
}
}
Expand All @@ -508,32 +479,6 @@ private static ConfigFileFormat GetConfigFileFormatFromFileName(string name)
return extension is ".yaml" or ".yml" ? ConfigFileFormat.Yaml : ConfigFileFormat.Json;
}

private async Task<Dictionary<string, VisualStudioCodeSnippet>?> DownloadSnippetsAsync(ConfigFileFormat format)
{
var formatSuffix = format == ConfigFileFormat.Yaml ? "yaml" : "json";
var snippetsFileUrl = $"{snippetsBaseUrl}/{formatSuffix}";
_logger.LogDebug("Downloading snippets from {SnippetsFileUrl}...", snippetsFileUrl);
var response = await _httpClient.GetAsync(new Uri(snippetsFileUrl));
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
try
{
return JsonSerializer.Deserialize<Dictionary<string, VisualStudioCodeSnippet>>(content, ProxyUtils.JsonSerializerOptions);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to parse snippets from {Url}", snippetsFileUrl);
return null;
}
}
else
{
_logger.LogError("Failed to download snippets. Status code: {StatusCode}", response.StatusCode);
return null;
}
}

private string GetTargetFileName(string name)
{
var originalNameWithoutExtension = Path.GetFileNameWithoutExtension(name);
Expand Down Expand Up @@ -566,16 +511,6 @@ private static string GetTargetFolderPath(string dataFolder, string configId)
return newFolder;
}

private static string? GetSnippetBody(string[] bodyLines)
{
var body = string.Join("\n", bodyLines);
// unescape $
body = body.Replace("\\$", "$", StringComparison.OrdinalIgnoreCase);
// remove snippet $n markers
body = Regex.Replace(body, @"\$[0-9]+", "");
return body;
}

private static string? ResolveConfigFile(string? configFilePath)
{
if (!string.IsNullOrEmpty(configFilePath))
Expand Down
3 changes: 3 additions & 0 deletions DevProxy/DevProxy.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@
<None Update="config\spo-csom-types.jpg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="config-templates\*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="prompts\*.prompty">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
10 changes: 10 additions & 0 deletions DevProxy/config-templates/devproxyrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.2.0/rc.schema.json",
"plugins": [
],
"urlsToWatch": [
],
"logLevel": "information",
"newVersionNotification": "stable",
"showSkipMessages": true
}
8 changes: 8 additions & 0 deletions DevProxy/config-templates/devproxyrc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.2.0/rc.schema.json
plugins:
-
urlsToWatch:
-
Comment thread
waldekmastykarz marked this conversation as resolved.
logLevel: information
newVersionNotification: stable
showSkipMessages: true
Loading