Skip to content

Commit

Permalink
add end-to-end C# update runner (#10521)
Browse files Browse the repository at this point in the history
  • Loading branch information
brettfo authored Sep 26, 2024
1 parent 08f2675 commit ddb9722
Show file tree
Hide file tree
Showing 33 changed files with 1,311 additions and 29 deletions.
35 changes: 23 additions & 12 deletions nuget/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,49 @@ USER root

ENV DEPENDABOT_NATIVE_HELPERS_PATH="/opt"

# Install .NET SDK dependencies
# install dependencies
RUN source /etc/os-release \
&& curl --location --output /tmp/packages-microsoft-prod.deb "https://packages.microsoft.com/config/ubuntu/$VERSION_ID/packages-microsoft-prod.deb" \
&& dpkg -i /tmp/packages-microsoft-prod.deb \
&& rm /tmp/packages-microsoft-prod.deb
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
libicu-dev=70.1-2 \
&& rm -rf /var/lib/apt/lists/*
&& apt-get install -y --no-install-recommends \
jq \
libicu-dev=70.1-2 \
powershell \
&& rm -rf /var/lib/apt/lists/*

# Install .NET SDK
ARG DOTNET_SDK_VERSION=8.0.303
ARG DOTNET_SDK_INSTALL_URL=https://dot.net/v1/dotnet-install.sh
ENV DOTNET_INSTALL_DIR=/usr/local/dotnet/current
ENV DOTNET_INSTALL_SCRIPT_PATH=/tmp/dotnet-install.sh
ENV DOTNET_NOLOGO=true
ENV DOTNET_ROOT="${DOTNET_INSTALL_DIR}"
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true
ENV DOTNET_CLI_TELEMETRY_OPTOUT=true
ENV NUGET_SCRATCH=/opt/nuget/helpers/tmp

RUN cd /tmp \
&& curl --location --output dotnet-install.sh "${DOTNET_SDK_INSTALL_URL}" \
&& chmod +x dotnet-install.sh \
&& mkdir -p "${DOTNET_INSTALL_DIR}" \
&& ./dotnet-install.sh --version "${DOTNET_SDK_VERSION}" --install-dir "${DOTNET_INSTALL_DIR}" \
&& rm dotnet-install.sh \
&& chown -R dependabot:dependabot "${DOTNET_INSTALL_DIR}/sdk"

RUN curl --location --output "${DOTNET_INSTALL_SCRIPT_PATH}" "${DOTNET_SDK_INSTALL_URL}" \
&& chmod +x "${DOTNET_INSTALL_SCRIPT_PATH}" \
&& mkdir -p "${DOTNET_INSTALL_DIR}" \
&& "${DOTNET_INSTALL_SCRIPT_PATH}" --version "${DOTNET_SDK_VERSION}" --install-dir "${DOTNET_INSTALL_DIR}" \
&& chown -R dependabot:dependabot "$DOTNET_INSTALL_DIR"
ENV PATH="${PATH}:${DOTNET_INSTALL_DIR}"
RUN dotnet --list-runtimes
RUN dotnet --list-sdks

# build tools
USER dependabot
COPY --chown=dependabot:dependabot nuget/helpers /opt/nuget/helpers
RUN bash /opt/nuget/helpers/build

COPY --chown=dependabot:dependabot nuget $DEPENDABOT_HOME/nuget
COPY --chown=dependabot:dependabot common $DEPENDABOT_HOME/common
COPY --chown=dependabot:dependabot updater $DEPENDABOT_HOME/dependabot-updater

# redirect entrypoint
RUN mv bin/run bin/run-original
COPY --chown=dependabot:dependabot nuget/script/* $DEPENDABOT_HOME/dependabot-updater/bin/
COPY --chown=dependabot:dependabot nuget/updater/* $DEPENDABOT_HOME/dependabot-updater/bin/
RUN chmod +x $DEPENDABOT_HOME/dependabot-updater/bin/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
using System.Text;
using System.Text.Json;

using NuGetUpdater.Core.Run;
using NuGetUpdater.Core.Run.ApiModel;
using NuGetUpdater.Core.Test;
using NuGetUpdater.Core.Test.Update;

using Xunit;

namespace NuGetUpdater.Cli.Test;

using TestFile = (string Path, string Content);

public partial class EntryPointTests
{
public class Run
{
[Fact]
public async Task Run_Simple()
{
// verify we can pass command line arguments and hit the appropriate URLs
await RunAsync(
packages:
[
MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net8.0"),
MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.1", "net8.0"),
],
files:
[
("src/project.csproj", """
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Some.Package" Version="1.0.0" />
</ItemGroup>
</Project>
""")
],
job: new Job()
{
PackageManager = "nuget",
AllowedUpdates = [
new()
{
UpdateType = "all"
}
],
Source = new()
{
Provider = "github",
Repo = "test",
Directory = "src",
}
},
expectedUrls:
[
"/update_jobs/TEST-ID/update_dependency_list",
"/update_jobs/TEST-ID/increment_metric",
"/update_jobs/TEST-ID/create_pull_request",
"/update_jobs/TEST-ID/mark_as_processed",
]
);
}

private static async Task RunAsync(TestFile[] files, Job job, string[] expectedUrls, MockNuGetPackage[]? packages = null)
{
using var tempDirectory = new TemporaryDirectory();

// write test files
foreach (var testFile in files)
{
var fullPath = Path.Join(tempDirectory.DirectoryPath, testFile.Path);
var directory = Path.GetDirectoryName(fullPath)!;
Directory.CreateDirectory(directory);
await File.WriteAllTextAsync(fullPath, testFile.Content);
}

// write job file
var jobPath = Path.Combine(tempDirectory.DirectoryPath, "job.json");
await File.WriteAllTextAsync(jobPath, JsonSerializer.Serialize(new { Job = job }, RunWorker.SerializerOptions));

// save packages
await UpdateWorkerTestBase.MockNuGetPackagesInDirectory(packages, tempDirectory.DirectoryPath);

var actualUrls = new List<string>();
using var http = TestHttpServer.CreateTestStringServer(url =>
{
actualUrls.Add(new Uri(url).PathAndQuery);
return (200, "ok");
});
var args = new List<string>()
{
"run",
"--job-path",
jobPath,
"--repo-contents-path",
tempDirectory.DirectoryPath,
"--api-url",
http.BaseUrl,
"--job-id",
"TEST-ID",
"--output-path",
Path.Combine(tempDirectory.DirectoryPath, "output.json"),
"--base-commit-sha",
"BASE-COMMIT-SHA",
"--verbose"
};

var output = new StringBuilder();
// redirect stdout
var originalOut = Console.Out;
Console.SetOut(new StringWriter(output));
int result = -1;
try
{
result = await Program.Main(args.ToArray());
}
catch
{
// restore stdout
Console.SetOut(originalOut);
throw;
}

Assert.True(result == 0, output.ToString());
Assert.Equal(expectedUrls, actualUrls);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System.CommandLine;

using NuGetUpdater.Core;
using NuGetUpdater.Core.Run;

namespace NuGetUpdater.Cli.Commands;

internal static class RunCommand
{
internal static readonly Option<FileInfo> JobPathOption = new("--job-path") { IsRequired = true };
internal static readonly Option<DirectoryInfo> RepoContentsPathOption = new("--repo-contents-path") { IsRequired = true };
internal static readonly Option<Uri> ApiUrlOption = new("--api-url") { IsRequired = true };
internal static readonly Option<string> JobIdOption = new("--job-id") { IsRequired = true };
internal static readonly Option<FileInfo> OutputPathOption = new("--output-path") { IsRequired = true };
internal static readonly Option<string> BaseCommitShaOption = new("--base-commit-sha") { IsRequired = true };
internal static readonly Option<bool> VerboseOption = new("--verbose", getDefaultValue: () => false);

internal static Command GetCommand(Action<int> setExitCode)
{
Command command = new("run", "Runs a full dependabot job.")
{
JobPathOption,
RepoContentsPathOption,
ApiUrlOption,
JobIdOption,
OutputPathOption,
BaseCommitShaOption,
VerboseOption
};

command.TreatUnmatchedTokensAsErrors = true;

command.SetHandler(async (jobPath, repoContentsPath, apiUrl, jobId, outputPath, baseCommitSha, verbose) =>
{
var apiHandler = new HttpApiHandler(apiUrl.ToString(), jobId);
var worker = new RunWorker(apiHandler, new Logger(verbose));
await worker.RunAsync(jobPath, repoContentsPath, baseCommitSha, outputPath);
}, JobPathOption, RepoContentsPathOption, ApiUrlOption, JobIdOption, OutputPathOption, BaseCommitShaOption, VerboseOption);

return command;
}
}
1 change: 1 addition & 0 deletions nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ internal static async Task<int> Main(string[] args)
DiscoverCommand.GetCommand(setExitCode),
AnalyzeCommand.GetCommand(setExitCode),
UpdateCommand.GetCommand(setExitCode),
RunCommand.GetCommand(setExitCode),
};
command.TreatUnmatchedTokensAsErrors = true;

Expand Down
Loading

0 comments on commit ddb9722

Please sign in to comment.