diff --git a/.github/workflows/UploadDockerImage.yml b/.github/workflows/UploadDockerImage.yml new file mode 100644 index 000000000..5b66f9db0 --- /dev/null +++ b/.github/workflows/UploadDockerImage.yml @@ -0,0 +1,43 @@ +name: Upload Docker Images + +on: + # Manually trigger on specific branches + workflow_dispatch: + push: + branches: + - main + +permissions: + id-token: write + +jobs: + upload-docker-images: + runs-on: ubuntu-latest + steps: + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@8c3f20df09ac63af7b3ae3d7c91f105f857d8497 #v4 + with: + aws-region: us-west-2 + role-to-assume: ${{ secrets.DOCKER_IMAGE_UPLOADER_ROLE }} + role-duration-seconds: 1800 + + - name: Checkout Repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup .NET Core 6.0 + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 6.0.x + + - name: Restore dependencies + run: dotnet restore + + - name: Build + run: dotnet build --no-restore + + - name: Run Docker Image Uploader + run: | + cd ./src/AWS.Deploy.DockerImageUploader + dotnet run --project ./AWS.Deploy.DockerImageUploader.csproj \ No newline at end of file diff --git a/AWS.Deploy.sln b/AWS.Deploy.sln index 6540ad553..5c446ad04 100644 --- a/AWS.Deploy.sln +++ b/AWS.Deploy.sln @@ -67,6 +67,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AWS.Deploy.DocGenerator", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AWS.Deploy.DocGenerator.UnitTests", "test\AWS.Deploy.DocGenerator.UnitTests\AWS.Deploy.DocGenerator.UnitTests.csproj", "{7E661545-7DFD-4FE3-A5F9-767FAE30DFFE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AWS.Deploy.DockerImageUploader", "src\AWS.Deploy.DockerImageUploader\AWS.Deploy.DockerImageUploader.csproj", "{407D6B9B-E831-4DD2-9270-A7913A7A09D1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -173,6 +175,10 @@ Global {7E661545-7DFD-4FE3-A5F9-767FAE30DFFE}.Debug|Any CPU.Build.0 = Debug|Any CPU {7E661545-7DFD-4FE3-A5F9-767FAE30DFFE}.Release|Any CPU.ActiveCfg = Release|Any CPU {7E661545-7DFD-4FE3-A5F9-767FAE30DFFE}.Release|Any CPU.Build.0 = Release|Any CPU + {407D6B9B-E831-4DD2-9270-A7913A7A09D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {407D6B9B-E831-4DD2-9270-A7913A7A09D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {407D6B9B-E831-4DD2-9270-A7913A7A09D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {407D6B9B-E831-4DD2-9270-A7913A7A09D1}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -204,6 +210,7 @@ Global {CEEBEC39-40E5-4A9B-878A-6EDB52B9B43E} = {C3A0C716-BDEA-4393-B223-AF8F8531522A} {6D4BD0C2-C2A0-4AFB-BC22-623DD64A4F84} = {11C7056E-93C1-408B-BD87-5270595BBE0E} {7E661545-7DFD-4FE3-A5F9-767FAE30DFFE} = {BD466B5C-D8B0-4069-98A9-6DC8F01FA757} + {407D6B9B-E831-4DD2-9270-A7913A7A09D1} = {11C7056E-93C1-408B-BD87-5270595BBE0E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {5A4B2863-1763-4496-B122-651A38A4F5D7} diff --git a/src/AWS.Deploy.DockerImageUploader/AWS.Deploy.DockerImageUploader.csproj b/src/AWS.Deploy.DockerImageUploader/AWS.Deploy.DockerImageUploader.csproj new file mode 100644 index 000000000..41b04e51b --- /dev/null +++ b/src/AWS.Deploy.DockerImageUploader/AWS.Deploy.DockerImageUploader.csproj @@ -0,0 +1,13 @@ + + + + Exe + net6.0 + enable + + + + + + + diff --git a/src/AWS.Deploy.DockerImageUploader/App.cs b/src/AWS.Deploy.DockerImageUploader/App.cs new file mode 100644 index 000000000..29ba67b38 --- /dev/null +++ b/src/AWS.Deploy.DockerImageUploader/App.cs @@ -0,0 +1,72 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +using AWS.Deploy.Common.IO; +using AWS.Deploy.Common; +using Microsoft.Extensions.DependencyInjection; +using System.Reflection; +using System.Collections.Generic; +using System; +using System.Threading.Tasks; +using System.IO; + +namespace AWS.Deploy.DockerImageUploader +{ + public class App + { + private readonly IFileManager _fileManager; + private readonly IDirectoryManager _directoryManager; + private readonly IProjectDefinitionParser _projectDefinitionParser; + private readonly CLI.App _deployToolCli; + + private readonly List _testApps = new List { "WebApiNET6", "ConsoleAppTask" }; + + public App(IServiceProvider serviceProvider) + { + _projectDefinitionParser = serviceProvider.GetRequiredService(); + _fileManager = serviceProvider.GetRequiredService(); + _directoryManager = serviceProvider.GetRequiredService(); + _deployToolCli = serviceProvider.GetRequiredService(); + } + + public async Task Run(string[] args) + { + foreach (var testApp in _testApps) + { + var projectPath = ResolvePath(testApp); + await CreateImageAndPushToECR(projectPath); + } + } + + private async Task CreateImageAndPushToECR(string projectPath) + { + var projectDefinition = await _projectDefinitionParser.Parse(projectPath); + + var dockerEngine = new DockerEngine.DockerEngine(projectDefinition, _fileManager, _directoryManager); + + dockerEngine.GenerateDockerFile(); + + var configFilePath = Path.Combine(projectPath, "DockerImageUploaderConfigFile.json"); + + var deployArgs = new[] { "deploy", "--project-path", projectPath, "--diagnostics", "--apply", configFilePath, "--silent" }; + await _deployToolCli.Run(deployArgs); + } + + private string ResolvePath(string projectName) + { + const string srcDir = "src"; + var srcDirPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + while (srcDirPath != null && !string.Equals(new DirectoryInfo(srcDirPath).Name, srcDir, StringComparison.OrdinalIgnoreCase)) + { + srcDirPath = Directory.GetParent(srcDirPath)?.FullName; + } + + if (string.IsNullOrEmpty(srcDirPath)) + { + throw new Exception($"Failed to find path to '{srcDir}' directory."); + } + + return Path.Combine(srcDirPath, "..", "testapps", projectName); + } + } +} diff --git a/src/AWS.Deploy.DockerImageUploader/Program.cs b/src/AWS.Deploy.DockerImageUploader/Program.cs new file mode 100644 index 000000000..1240a7f29 --- /dev/null +++ b/src/AWS.Deploy.DockerImageUploader/Program.cs @@ -0,0 +1,32 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +using Microsoft.Extensions.DependencyInjection; +using AWS.Deploy.CLI.Extensions; +using System.Threading.Tasks; +using System; + +namespace AWS.Deploy.DockerImageUploader +{ + internal class Program + { + public static async Task Main(string[] args) + { + var serviceCollection = new ServiceCollection(); + + serviceCollection.AddCustomServices(); + serviceCollection.AddSingleton(); + + var serviceProvider = serviceCollection.BuildServiceProvider(); + + var app = serviceProvider.GetService(); + if (app == null) + { + throw new Exception("App dependencies aren't injected correctly." + + " Verify that all the required dependencies to instantiate DockerImageUploader are present."); + } + + await app.Run(args); + } + } +} diff --git a/testapps/ConsoleAppTask/DockerImageUploaderConfigFile.json b/testapps/ConsoleAppTask/DockerImageUploaderConfigFile.json new file mode 100644 index 000000000..fcc40ce0e --- /dev/null +++ b/testapps/ConsoleAppTask/DockerImageUploaderConfigFile.json @@ -0,0 +1,7 @@ +{ + "RecipeId": "PushContainerImageEcr", + "settings": { + "ImageTag": "latest", + "ECRRepositoryName": "deploytool-consoleapp" + } +} diff --git a/testapps/WebApiNET6/DockerImageUploaderConfigFile.json b/testapps/WebApiNET6/DockerImageUploaderConfigFile.json new file mode 100644 index 000000000..51d813572 --- /dev/null +++ b/testapps/WebApiNET6/DockerImageUploaderConfigFile.json @@ -0,0 +1,7 @@ +{ + "RecipeId": "PushContainerImageEcr", + "settings": { + "ImageTag": "latest", + "ECRRepositoryName": "deploytool-webapp" + } +}