From f343cab37533d74a06fd2b57557354b3ee8259a3 Mon Sep 17 00:00:00 2001 From: Margaret Date: Sat, 4 Mar 2023 16:34:11 -0500 Subject: [PATCH 01/33] Additional integration tests Fix missing FromQuery params Fix integration tests not using JSON datasource mocker --- .../Emissions/EmissionsCommandTests.cs | 20 +++ .../src/Controllers/CarbonAwareController.cs | 6 +- .../src/Models/CarbonIntensityDTO.cs | 6 +- .../CarbonAwareControllerTests.cs | 115 ++++++++++++++++-- .../IntegrationTestingBase.cs | 11 +- 5 files changed, 142 insertions(+), 16 deletions(-) diff --git a/src/CarbonAware.CLI/test/integrationTests/Commands/Emissions/EmissionsCommandTests.cs b/src/CarbonAware.CLI/test/integrationTests/Commands/Emissions/EmissionsCommandTests.cs index 9ce5f2e9c..cd9c7db3f 100644 --- a/src/CarbonAware.CLI/test/integrationTests/Commands/Emissions/EmissionsCommandTests.cs +++ b/src/CarbonAware.CLI/test/integrationTests/Commands/Emissions/EmissionsCommandTests.cs @@ -154,4 +154,24 @@ public async Task Emissions_AverageOption_ReturnsExpectedData() Assert.IsNotNull(firstResult["Duration"]); } + [Test] + public async Task Average_Best_ReturnsExpectedError() + { + // Arrange + var start = DateTimeOffset.Parse("2022-09-01T00:00:00Z"); + var end = DateTimeOffset.Parse("2022-09-01T03:00:00Z"); + var location = "eastus"; + _dataSourceMocker.SetupDataMock(start, end, location); + + // Act + var exitCode = await InvokeCliAsync($"emissions -l {location} -s 2022-09-01T02:01:00Z -e 2022-09-01T02:04:00Z -a -best"); + // Assert + Assert.AreEqual(1, exitCode); + var expectedError = "Options --average and --best cannot be used together Option '-s' expects a single argument but 2 were provided. "; + // Whitespace characters regex + var regex = @"\s+"; + var output = Regex.Replace(_console.Error.ToString()!, regex, " "); + + Assert.AreEqual(expectedError, output); + } } diff --git a/src/CarbonAware.WebApi/src/Controllers/CarbonAwareController.cs b/src/CarbonAware.WebApi/src/Controllers/CarbonAwareController.cs index 5d1de6074..d568cdc04 100644 --- a/src/CarbonAware.WebApi/src/Controllers/CarbonAwareController.cs +++ b/src/CarbonAware.WebApi/src/Controllers/CarbonAwareController.cs @@ -74,9 +74,9 @@ public async Task GetEmissionsDataForLocationsByTime([FromQuery] [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ValidationProblemDetails))] [HttpGet("bylocation")] public async Task GetEmissionsDataForLocationByTime( - [FromQuery, SwaggerParameter(Required = true)] string location, - DateTimeOffset? startTime = null, - DateTimeOffset? endTime = null) + [FromQuery, SwaggerParameter(Required = true)] string location, + [FromQuery(Name = "time")] DateTimeOffset? startTime = null, + [FromQuery(Name = "toTime")] DateTimeOffset? endTime = null) { var parameters = new EmissionsDataForLocationsParametersDTO { diff --git a/src/CarbonAware.WebApi/src/Models/CarbonIntensityDTO.cs b/src/CarbonAware.WebApi/src/Models/CarbonIntensityDTO.cs index bcaf7fccf..4396c9fbe 100644 --- a/src/CarbonAware.WebApi/src/Models/CarbonIntensityDTO.cs +++ b/src/CarbonAware.WebApi/src/Models/CarbonIntensityDTO.cs @@ -5,6 +5,8 @@ namespace CarbonAware.WebApi.Models; [Serializable] public record CarbonIntensityDTO { + private DateTimeOffset? _startTime; + private DateTimeOffset? _endTime; /// the location name where workflow is run /// eastus [JsonPropertyName("location")] @@ -13,12 +15,12 @@ public record CarbonIntensityDTO /// the time at which the workflow we are measuring carbon intensity for started /// 2022-03-01T15:30:00Z [JsonPropertyName("startTime")] - public DateTimeOffset? StartTime { get; set; } + public DateTimeOffset? StartTime { get => _startTime; set => _startTime = value?.ToUniversalTime(); } /// the time at which the workflow we are measuring carbon intensity for ended /// 2022-03-01T18:30:00Z [JsonPropertyName("endTime")] - public DateTimeOffset? EndTime { get; set; } + public DateTimeOffset? EndTime { get => _endTime; set => _endTime = value?.ToUniversalTime(); } /// Value of the marginal carbon intensity in grams per kilowatt-hour. /// 345.434 diff --git a/src/CarbonAware.WebApi/test/integrationTests/CarbonAwareControllerTests.cs b/src/CarbonAware.WebApi/test/integrationTests/CarbonAwareControllerTests.cs index e881c2230..95ade1e37 100644 --- a/src/CarbonAware.WebApi/test/integrationTests/CarbonAwareControllerTests.cs +++ b/src/CarbonAware.WebApi/test/integrationTests/CarbonAwareControllerTests.cs @@ -20,12 +20,13 @@ public class CarbonAwareControllerTests : IntegrationTestingBase private readonly string healthURI = "/health"; private readonly string fakeURI = "/fake-endpoint"; private readonly string bestLocationsURI = "/emissions/bylocations/best"; + private readonly string bylocationsURI = "/emissions/bylocations"; + private readonly string bylocationURI = "/emissions/bylocation"; private readonly string currentForecastURI = "/emissions/forecasts/current"; private readonly string batchForecastURI = "/emissions/forecasts/batch"; private readonly string averageCarbonIntensityURI = "/emissions/average-carbon-intensity"; private readonly string batchAverageCarbonIntensityURI = "/emissions/average-carbon-intensity/batch"; - public CarbonAwareControllerTests(DataSourceType dataSource) : base(dataSource) { } [Test] @@ -46,9 +47,89 @@ public async Task FakeEndPoint_ReturnsNotFound() } //ISO8601: YYYY-MM-DD - [TestCase("2022-1-1T04:05:06Z", "2022-1-2T04:05:06Z", "eastus")] - [TestCase("2021-12-25", "2021-12-26", "westus")] - public async Task BestLocations_ReturnsOK(DateTimeOffset start, DateTimeOffset end, string location) + [TestCase("2022-1-1T04:05:06Z", "2022-1-2T04:05:06Z", "eastus", nameof(ByLocationURI_ReturnsOK) + "0")] + [TestCase("2021-12-25T00:00:00+06:00", "2021-12-26T00:00:00+06:00", "westus", nameof(ByLocationURI_ReturnsOK) + "1")] + public async Task ByLocationURI_ReturnsOK(DateTimeOffset start, DateTimeOffset end, string location, string expectedResultName) + { + //Sets up any data endpoints needed for mocking purposes + _dataSourceMocker?.SetupDataMock(start, end, location); + + //Call the private method to construct with parameters + var queryStrings = new Dictionary(); + queryStrings["location"] = location; + queryStrings["time"] = $"{start:O}"; + queryStrings["toTime"] = $"{end:O}"; + + var endpointURI = ConstructUriWithQueryString(bylocationURI, queryStrings); + + //Get response and response content + var result = await _client.GetAsync(endpointURI); + + Assert.That(result, Is.Not.Null); + Assert.That(result.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + + [TestCase("location", "", TestName = "empty location query string")] + [TestCase("non-location-param", "", TestName = "location param not present")] + public async Task ByLocation_EmptyLocationQueryString_ReturnsBadRequest(string queryString, string value) + { + //Call the private method to construct with parameters + var queryStrings = new Dictionary(); + queryStrings[queryString] = value; + + var endpointURI = ConstructUriWithQueryString(bylocationURI, queryStrings); + + //Get response and response content + var result = await _client.GetAsync(endpointURI); + + Assert.That(result, Is.Not.Null); + Assert.That(result.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest)); + } + + //ISO8601: YYYY-MM-DD + [TestCase("2022-1-1T04:05:06Z", "2022-1-2T04:05:06Z", "eastus", nameof(ByLocationsURI_ReturnsOK) + "0")] + [TestCase("2021-12-25T00:00:00+06:00", "2021-12-26T00:00:00+06:00", "westus", nameof(ByLocationsURI_ReturnsOK) + "1")] + public async Task ByLocationsURI_ReturnsOK(DateTimeOffset start, DateTimeOffset end, string location, string expectedResultName) + { + //Sets up any data endpoints needed for mocking purposes + _dataSourceMocker?.SetupDataMock(start, end, location); + + //Call the private method to construct with parameters + var queryStrings = new Dictionary(); + queryStrings["location"] = location; + queryStrings["time"] = $"{start:O}"; + queryStrings["toTime"] = $"{end:O}"; + + var endpointURI = ConstructUriWithQueryString(bylocationsURI, queryStrings); + + //Get response and response content + var result = await _client.GetAsync(endpointURI); + + Assert.That(result, Is.Not.Null); + Assert.That(result.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + + [TestCase("location", "", TestName = "empty location query string")] + [TestCase("non-location-param", "", TestName = "location param not present")] + public async Task ByLocations_EmptyLocationQueryString_ReturnsBadRequest(string queryString, string value) + { + //Call the private method to construct with parameters + var queryStrings = new Dictionary(); + queryStrings[queryString] = value; + + var endpointURI = ConstructUriWithQueryString(bylocationsURI, queryStrings); + + //Get response and response content + var result = await _client.GetAsync(endpointURI); + + Assert.That(result, Is.Not.Null); + Assert.That(result.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest)); + } + + //ISO8601: YYYY-MM-DD + [TestCase("2022-1-1T04:05:06Z", "2022-1-2T04:05:06Z", "eastus", nameof(BestLocations_ReturnsOK) + "0")] + [TestCase("2021-12-25T00:00:00+06:00", "2021-12-26T00:00:00+06:00", "westus", nameof(BestLocations_ReturnsOK) + "1")] + public async Task BestLocations_ReturnsOK(DateTimeOffset start, DateTimeOffset end, string location, string expectedResultName) { //Sets up any data endpoints needed for mocking purposes _dataSourceMocker?.SetupDataMock(start, end, location); @@ -101,6 +182,20 @@ public async Task EmissionsForecastsCurrent_SupportedDataSources_ReturnsOk() var result = await _client.GetAsync(endpointURI); Assert.That(result, Is.Not.Null); Assert.That(result.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + using (var data = await result!.Content.ReadAsStreamAsync()) + { + Assert.That(data, Is.Not.Null); + var forecasts = await JsonSerializer.DeserializeAsync>(data); + Assert.That(forecasts, Is.Not.Null); + Assert.AreEqual(forecasts!.Count(), 1); + foreach (var forecast in forecasts!) + { + Assert.That(forecast.RequestedAt, Is.Not.Null); + Assert.That(forecast.GeneratedAt, Is.Not.Null); + Assert.That(forecast.OptimalDataPoints, Is.Not.Null); + Assert.That(forecast.ForecastData, Is.Not.Null); + } + } } [Test] @@ -204,9 +299,9 @@ public async Task EmissionsForecastsBatch_SupportedDataSources_ReturnsOk(string } } - [TestCase("2022-1-1T04:05:06Z", "2022-1-2T04:05:06Z", "eastus", TestName = "EmissionsMarginalCarbonIntensity expects OK for full datetime")] - [TestCase("2021-12-25", "2021-12-26", "westus", TestName = "EmissionsMarginalCarbonIntensity expects OK date only, no time")] - public async Task EmissionsMarginalCarbonIntensity_ReturnsOk(string start, string end, string location) + [TestCase("2022-1-1T04:05:06Z", "2022-1-2T04:05:06Z", "eastus", nameof(EmissionsMarginalCarbonIntensity_ReturnsOk) + "0", TestName = "EmissionsMarginalCarbonIntensity expects OK for full datetime")] + [TestCase("2021-12-25T00:00:00+06:00", "2021-12-26T00:00:00+06:00", "westus", nameof(EmissionsMarginalCarbonIntensity_ReturnsOk) + "1", TestName = "EmissionsMarginalCarbonIntensity expects OK date only, no time")] + public async Task EmissionsMarginalCarbonIntensity_ReturnsOk(string start, string end, string location, string expectedResultName) { var startDate = DateTimeOffset.Parse(start); var endDate = DateTimeOffset.Parse(end); @@ -268,9 +363,9 @@ public async Task EmissionsMarginalCarbonIntensityBatch_MissingRequiredParams_Re Assert.That(result!.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest)); } - [TestCase("2022-01-01T04:05:06Z", "2022-01-02T04:05:06Z", "eastus", 1, TestName = "EmissionsMarginalCarbonIntensityBatch expects OK for single element batch")] - [TestCase("2021-12-25", "2021-12-26", "westus", 3, TestName = "EmissionsMarginalCarbonIntensityBatch expects OK for multiple element batch")] - public async Task EmissionsMarginalCarbonIntensityBatch_SupportedDataSources_ReturnsOk(string start, string end, string location, int nelems) + [TestCase("2022-01-01T04:05:06Z", "2022-01-02T04:05:06Z", "eastus", 1, nameof(EmissionsMarginalCarbonIntensityBatch_SupportedDataSources_ReturnsOk) + "0", TestName = "EmissionsMarginalCarbonIntensityBatch expects OK for single element batch")] + [TestCase("2021-12-25T00:00:00+06:00", "2021-12-26T00:00:00+06:00", "westus", 3, nameof(EmissionsMarginalCarbonIntensityBatch_SupportedDataSources_ReturnsOk) + "1", TestName = "EmissionsMarginalCarbonIntensityBatch expects OK for multiple element batch")] + public async Task EmissionsMarginalCarbonIntensityBatch_SupportedDataSources_ReturnsOk(string start, string end, string location, int nelems, string expectedResultName) { var startDate = DateTimeOffset.Parse(start); var endDate = DateTimeOffset.Parse(end); diff --git a/src/CarbonAware.WebApi/test/integrationTests/IntegrationTestingBase.cs b/src/CarbonAware.WebApi/test/integrationTests/IntegrationTestingBase.cs index 152d65614..cb9e6b9f2 100644 --- a/src/CarbonAware.WebApi/test/integrationTests/IntegrationTestingBase.cs +++ b/src/CarbonAware.WebApi/test/integrationTests/IntegrationTestingBase.cs @@ -86,7 +86,7 @@ public void Setup() Environment.SetEnvironmentVariable("DataSources__EmissionsDataSource", "Json"); Environment.SetEnvironmentVariable("DataSources__ForecastDataSource", ""); Environment.SetEnvironmentVariable("DataSources__Configurations__Json__Type", "Json"); - Environment.SetEnvironmentVariable("DataSources__Configurations__Json__DataFileLocation", "demo.json"); + Environment.SetEnvironmentVariable("DataSources__Configurations__Json__DataFileLocation", "test-data-azure-emissions.json"); Environment.SetEnvironmentVariable("CarbonAwareVars__VerboseApi", "true"); _dataSourceMocker = new JsonDataSourceMocker(); break; @@ -127,6 +127,15 @@ public void Setup() [SetUp] public void SetupTests() { + if (_dataSource == DataSourceType.JSON) + { + // To force WebApplication to consume new JSON datasorce it needs to be restarted. + // This is a direct result of JSON caching in the CatbonAware code + _factory.Dispose(); + _factory = new WebApplicationFactory(); + _client = _factory.CreateClient(); + } + _dataSourceMocker?.Initialize(); } From 146165e915d4d1f394e7792dc0318433b63b5fac Mon Sep 17 00:00:00 2001 From: Margaret Date: Sat, 4 Mar 2023 16:43:56 -0500 Subject: [PATCH 02/33] DCO Remediation Commit for Margaret I, Margaret , hereby add my Signed-off-by to this commit: f881406a8674645a96d05af2c520dd89f36d7c4f I, Margaret , hereby add my Signed-off-by to this commit: f343cab37533d74a06fd2b57557354b3ee8259a3 Signed-off-by: Margaret --- .../test/integrationTests/CarbonAwareControllerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CarbonAware.WebApi/test/integrationTests/CarbonAwareControllerTests.cs b/src/CarbonAware.WebApi/test/integrationTests/CarbonAwareControllerTests.cs index 95ade1e37..5323491c0 100644 --- a/src/CarbonAware.WebApi/test/integrationTests/CarbonAwareControllerTests.cs +++ b/src/CarbonAware.WebApi/test/integrationTests/CarbonAwareControllerTests.cs @@ -372,7 +372,7 @@ public async Task EmissionsMarginalCarbonIntensityBatch_SupportedDataSources_Ret _dataSourceMocker?.SetupDataMock(startDate, endDate, location); var intesityData = Enumerable.Range(0, nelems).Select(x => new { - location = location, + location, startTime = start, endTime = end }); From 36a3d8458eeb27fb14c66ce95c07368b00230b11 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Thu, 27 Apr 2023 10:12:16 +0900 Subject: [PATCH 03/33] Add 4-release.yaml Signed-off-by: Yasumasa Suenaga --- .github/workflows/4-release.yaml | 43 ++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/4-release.yaml diff --git a/.github/workflows/4-release.yaml b/.github/workflows/4-release.yaml new file mode 100644 index 000000000..b4eaa34d1 --- /dev/null +++ b/.github/workflows/4-release.yaml @@ -0,0 +1,43 @@ +name: Publish container image to GitHub Packages + +on: + release: + types: [published] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + publish-container-image: + runs-on: ubuntu-latest + permissions: + packages: write + steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Log in to the Container registry + uses: docker/login-action@v2.1.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ github.token }} + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4.3.0 + with: + flavor: latest=true + tags: type=raw,value=${{ github.ref_name }} + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + - name: Build and push Docker image + uses: docker/build-push-action@v4.0.0 + with: + context: "{{defaultContext}}:src" + file: CarbonAware.WebApi/src/Dockerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + provenance: false From b9067cc259e7ff87b5717034a395fe04305b7c9b Mon Sep 17 00:00:00 2001 From: Dan Benitah Date: Tue, 11 Jul 2023 07:38:14 +0100 Subject: [PATCH 04/33] Devops/clean up workflows (#361) * cleaning workflows Signed-off-by: Dan Benitah * pull request should on trigger for pull request event - removing on push for PRs Signed-off-by: Dan Benitah * syntax Signed-off-by: Dan Benitah * syntax Signed-off-by: Dan Benitah * moving markdown linting and disabling 2.a-deploy Signed-off-by: Dan Benitah * adding some jobs dependencies so packaging does not run if code does not build etc... Signed-off-by: Dan Benitah * moving code analysis into the build step and clean up Signed-off-by: Dan Benitah --------- Signed-off-by: Dan Benitah Co-authored-by: danuw --- .github/workflows/{stale.yml => 0-stale.yml} | 2 +- .github/workflows/1-pr.yaml | 247 ++++++++++++++++++ .github/workflows/2-pre-release.yaml | 2 +- .github/workflows/2.a-deploy.yaml | 42 +++ .github/workflows/build-cli-dotnet.yaml | 34 --- .github/workflows/build-packages.yaml | 56 ---- .github/workflows/build-webapi.yaml | 125 --------- .github/workflows/codeQL-analysis.yaml | 81 ------ .github/workflows/dev_carbon-aware-api.yml | 2 +- .github/workflows/linting.yaml | 35 --- .github/workflows/run-sdkCLI-githubaction.yml | 48 ++-- 11 files changed, 316 insertions(+), 358 deletions(-) rename .github/workflows/{stale.yml => 0-stale.yml} (97%) create mode 100644 .github/workflows/1-pr.yaml create mode 100644 .github/workflows/2.a-deploy.yaml delete mode 100644 .github/workflows/build-cli-dotnet.yaml delete mode 100644 .github/workflows/build-packages.yaml delete mode 100644 .github/workflows/build-webapi.yaml delete mode 100644 .github/workflows/codeQL-analysis.yaml delete mode 100644 .github/workflows/linting.yaml diff --git a/.github/workflows/stale.yml b/.github/workflows/0-stale.yml similarity index 97% rename from .github/workflows/stale.yml rename to .github/workflows/0-stale.yml index 8d284a327..e06fa67b1 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/0-stale.yml @@ -3,7 +3,7 @@ # You can adjust the behavior by modifying this file. # For more information, see: # https://github.com/actions/stale -name: Mark stale issues and pull requests +name: 0-Mark stale issues and pull requests on: schedule: diff --git a/.github/workflows/1-pr.yaml b/.github/workflows/1-pr.yaml new file mode 100644 index 000000000..c6d8f9f44 --- /dev/null +++ b/.github/workflows/1-pr.yaml @@ -0,0 +1,247 @@ +name: 1-PR checks +on: + pull_request: + branches: [ dev, main ] + workflow_dispatch: + +env: + # web app + DOCKERFILE_PATH: "CarbonAware.WebApi/src/Dockerfile" + HEALTH_ENDPOINT: "0.0.0.0:8080/health" + DLL_FILE_PATH: "./bin/Release/net6.0/CarbonAware.WebApi.dll" + DOTNET_SRC_DIR: "./src" + # console app packages + DOTNET_SOLUTION: "src/GSF.CarbonAware/src/GSF.CarbonAware.csproj" + OUTPUT_DIR: "packages" + CONSOLE_APP: "samples/lib-integration/ConsoleApp/ConsoleApp.csproj" + CREATE_PKGS: "scripts/package/create_packages.ps1" + ADD_PKGS: "scripts/package/add_packages.ps1" + + +jobs: + sln-build-and-test: + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'csharp' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://git.io/codeql-language-support + + defaults: + run: + working-directory: ./src + steps: + + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 6.0.x + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + - name: Restore dependencies + run: dotnet restore + + - name: Build + run: dotnet build --no-restore + + - name: Unit Tests + run: dotnet test --no-build --verbosity normal + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + #- name: Autobuild + # uses: github/codeql-action/autobuild@v2 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + + webapp-container-dotnet-build: + needs: sln-build-and-test + runs-on: ubuntu-latest + container: + image: mcr.microsoft.com/dotnet/sdk:6.0 + steps: + - uses: actions/checkout@v3 + + - name: Setup .NET Core SDK 6 + uses: actions/setup-dotnet@v2 + with: + dotnet-version: '6.0.x' + include-prerelease: false + + - name: Install dependencies + run: dotnet restore + working-directory: ${{ env.DOTNET_SRC_DIR }} + + - name: Install tools + run: dotnet tool restore + working-directory: ${{ env.DOTNET_SRC_DIR }}/CarbonAware.WebApi/src + + - name: Build + run: dotnet build --configuration Release --no-restore + working-directory: ${{ env.DOTNET_SRC_DIR }} + + - name: Unit Test + Code Coverage + run: dotnet test --filter TestCategory=Unit --no-restore --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=json + working-directory: ${{ env.DOTNET_SRC_DIR }} + + - name: Integration Test + Code Coverage + run: dotnet test --filter TestCategory=Integration --no-restore --verbosity normal /p:CollectCoverage=true /p:MergeWith=\"./coverage.json\" /p:CoverletOutputFormat=\"json,opencover\" + working-directory: ${{ env.DOTNET_SRC_DIR }} + + - name: Codecov + uses: codecov/codecov-action@v2 + with: + directory: ${{ env.DOTNET_SRC_DIR }} + + - name: Generate Open API + run: dotnet tool run swagger tofile --output ./wwwroot/api/v1/swagger.yaml --yaml ${{ env.DLL_FILE_PATH }} v1 + working-directory: ./src/CarbonAware.WebApi/src + + - name: Upload swagger artifact + uses: actions/upload-artifact@v1 + with: + name: pr-swagger.yaml + path: src/CarbonAware.WebApi/src/wwwroot/api/v1/swagger.yaml + + webapp-container-validation: + needs: sln-build-and-test + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Docker Target Final + run: docker build . -f ${DOCKERFILE_PATH} -t ca-api + working-directory: ./src + + - name: Docker Run Container + run: | + docker run -d --name runnable-container -p 8080:80 ca-api + docker container ls + + - name: Docker WGET Health Endpoint + run: | + wget -t 5 --waitretry=5 ${HEALTH_ENDPOINT} + + api-comparison: + needs: webapp-container-dotnet-build + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./src/CarbonAware.WebApi/src + container: + image: mcr.microsoft.com/dotnet/sdk + steps: + - name: Checkout Dev Branch + uses: actions/checkout@v3 + with: + ref: dev + - name: Setup .NET Core SDK 6 + uses: actions/setup-dotnet@v2 + with: + dotnet-version: '6.0.x' + include-prerelease: false + - name: Install dependencies + run: dotnet restore + working-directory: ${{ env.DOTNET_SRC_DIR }} + - name: Install tools + run: dotnet tool restore + - name: Build + run: dotnet build --configuration Release --no-restore + working-directory: ${{ env.DOTNET_SRC_DIR }} + - name: Generate Open API + run: dotnet tool run swagger tofile --output ./wwwroot/api/v1/swagger.yaml --yaml ${{ env.DLL_FILE_PATH }} v1 + - name: Upload dev artifact + uses: actions/upload-artifact@v1 + with: + name: dev-swagger.yaml + path: src/CarbonAware.WebApi/src/wwwroot/api/v1/swagger.yaml + - uses: actions/download-artifact@v3 + with: + name: pr-swagger.yaml + path: ./src/CarbonAware.WebApi/src/wwwroot/api/v1/pr-swagger.yaml + - name: API Diff Comparison + run: | + diff ./wwwroot/api/v1/pr-swagger.yaml ./wwwroot/api/v1/swagger.yaml && echo "No API Changes detected" || echo "::warning:: API Changed" + + dotnet-pack: + needs: sln-build-and-test + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup .NET Core SDK 6 + uses: actions/setup-dotnet@v2 + with: + dotnet-version: '6.0.x' + include-prerelease: false + + - name: Create packages + shell: pwsh + run: ${{ env.CREATE_PKGS }} ${{ env.DOTNET_SOLUTION }} ${{ env.OUTPUT_DIR }} + + - name: Restore current packages for ConsoleApp + run: dotnet restore ${{ env.CONSOLE_APP }} + + - name: Add packages to ConsoleApp + shell: pwsh + run: ${{ env.ADD_PKGS }} ${{ env.CONSOLE_APP}} ${{ env.OUTPUT_DIR }} + + - name: Cat ConsoleApp project file + run: cat ${{ env.CONSOLE_APP }} + + - name: Restore packages for ConsoleApp + run: dotnet restore ${{ env.CONSOLE_APP }} + + - name: Build ConsoleApp + run: dotnet build ${{ env.CONSOLE_APP }} + + # Non-blocking job that checks .md file locations and also lints them + markdown-linting: + runs-on: ubuntu-latest + steps: + - name: Check out the code + uses: actions/checkout@v2 + + # See the script for details about exceptions to this check + - name: Markdown files should be located in docs folder + continue-on-error: true + run: "scripts/markdown/check-markdown-files.sh" + + - name: markdownlint-cli2-action + uses: DavidAnson/markdownlint-cli2-action@v9 + continue-on-error: true + with: + command: config + globs: | + ./custom.markdownlint.jsonc + {"*[^.github]/**,*"}.md \ No newline at end of file diff --git a/.github/workflows/2-pre-release.yaml b/.github/workflows/2-pre-release.yaml index b04b85ec1..11f07d5f0 100644 --- a/.github/workflows/2-pre-release.yaml +++ b/.github/workflows/2-pre-release.yaml @@ -1,4 +1,4 @@ -name: Publish container image to GitHub Packages +name: 2-Publish container image to GitHub Packages on: push: diff --git a/.github/workflows/2.a-deploy.yaml b/.github/workflows/2.a-deploy.yaml new file mode 100644 index 000000000..28068412d --- /dev/null +++ b/.github/workflows/2.a-deploy.yaml @@ -0,0 +1,42 @@ +# # Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy +# # More GitHub Actions for Azure: https://github.com/Azure/actions + +# name: 2.a-Deploy Container to Azure Web App - carbon-aware-api + +# # Check what scenario we are in +# # If push to dev, deploy latest pre image + +# # TODO: +# # - add how to get the latest pre package +# # - test? +# # - deploy (existing code to use new image instead of what would have come from build step) + +# on: +# push: +# branches: +# - dev +# workflow_dispatch: + +# jobs: +# deploy: +# runs-on: ubuntu-latest +# permissions: +# packages: read +# environment: +# name: 'Production' +# url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} + +# steps: +# - name: Download artifact from build job +# uses: actions/download-artifact@v2 +# with: +# name: CarbonAwareApi + +# - name: Deploy to Azure Web App +# id: deploy-to-webapp +# uses: azure/webapps-deploy@v2 +# with: +# app-name: 'carbon-aware-api' +# slot-name: 'Production' +# publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_D9BE266F4F034E79818711107BC7DDC5 }} +# package: . \ No newline at end of file diff --git a/.github/workflows/build-cli-dotnet.yaml b/.github/workflows/build-cli-dotnet.yaml deleted file mode 100644 index 86e667aba..000000000 --- a/.github/workflows/build-cli-dotnet.yaml +++ /dev/null @@ -1,34 +0,0 @@ -name: BUILD CLI in DOTNET - -on: - push: - paths: - - 'src/**' - - '.github/workflows/**' - pull_request: - branches: [ dev, main ] - paths: - - 'src/**' - -jobs: - build: - runs-on: ubuntu-latest - defaults: - run: - working-directory: ./src - steps: - - - uses: actions/checkout@v2 - - name: Setup .NET - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 6.0.x - - - name: Restore dependencies - run: dotnet restore - - - name: Build - run: dotnet build --no-restore - - - name: Unit Tests - run: dotnet test --no-build --verbosity normal \ No newline at end of file diff --git a/.github/workflows/build-packages.yaml b/.github/workflows/build-packages.yaml deleted file mode 100644 index 8d195e05f..000000000 --- a/.github/workflows/build-packages.yaml +++ /dev/null @@ -1,56 +0,0 @@ -name: Build and Install GSF Packages on Sample ConsoleApp - -on: - push: - branches: [ dev, main ] - pull_request: - branches: [ dev, main ] - paths: - - 'src/**' - - '.github/workflows/**' - - 'samples/lib-integration/ConsoleApp/**' - - 'scripts/package/**' - -env: - DOTNET_SOLUTION: "src/GSF.CarbonAware/src/GSF.CarbonAware.csproj" - OUTPUT_DIR: "packages" - CONSOLE_APP: "samples/lib-integration/ConsoleApp/ConsoleApp.csproj" - CREATE_PKGS: "scripts/package/create_packages.ps1" - ADD_PKGS: "scripts/package/add_packages.ps1" - -jobs: - dotnet-pack: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup .NET Core SDK 6 - uses: actions/setup-dotnet@v2 - with: - dotnet-version: '6.0.x' - include-prerelease: false - - - name: Create packages - shell: pwsh - run: ${{ env.CREATE_PKGS }} ${{ env.DOTNET_SOLUTION }} ${{ env.OUTPUT_DIR }} - - - name: Restore current packages for ConsoleApp - run: dotnet restore ${{ env.CONSOLE_APP }} - - - name: Add packages to ConsoleApp - shell: pwsh - run: ${{ env.ADD_PKGS }} ${{ env.CONSOLE_APP}} ${{ env.OUTPUT_DIR }} - - - name: Cat ConsoleApp project file - run: cat ${{ env.CONSOLE_APP }} - - - name: Restore packages for ConsoleApp - run: dotnet restore ${{ env.CONSOLE_APP }} - - - name: Build ConsoleApp - run: dotnet build ${{ env.CONSOLE_APP }} - - - name: Run ConsoleApp - run: dotnet run --project ${{ env.CONSOLE_APP }} - diff --git a/.github/workflows/build-webapi.yaml b/.github/workflows/build-webapi.yaml deleted file mode 100644 index 2171b6b1d..000000000 --- a/.github/workflows/build-webapi.yaml +++ /dev/null @@ -1,125 +0,0 @@ -name: Docker Web API Build - -on: - push: - branches: [ dev, main ] - pull_request: - branches: [ dev, main ] - paths: - - 'src/**' - - '.github/workflows/**' - -env: - DOCKERFILE_PATH: "CarbonAware.WebApi/src/Dockerfile" - HEALTH_ENDPOINT: "0.0.0.0:8080/health" - DLL_FILE_PATH: "./bin/Release/net6.0/CarbonAware.WebApi.dll" - DOTNET_SRC_DIR: "./src" - -jobs: - container-dotnet-build: - runs-on: ubuntu-latest - container: - image: mcr.microsoft.com/dotnet/sdk:6.0 - steps: - - uses: actions/checkout@v3 - - - name: Setup .NET Core SDK 6 - uses: actions/setup-dotnet@v2 - with: - dotnet-version: '6.0.x' - include-prerelease: false - - - name: Install dependencies - run: dotnet restore - working-directory: ${{ env.DOTNET_SRC_DIR }} - - - name: Install tools - run: dotnet tool restore - working-directory: ${{ env.DOTNET_SRC_DIR }}/CarbonAware.WebApi/src - - - name: Build - run: dotnet build --configuration Release --no-restore - working-directory: ${{ env.DOTNET_SRC_DIR }} - - - name: Unit Test + Code Coverage - run: dotnet test --filter TestCategory=Unit --no-restore --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=json - working-directory: ${{ env.DOTNET_SRC_DIR }} - - - name: Integration Test + Code Coverage - run: dotnet test --filter TestCategory=Integration --no-restore --verbosity normal /p:CollectCoverage=true /p:MergeWith=\"./coverage.json\" /p:CoverletOutputFormat=\"json,opencover\" - working-directory: ${{ env.DOTNET_SRC_DIR }} - - - name: Codecov - uses: codecov/codecov-action@v2 - with: - directory: ${{ env.DOTNET_SRC_DIR }} - - - name: Generate Open API - run: dotnet tool run swagger tofile --output ./wwwroot/api/v1/swagger.yaml --yaml ${{ env.DLL_FILE_PATH }} v1 - working-directory: ./src/CarbonAware.WebApi/src - - - name: Upload artifact - uses: actions/upload-artifact@v1 - with: - name: pr-swagger.yaml - path: src/CarbonAware.WebApi/src/wwwroot/api/v1/swagger.yaml - - container-validation: - runs-on: ubuntu-latest - steps: - - name: Checkout Repository - uses: actions/checkout@v2 - - - name: Docker Target Final - run: docker build . -f ${DOCKERFILE_PATH} -t ca-api - working-directory: ./src - - - name: Docker Run Container - run: | - docker run -d --name runnable-container -p 8080:80 ca-api - docker container ls - - - name: Docker WGET Health Endpoint - run: | - wget -t 5 --waitretry=5 ${HEALTH_ENDPOINT} - -# api-comparison: -# needs: container-dotnet-build -# runs-on: ubuntu-latest -# defaults: -# run: -# working-directory: ./src/CarbonAware.WebApi/src -# container: -# image: mcr.microsoft.com/dotnet/sdk -# steps: -# - name: Checkout Dev Branch -# uses: actions/checkout@v3 -# with: -# ref: dev -# - name: Setup .NET Core SDK 6 -# uses: actions/setup-dotnet@v2 -# with: -# dotnet-version: '6.0.x' -# include-prerelease: false -# - name: Install dependencies -# run: dotnet restore -# working-directory: ${{ env.DOTNET_SRC_DIR }} -# - name: Install tools -# run: dotnet tool restore -# - name: Build -# run: dotnet build --configuration Release --no-restore -# working-directory: ${{ env.DOTNET_SRC_DIR }} -# - name: Generate Open API -# run: dotnet tool run swagger tofile --output ./wwwroot/api/v1/swagger.yaml --yaml ${{ env.DLL_FILE_PATH }} v1 -# - name: Upload dev artifact -# uses: actions/upload-artifact@v1 -# with: -# name: dev-swagger.yaml -# path: src/CarbonAware.WebApi/src/wwwroot/api/v1/swagger.yaml -# - uses: actions/download-artifact@v3 -# with: -# name: pr-swagger.yaml -# path: ./src/CarbonAware.WebApi/src/wwwroot/api/v1/pr-swagger.yaml -# - name: API Diff Comparison -# run: | -# diff ./wwwroot/api/v1/pr-swagger.yaml ./wwwroot/api/v1/swagger.yaml && echo "No API Changes detected" || echo "::warning:: API Changed" diff --git a/.github/workflows/codeQL-analysis.yaml b/.github/workflows/codeQL-analysis.yaml deleted file mode 100644 index 7624b0f52..000000000 --- a/.github/workflows/codeQL-analysis.yaml +++ /dev/null @@ -1,81 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "Code Security Scan with CodeQL" - -on: - push: - pull_request: - # The branches below must be a subset of the branches above - branches: [ dev, main ] - schedule: - - cron: '42 23 * * 5' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'csharp' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Learn more about CodeQL language support at https://git.io/codeql-language-support - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - - - name: Setup .NET - uses: actions/setup-dotnet@v1 - with: - dotnet-version: '6.0' - - - name: Restore dependencies - run: dotnet restore - working-directory: './src/' - - name: Build - run: dotnet build --no-restore - working-directory: './src/' - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - #- name: Autobuild - # uses: github/codeql-action/autobuild@v2 - - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/dev_carbon-aware-api.yml b/.github/workflows/dev_carbon-aware-api.yml index 9eb8aba88..fc3dc2494 100644 --- a/.github/workflows/dev_carbon-aware-api.yml +++ b/.github/workflows/dev_carbon-aware-api.yml @@ -1,7 +1,7 @@ # Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy # More GitHub Actions for Azure: https://github.com/Azure/actions -name: Build and deploy ASP.Net Core app to Azure Web App - carbon-aware-api +name: 2.a-Build and deploy ASP.Net Core app to Azure Web App - carbon-aware-api on: push: diff --git a/.github/workflows/linting.yaml b/.github/workflows/linting.yaml deleted file mode 100644 index dbf6e651a..000000000 --- a/.github/workflows/linting.yaml +++ /dev/null @@ -1,35 +0,0 @@ -name: "Linting" - -on: - push: - paths: - - './**' - - '.github/workflows/**' - pull_request: - branches: [ dev, main ] - paths: - - './**' - -jobs: - # Non-blocking job that checks .md file locations and also lints them - markdown: - runs-on: ubuntu-latest - steps: - - name: Check out the code - uses: actions/checkout@v2 - - # See the script for details about exceptions to this check - - name: Markdown files should be located in docs folder - continue-on-error: true - run: "scripts/markdown/check-markdown-files.sh" - - - name: markdownlint-cli2-action - uses: DavidAnson/markdownlint-cli2-action@v9 - continue-on-error: true - with: - command: config - globs: | - ./custom.markdownlint.jsonc - {"*[^.github]/**,*"}.md - - diff --git a/.github/workflows/run-sdkCLI-githubaction.yml b/.github/workflows/run-sdkCLI-githubaction.yml index 76d4687fc..8cf1d34a8 100644 --- a/.github/workflows/run-sdkCLI-githubaction.yml +++ b/.github/workflows/run-sdkCLI-githubaction.yml @@ -1,28 +1,28 @@ -name: using CarboneAware Github action in sample pipeline +# name: using CarboneAware Github action in sample pipeline -on: - push: - paths: - - 'src/**' - - '.github/workflows/**' - pull_request: - branches: [ dev, main ] - paths: - - 'src/**' +# on: +# push: +# paths: +# - 'src/**' +# - '.github/workflows/**' +# pull_request: +# branches: [ dev, main ] +# paths: +# - 'src/**' -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: CarboneAWare metrics - id: carboneaware-metrics - uses: Green-Software-Foundation/carbon-aware-sdk@sdkCLI-githubaction # here "sdkCLI-githubaction" is the name of the branch - with: - location: westeurope,francecentral,westus - #config: /carbon-aware.json - #fromTime: - #toTime: +# jobs: +# build: +# runs-on: ubuntu-latest +# steps: +# - name: CarboneAWare metrics +# id: carboneaware-metrics +# uses: Green-Software-Foundation/carbon-aware-sdk@sdkCLI-githubaction # here "sdkCLI-githubaction" is the name of the branch +# with: +# location: westeurope,francecentral,westus +# #config: /carbon-aware.json +# #fromTime: +# #toTime: - - name: Deplpoy Workload to Selected Region - run: echo deploying ML Training Job to Region "${{ steps.carboneaware-metrics.outputs.LowestEmissionsLocation}}" +# - name: Deplpoy Workload to Selected Region +# run: echo deploying ML Training Job to Region "${{ steps.carboneaware-metrics.outputs.LowestEmissionsLocation}}" From 9768b101e70e9f733fe6b556ff3a0ba469b60880 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Tue, 11 Jul 2023 15:40:10 +0900 Subject: [PATCH 05/33] Skip deploy workflows in forked repos (#347) * Skip deploy workflows in forked repos Signed-off-by: Yasumasa Suenaga * Add vars Signed-off-by: Yasumasa Suenaga --------- Signed-off-by: Yasumasa Suenaga --- .github/workflows/2-pre-release.yaml | 1 + .github/workflows/dev_carbon-aware-api.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/2-pre-release.yaml b/.github/workflows/2-pre-release.yaml index 11f07d5f0..ddd6afe72 100644 --- a/.github/workflows/2-pre-release.yaml +++ b/.github/workflows/2-pre-release.yaml @@ -18,6 +18,7 @@ concurrency: jobs: publish-container-image: + if: github.repository == 'Green-Software-Foundation/carbon-aware-sdk' || vars.ENABLE_PRERELEASE_WORKFLOW == 'true' runs-on: ubuntu-latest permissions: packages: write diff --git a/.github/workflows/dev_carbon-aware-api.yml b/.github/workflows/dev_carbon-aware-api.yml index fc3dc2494..643d58b8d 100644 --- a/.github/workflows/dev_carbon-aware-api.yml +++ b/.github/workflows/dev_carbon-aware-api.yml @@ -11,6 +11,7 @@ on: jobs: build: + if: github.repository == 'Green-Software-Foundation/carbon-aware-sdk' || vars.ENABLE_WEBAPP_WORKFLOW == 'true' runs-on: windows-latest steps: From 5347db68641c28242832d5939990fbd9512fda93 Mon Sep 17 00:00:00 2001 From: Roman Lutz Date: Tue, 18 Jul 2023 15:16:58 -0400 Subject: [PATCH 06/33] fix typos Signed-off-by: Roman Lutz --- docs/architecture/decisions/0010-sdk-packaging.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/architecture/decisions/0010-sdk-packaging.md b/docs/architecture/decisions/0010-sdk-packaging.md index e16a8dbe8..105f6c987 100644 --- a/docs/architecture/decisions/0010-sdk-packaging.md +++ b/docs/architecture/decisions/0010-sdk-packaging.md @@ -11,8 +11,8 @@ Accepted ## Context Current GSF CarbonAware software can't be consumed as -[Nuget](https://www.nuget.org) Packages in case there is an application that -requires to integrate with it. There are scenerarios where the current runtimes +[Nuget](https://www.nuget.org) packages in case there is an application that +requires to integrate with it. There are scenarios where the current runtimes (CLI/WebApi) environments are not allowed to be used since all the functionality requires to be bundled together. The goal of this proposal is to show that the current GSF repository can provide a mechanism to generate `Nuget` packages that @@ -21,7 +21,7 @@ can be consumed by any application that wants to integrate with ## Decision -Having nuget packages available to be consumed by 3rd party application would +Having Nuget packages available to be consumed by 3rd party application would help to integrate easily and it would open the possibilities to extend the SDK more. Currently there are seven (7) `dotnet` projects that can be set to be packaged with tools like `dotnet pack` or `msbuild -t:pack`. @@ -37,7 +37,7 @@ packaged with tools like `dotnet pack` or `msbuild -t:pack`. | CarbonAware.LocationSources | | CarbonAware.Tools.WattTimeClient | -**[Must Address]** Creation of a minimum set of packages that can be integrate +**[Must Address]** Creation of a minimum set of packages that can be integrated with a 3rd party application. - Continues enhancing the SDK to support integration with different type of From e697984cd38adb80d8e41e30edf4f6f0a4c127c7 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Sat, 5 Aug 2023 23:16:39 +0900 Subject: [PATCH 07/33] Add Helm chart and workflow Signed-off-by: Yasumasa Suenaga --- .github/workflows/publish-helm-chart.yaml | 40 +++ .../decisions/0004-documentation.md | 2 - docs/overview.md | 117 +++++++++ .../helmexample => helm-chart}/.helmignore | 0 .../helmexample => helm-chart}/Chart.yaml | 8 +- .../templates/NOTES.txt | 8 +- .../templates/_helpers.tpl | 20 +- .../templates/deployment.yaml | 31 ++- .../templates/hpa.yaml | 7 +- .../templates/ingress.yaml | 10 +- helm-chart/templates/secret.yaml | 10 + .../templates/service.yaml | 7 +- .../templates/tests/test-connection.yaml | 14 ++ .../helmexample => helm-chart}/values.yaml | 76 +++--- samples/helmexample/README.md | 231 ------------------ .../helmexample/templates/serviceaccount.yaml | 12 - .../templates/tests/test-connection.yaml | 15 -- 17 files changed, 269 insertions(+), 339 deletions(-) create mode 100644 .github/workflows/publish-helm-chart.yaml rename {samples/helmexample => helm-chart}/.helmignore (100%) rename {samples/helmexample => helm-chart}/Chart.yaml (90%) rename {samples/helmexample => helm-chart}/templates/NOTES.txt (75%) rename {samples/helmexample => helm-chart}/templates/_helpers.tpl (72%) rename {samples/helmexample => helm-chart}/templates/deployment.yaml (64%) rename {samples/helmexample => helm-chart}/templates/hpa.yaml (83%) rename {samples/helmexample => helm-chart}/templates/ingress.yaml (89%) create mode 100644 helm-chart/templates/secret.yaml rename {samples/helmexample => helm-chart}/templates/service.yaml (53%) create mode 100644 helm-chart/templates/tests/test-connection.yaml rename {samples/helmexample => helm-chart}/values.yaml (53%) delete mode 100644 samples/helmexample/README.md delete mode 100644 samples/helmexample/templates/serviceaccount.yaml delete mode 100644 samples/helmexample/templates/tests/test-connection.yaml diff --git a/.github/workflows/publish-helm-chart.yaml b/.github/workflows/publish-helm-chart.yaml new file mode 100644 index 000000000..84bbfb1ab --- /dev/null +++ b/.github/workflows/publish-helm-chart.yaml @@ -0,0 +1,40 @@ +name: Publish Helm chart + +on: + workflow_dispatch: + +concurrency: + group: publish-helm-chart + cancel-in-progress: true + +jobs: + push-helm-charts: + if: github.repository == 'Green-Software-Foundation/carbon-aware-sdk' || vars.ENABLE_HELM_WORKFLOW == 'true' + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Detect Helm chart version + run: | + CHART_VERSION=`yq .version helm-chart/Chart.yaml` + echo "CHART_VERSION=$CHART_VERSION" >> "$GITHUB_ENV" + + - name: Packaging + run: helm package helm-chart + + - name: Log in to the Container registry + uses: docker/login-action@v2.1.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ github.token }} + + - name: Push charts to GHCR + run: | + helm push carbon-aware-sdk-${{ env.CHART_VERSION }}.tgz "oci://ghcr.io/green-software-foundation/charts" + shell: bash diff --git a/docs/architecture/decisions/0004-documentation.md b/docs/architecture/decisions/0004-documentation.md index ba0e7fef1..3d950ce59 100644 --- a/docs/architecture/decisions/0004-documentation.md +++ b/docs/architecture/decisions/0004-documentation.md @@ -110,8 +110,6 @@ following implementation of this ADR proposal: ┃ â”Ŗ carbon-aware-webapi.md ┃ ┗ carbon-aware-cli.md â”Ŗ samples/ - ┃ â”Ŗ helmexample/ - ┃ ┃ ┗ README.md ┃ ┗ python-proxy-server/ ┃ ┗ README.md â”Ŗ README.md diff --git a/docs/overview.md b/docs/overview.md index 6ceddccf9..d69e4f8fe 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -219,3 +219,120 @@ $ curl -s http://localhost:8080/emissions/forecasts/current?location=westus2 | j For more information on containerization, refer to the markdown in [containerization.md](./containerization.md). + +### Deploy Web API on Kubernetes with Helm + +You can deploy Web API as a Kubernetes application via Helm. GSF provides a chart as an OCI container, so you have to use Helm v3.8.0 or later. + +Following command creates `carbon-aware-sdk` namespace and deploys Web API into it with specified `values.yaml`. + +```bash +$ helm install casdk -n carbon-aware-sdk --create-namespace oci://ghcr.io/green-software-foundation/charts/carbon-aware-sdk --values values.yaml +``` + +`values.yaml` should contain `appsettings.json` which would be used in Web API at least. It should include data source definitions and their credentials. It would be stored as `Secret` resource. + +```yaml +appsettings: |- + { + "DataSources": { + "EmissionsDataSource": "WattTime", + "ForecastDataSource": "WattTime", + "Configurations": { + "WattTime": { + "Type": "WattTime", + "Username": "username", + "Password": "password", + "BaseURL": "https://api2.watttime.org/v2/" + } + } + } + } +``` + +Also you can include following configuration into `values.yaml`. + +```yaml +# Number of replicas +replicaCount: 1 + +image: + repository: ghcr.io/green-software-foundation/carbon-aware-sdk + pullPolicy: IfNotPresent + # You can set specified tag (equivalent with the SDK version in here) + tag: latest + +# Set the value if you want to override the name. +nameOverride: "" +fullnameOverride: "" + +podAnnotations: {} + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: false + className: "" + annotations: {} + hosts: + - host: carbon-aware-sdk.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: carbon-aware-sdk-tls + # hosts: + # - carbon-aware-sdk.local + +resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +# appsettings.json +appsettings: |- + { + "DataSources": { + "EmissionsDataSource": "ElectricityMaps", + "ForecastDataSource": "WattTime", + "Configurations": { + "WattTime": { + "Type": "WattTime", + "Username": "username", + "Password": "password", + "BaseURL": "https://api2.watttime.org/v2/", + "Proxy": { + "useProxy": true, + "url": "http://10.10.10.1", + "username": "proxyUsername", + "password": "proxyPassword" + } + }, + "ElectricityMaps": { + "Type": "ElectricityMaps", + "APITokenHeader": "auth-token", + "APIToken": "myAwesomeToken", + "BaseURL": "https://api.electricitymap.org/v3/" + } + } + } + } +``` diff --git a/samples/helmexample/.helmignore b/helm-chart/.helmignore similarity index 100% rename from samples/helmexample/.helmignore rename to helm-chart/.helmignore diff --git a/samples/helmexample/Chart.yaml b/helm-chart/Chart.yaml similarity index 90% rename from samples/helmexample/Chart.yaml rename to helm-chart/Chart.yaml index 837354aa5..0037e6951 100644 --- a/samples/helmexample/Chart.yaml +++ b/helm-chart/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 -name: helmexample -description: A Helm chart for Kubernetes +name: carbon-aware-sdk +description: A Helm chart for Carbon Aware SDK # A chart can be either an 'application' or a 'library' chart. # @@ -15,10 +15,10 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 +version: 1.0.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "1.16.0" +appVersion: "1.1.0" diff --git a/samples/helmexample/templates/NOTES.txt b/helm-chart/templates/NOTES.txt similarity index 75% rename from samples/helmexample/templates/NOTES.txt rename to helm-chart/templates/NOTES.txt index ed54c0885..48bbfd547 100644 --- a/samples/helmexample/templates/NOTES.txt +++ b/helm-chart/templates/NOTES.txt @@ -6,16 +6,16 @@ {{- end }} {{- end }} {{- else if contains "NodePort" .Values.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "helmexample.fullname" . }}) + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "carbon-aware-sdk.fullname" . }}) export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") echo http://$NODE_IP:$NODE_PORT {{- else if contains "LoadBalancer" .Values.service.type }} NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "helmexample.fullname" . }}' - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "helmexample.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "carbon-aware-sdk.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "carbon-aware-sdk.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") echo http://$SERVICE_IP:{{ .Values.service.port }} {{- else if contains "ClusterIP" .Values.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "helmexample.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "carbon-aware-sdk.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT diff --git a/samples/helmexample/templates/_helpers.tpl b/helm-chart/templates/_helpers.tpl similarity index 72% rename from samples/helmexample/templates/_helpers.tpl rename to helm-chart/templates/_helpers.tpl index 9437334f2..eb34521bb 100644 --- a/samples/helmexample/templates/_helpers.tpl +++ b/helm-chart/templates/_helpers.tpl @@ -1,7 +1,7 @@ {{/* Expand the name of the chart. */}} -{{- define "helmexample.name" -}} +{{- define "carbon-aware-sdk.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }} @@ -10,7 +10,7 @@ Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). If release name contains chart name it will be used as a full name. */}} -{{- define "helmexample.fullname" -}} +{{- define "carbon-aware-sdk.fullname" -}} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} @@ -26,16 +26,16 @@ If release name contains chart name it will be used as a full name. {{/* Create chart name and version as used by the chart label. */}} -{{- define "helmexample.chart" -}} +{{- define "carbon-aware-sdk.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Common labels */}} -{{- define "helmexample.labels" -}} -helm.sh/chart: {{ include "helmexample.chart" . }} -{{ include "helmexample.selectorLabels" . }} +{{- define "carbon-aware-sdk.labels" -}} +helm.sh/chart: {{ include "carbon-aware-sdk.chart" . }} +{{ include "carbon-aware-sdk.selectorLabels" . }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} @@ -45,17 +45,17 @@ app.kubernetes.io/managed-by: {{ .Release.Service }} {{/* Selector labels */}} -{{- define "helmexample.selectorLabels" -}} -app.kubernetes.io/name: {{ include "helmexample.name" . }} +{{- define "carbon-aware-sdk.selectorLabels" -}} +app.kubernetes.io/name: {{ include "carbon-aware-sdk.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} {{/* Create the name of the service account to use */}} -{{- define "helmexample.serviceAccountName" -}} +{{- define "carbon-aware-sdk.serviceAccountName" -}} {{- if .Values.serviceAccount.create }} -{{- default (include "helmexample.fullname" .) .Values.serviceAccount.name }} +{{- default (include "carbon-aware-sdk.fullname" .) .Values.serviceAccount.name }} {{- else }} {{- default "default" .Values.serviceAccount.name }} {{- end }} diff --git a/samples/helmexample/templates/deployment.yaml b/helm-chart/templates/deployment.yaml similarity index 64% rename from samples/helmexample/templates/deployment.yaml rename to helm-chart/templates/deployment.yaml index 6cd0aef70..eda6adb4c 100644 --- a/samples/helmexample/templates/deployment.yaml +++ b/helm-chart/templates/deployment.yaml @@ -1,16 +1,17 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: {{ include "helmexample.fullname" . }} + name: webapi + namespace: {{ $.Release.Namespace }} labels: - {{- include "helmexample.labels" . | nindent 4 }} + {{- include "carbon-aware-sdk.labels" . | nindent 4 }} spec: {{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.replicaCount }} {{- end }} selector: matchLabels: - {{- include "helmexample.selectorLabels" . | nindent 6 }} + {{- include "carbon-aware-sdk.selectorLabels" . | nindent 6 }} template: metadata: {{- with .Values.podAnnotations }} @@ -18,31 +19,39 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} labels: - {{- include "helmexample.selectorLabels" . | nindent 8 }} + {{- include "carbon-aware-sdk.selectorLabels" . | nindent 8 }} spec: {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} - serviceAccountName: {{ include "helmexample.serviceAccountName" . }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: - name: {{ .Chart.Name }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports: - name: http containerPort: 80 protocol: TCP + volumeMounts: + - name: appsettings + mountPath: /app/appsettings.json + subPath: appsettings.json + readOnly: true livenessProbe: - {{ .Values.monitorConfig.liveness | toYaml | indent 12 | trim }} + httpGet: + path: /health + port: http readinessProbe: - {{ .Values.monitorConfig.readiness | toYaml | indent 12 | trim }} + httpGet: + path: /health + port: http resources: {{- toYaml .Values.resources | nindent 12 }} + volumes: + - name: appsettings + secret: + secretName: appsettings {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/samples/helmexample/templates/hpa.yaml b/helm-chart/templates/hpa.yaml similarity index 83% rename from samples/helmexample/templates/hpa.yaml rename to helm-chart/templates/hpa.yaml index 7ccf2b6d2..4d1856dfd 100644 --- a/samples/helmexample/templates/hpa.yaml +++ b/helm-chart/templates/hpa.yaml @@ -2,14 +2,15 @@ apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata: - name: {{ include "helmexample.fullname" . }} + name: webapi + namespace: {{ $.Release.Namespace }} labels: - {{- include "helmexample.labels" . | nindent 4 }} + {{- include "carbon-aware-sdk.labels" . | nindent 4 }} spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment - name: {{ include "helmexample.fullname" . }} + name: webapi minReplicas: {{ .Values.autoscaling.minReplicas }} maxReplicas: {{ .Values.autoscaling.maxReplicas }} metrics: diff --git a/samples/helmexample/templates/ingress.yaml b/helm-chart/templates/ingress.yaml similarity index 89% rename from samples/helmexample/templates/ingress.yaml rename to helm-chart/templates/ingress.yaml index 95ed7ec83..4dbd741a9 100644 --- a/samples/helmexample/templates/ingress.yaml +++ b/helm-chart/templates/ingress.yaml @@ -1,5 +1,4 @@ {{- if .Values.ingress.enabled -}} -{{- $fullName := include "helmexample.fullname" . -}} {{- $svcPort := .Values.service.port -}} {{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} @@ -15,9 +14,10 @@ apiVersion: extensions/v1beta1 {{- end }} kind: Ingress metadata: - name: {{ $fullName }} + name: webapi + namespace: {{ $.Release.Namespace }} labels: - {{- include "helmexample.labels" . | nindent 4 }} + {{- include "carbon-aware-sdk.labels" . | nindent 4 }} {{- with .Values.ingress.annotations }} annotations: {{- toYaml . | nindent 4 }} @@ -49,11 +49,11 @@ spec: backend: {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} service: - name: {{ $fullName }} + name: webapi port: number: {{ $svcPort }} {{- else }} - serviceName: {{ $fullName }} + serviceName: webapi servicePort: {{ $svcPort }} {{- end }} {{- end }} diff --git a/helm-chart/templates/secret.yaml b/helm-chart/templates/secret.yaml new file mode 100644 index 000000000..a52bfa3ac --- /dev/null +++ b/helm-chart/templates/secret.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: appsettings + namespace: {{ $.Release.Namespace }} + labels: + {{- include "carbon-aware-sdk.labels" . | nindent 4 }} +type: Opaque +stringData: + appsettings.json: {{- .Values.appsettings | toYaml | indent 2 }} diff --git a/samples/helmexample/templates/service.yaml b/helm-chart/templates/service.yaml similarity index 53% rename from samples/helmexample/templates/service.yaml rename to helm-chart/templates/service.yaml index 3a637319e..644c31442 100644 --- a/samples/helmexample/templates/service.yaml +++ b/helm-chart/templates/service.yaml @@ -1,9 +1,10 @@ apiVersion: v1 kind: Service metadata: - name: {{ include "helmexample.fullname" . }} + name: webapi + namespace: {{ $.Release.Namespace }} labels: - {{- include "helmexample.labels" . | nindent 4 }} + {{- include "carbon-aware-sdk.labels" . | nindent 4 }} spec: type: {{ .Values.service.type }} ports: @@ -12,4 +13,4 @@ spec: protocol: TCP name: http selector: - {{- include "helmexample.selectorLabels" . | nindent 4 }} + {{- include "carbon-aware-sdk.selectorLabels" . | nindent 4 }} diff --git a/helm-chart/templates/tests/test-connection.yaml b/helm-chart/templates/tests/test-connection.yaml new file mode 100644 index 000000000..b7b3405f6 --- /dev/null +++ b/helm-chart/templates/tests/test-connection.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: webapi-test-connection + namespace: {{ $.Release.Namespace }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['webapi:{{ .Values.service.port }}/health'] + restartPolicy: Never diff --git a/samples/helmexample/values.yaml b/helm-chart/values.yaml similarity index 53% rename from samples/helmexample/values.yaml rename to helm-chart/values.yaml index 877485e7d..38ac85b17 100644 --- a/samples/helmexample/values.yaml +++ b/helm-chart/values.yaml @@ -1,41 +1,20 @@ -# Default values for helmexample. +# Default values for carbon-aware-sdk. # This is a YAML-formatted file. # Declare variables to be passed into your templates. replicaCount: 1 image: - repository: carbonawaretoyacr.azurecr.io/ca_0504 + repository: ghcr.io/green-software-foundation/carbon-aware-sdk pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. - tag: "latest" + tag: latest -imagePullSecrets: [] -nameOverride: "helm-example" -fullnameOverride: "helm-chart-example" - -serviceAccount: - # Specifies whether a service account should be created - create: true - # Annotations to add to the service account - annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: "helmexample" +nameOverride: "" +fullnameOverride: "" podAnnotations: {} -podSecurityContext: {} - # fsGroup: 2000 - -securityContext: {} - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 - service: type: ClusterIP port: 80 @@ -47,24 +26,14 @@ ingress: # kubernetes.io/ingress.class: nginx # kubernetes.io/tls-acme: "true" hosts: - - host: chart-example.local + - host: carbon-aware-sdk.local paths: - path: / pathType: ImplementationSpecific tls: [] - # - secretName: chart-example-tls + # - secretName: carbon-aware-sdk-tls # hosts: - # - chart-example.local - -monitorConfig: - liveness: - httpGet: - path: "/health" - port: "http" - readiness: - httpGet: - path: "/health" - port: "http" + # - carbon-aware-sdk.local resources: {} # We usually recommend not to specify default resources and to leave this as a conscious @@ -90,3 +59,32 @@ nodeSelector: {} tolerations: [] affinity: {} + +# /app/appsettings.json +appsettings: |- + { + "DataSources": { + "EmissionsDataSource": "ElectricityMaps", + "ForecastDataSource": "WattTime", + "Configurations": { + "WattTime": { + "Type": "WattTime", + "Username": "username", + "Password": "password", + "BaseURL": "https://api2.watttime.org/v2/", + "Proxy": { + "useProxy": true, + "url": "http://10.10.10.1", + "username": "proxyUsername", + "password": "proxyPassword" + } + }, + "ElectricityMaps": { + "Type": "ElectricityMaps", + "APITokenHeader": "auth-token", + "APIToken": "myAwesomeToken", + "BaseURL": "https://api.electricitymap.org/v3/" + } + } + } + } diff --git a/samples/helmexample/README.md b/samples/helmexample/README.md deleted file mode 100644 index 189c2ed4d..000000000 --- a/samples/helmexample/README.md +++ /dev/null @@ -1,231 +0,0 @@ -# How-To: Deploy to AKS using Helm - -## Setup Dev Environment (optional) - -The easiest way to setup your environment is to use a VSCode dev container. -Suggested setup is with the latest `debian` OS with `az CLI` and `kubectl-helm` -packages enabled. - -## Setup Resource Group in Azure - -1. Create a new Kubernetes service following the default settings -1. Create a container registry -1. Create a key vault - -## Push an image to the container registry - -The following steps illustrates how to push a webservice image in order to be -deployed in AKS using ACR (Azure Container Registry). - -1. Build a `published` image using for instancee the following - [Dockerfile](https://docs.microsoft.com/en-us/dotnet/core/docker/build-container?tabs=windows#create-the-dockerfile) - - ```sh - docker build -t myapp:v1 . - ``` - -1. Login into ACR using the username and password credentials that are needed in - order to push. See Access Keys section of the ACR Portal. - - ```sh - docker login .azurecr.io - ``` - -1. Tag the image following ACR tagging scheme - - ```sh - docker tag myapp .azurecr.io/myapp:v1 - ``` - -1. Push to ACR - - ```sh - docker push .azurecr.io/myapp:v1 - ``` - -After these steps, using Azure's Portal ACR resource an image should be -available under repositories following the naming convention mentioned above. - -### Give cluster access to ACR - -To attach the ACR to the cluster so that the image can be accessed, run - -```bash -az aks update -n -g --attach-acr -``` - -## Create a new Helm chart (optional) - -Run `helm` to ensure you have the helm CLI running properly. Then you can create -a new helm chart by running - -```bash -helm create -``` - -## Setting up the Helm chart - -Once you've got your helm chart open (whether from scratch or existing), the -main files you will likely be working with are `Chart.yaml` and `values.yaml`. - -### Chart.yaml - -In `Chart.yaml`, we won't need to make any changes but make note of the chart -`name`, as you will need to reference it in commands later on. - -### Values.yaml - -In `values.yaml`, we need to change a couple fields. In the `image` section, you -will need to set - -- The `repository` field to be `/` -- The `pullPolicy` field to be `IfNotPresent` (pulls a new image if not present) - or `Always` (pulls a new image every time). -- The `tag` field if you need a particuar tag version - -Set the `nameOverride` and `fullNameOverride` fields to make it easier to -reference your helm chart, and ensure they are not the same. - -In the `serviceAccount` section, ensure that - -- The `name` field is set to the name of the helm chart from `Chart.yaml`. - -In the `monitorConfig` section, you will need to adjust the `liveness` and -`readiness` that the helm chart will ping to ensure the sdk is ready. As a -default, you should set the path to `/health`. - -## Connecting to AKS from Helm - -To connect to AKS you need to be logged into the azure. Run `az login` and -follow the prompts to get access to your azure subscriptions. - -To set the right subscription for the service, run: - -```bash -az account set --subscription -``` - -To give credentials for the resource group to the kubernetes service, run: - -```bash -az aks get-credentials --resource-group --name -``` - -With these two commands, helm should be setup to access AKS and be able to -deploy on it. With the current setup, Helm is not directly accessing the ACR to -pull the image, put instead is going through the cluster (which is why we gave -the cluster authorized access to the ACR in the earlier section). If you do need -helm to access your ACR for any reason, you will need to register it and login -with the following - -```bash -helm registry login \ - --username \ - --password -``` - -The neccessary credentials can be found by opening your ACR in the Azure portal -and going to credentials. - -### Installing your helm chart - -To install your helm chart, you should run - -```bash -helm install / -``` - -(If you run into an error, see the [troubleshooting](#troubleshooting) section. -below.) - -### Deploying your helm chart - -If the installation was successful, helm should give you a console out message -for your to copy and paste to deploy the chart. We've replicated below for quick -reference (you will need to fill in `nameOverride` and `fullNameOverride`): - -```bash -export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=,app.kubernetes.io/instance=" -o jsonpath="{.items[0].metadata.name}") -export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT -``` - -If the deployment works properly, you should be able to visit the link they -provide and use it to query the SDK - -## Troubleshooting - -### Error connecting to the kubernetes service - -If you get - -```text -Error: INSTALLATION FAILED: Kubernetes cluster unreachable: Get "http://localhost:8080/version": dial tcp 127.0.0.1:8080: connect: connection refused -``` - -that means that helm cannot connect to kubernetes. Helm connects to kuberentes -either via the $KUBECONFIG env variable, or (if it's not set) looks for the -default location kubectl files are location (`~/.kube/config`). This may occur -the first time to try connecting the helm chart or if you clear the -files/variables. To fix, follow the cli commands in the -[connecting to AKS](#connecting-to-aks-from-helm) section and that should -automatically generate the proper config files. - -### Error installing the helm chart - -If you get -`Error: INSTALLATION FAILED: cannot re-use a name that is still in use` when you -tried to install the helm chart, it means there is still an instance of that -chart installed. If you started this instance, you can simply skip the install -step and continue. If you're unsure that it's the right installation, or you've -made changes, first run `helm uninstall `. Once it's -uninstalled, you can redo the helm install step. - -### Error pulling image - -If there is an issue pulling the image from ACR, the pod will deploy but will -fail to start. If you check the status of the pod (using the kubectl commands -below in the azure portal) you will see the `ImagePullBackOff` status and a note -that the pod has not started. This may be for a couple reasons: - -1. The cluster isn't authorized to access the ACR registry. Ensure you've run - [this command](#give-cluster-access-to-acr). -2. The image reference in helm is incorrect. Review the Values.yaml - [section](#valuesyaml) to ensure you've got the right reference in the - image repository field. - -### Error deploying the helm chart - -If you get an error deploying the helm chart and have ensured the image is -pulling properly, one possible error may be with the liveliness and readiness -probes. If those are failing, the deployment will fail to start properly. Ensure -that the paths provided in the `deployment.yaml` file are valid and that the sdk -can actual spin up correctly. - -### Useful kubectl commands to check on cluster - -- List all deployments in all namespaces: - `kubectl get deployments --all-namespaces=true` -- List details about a specific deployment: - `kubectl describe deployment --namespace ` -- Delete a specific deployment: `kubectl delete deployment ` -- List pods: `kubectl get pods` -- Check on a specific pod: `kubectl describe pod ` -- Get logs on a specific pod: `kubectl logs ` -- Delete a specific pod: `kubectl delete pod ` - -## References - -Helm 3: [docs](https://helm.sh/docs/), -[image docs](https://helm.sh/docs/chart_best_practices/pods/#images) - -MS Docs: -[Creating an ingress controller in AKS](https://docs.microsoft.com/en-us/azure/aks/ingress-basic?tabs=azure-cli), -[Authenticate with ACR from AKS](https://docs.microsoft.com/en-us/azure/aks/cluster-container-registry-integration?tabs=azure-cli#access-with-kubernetes-secret) - -Github Issue: -[Deploying a container from ACR to AKS](https://github.com/MicrosoftDocs/azure-docs/issues/33430) - -ContainIQ: -[Troubleshooting ImagePullBackOff Error](https://www.containiq.com/post/kubernetes-imagepullbackoff) diff --git a/samples/helmexample/templates/serviceaccount.yaml b/samples/helmexample/templates/serviceaccount.yaml deleted file mode 100644 index edb759fb1..000000000 --- a/samples/helmexample/templates/serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "helmexample.serviceAccountName" . }} - labels: - {{- include "helmexample.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/samples/helmexample/templates/tests/test-connection.yaml b/samples/helmexample/templates/tests/test-connection.yaml deleted file mode 100644 index d34f26fb0..000000000 --- a/samples/helmexample/templates/tests/test-connection.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: "{{ include "helmexample.fullname" . }}-test-connection" - labels: - {{- include "helmexample.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": test -spec: - containers: - - name: wget - image: busybox - command: ['wget'] - args: ['{{ include "helmexample.fullname" . }}:{{ .Values.service.port }}'] - restartPolicy: Never From cb3964b79ff08da78e189b4d96b0fdc4b235fa23 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Wed, 9 Aug 2023 15:22:16 +0900 Subject: [PATCH 08/33] Update HPA apiVersion https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#api-object Signed-off-by: Yasumasa Suenaga --- helm-chart/templates/hpa.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm-chart/templates/hpa.yaml b/helm-chart/templates/hpa.yaml index 4d1856dfd..f254c9d35 100644 --- a/helm-chart/templates/hpa.yaml +++ b/helm-chart/templates/hpa.yaml @@ -1,5 +1,5 @@ {{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2beta1 +apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: webapi From a3d7640a267c983be78f74e11825c8f5119a84ac Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Wed, 9 Aug 2023 15:24:13 +0900 Subject: [PATCH 09/33] .image.tag should be comment-outed to use app version by default Signed-off-by: Yasumasa Suenaga --- helm-chart/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm-chart/values.yaml b/helm-chart/values.yaml index 38ac85b17..402ef8f39 100644 --- a/helm-chart/values.yaml +++ b/helm-chart/values.yaml @@ -8,7 +8,7 @@ image: repository: ghcr.io/green-software-foundation/carbon-aware-sdk pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. - tag: latest + #tag: latest nameOverride: "" fullnameOverride: "" From 0b1c9396d337cfec82b99f93450315a9f79f8c88 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Wed, 9 Aug 2023 15:28:43 +0900 Subject: [PATCH 10/33] Restore security context Signed-off-by: Yasumasa Suenaga --- docs/overview.md | 11 +++++++++++ helm-chart/templates/deployment.yaml | 4 ++++ helm-chart/values.yaml | 11 +++++++++++ 3 files changed, 26 insertions(+) diff --git a/docs/overview.md b/docs/overview.md index d69e4f8fe..588ca6ce8 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -268,6 +268,17 @@ fullnameOverride: "" podAnnotations: {} +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + service: type: ClusterIP port: 80 diff --git a/helm-chart/templates/deployment.yaml b/helm-chart/templates/deployment.yaml index eda6adb4c..413873315 100644 --- a/helm-chart/templates/deployment.yaml +++ b/helm-chart/templates/deployment.yaml @@ -25,8 +25,12 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports: diff --git a/helm-chart/values.yaml b/helm-chart/values.yaml index 402ef8f39..e93ae501a 100644 --- a/helm-chart/values.yaml +++ b/helm-chart/values.yaml @@ -15,6 +15,17 @@ fullnameOverride: "" podAnnotations: {} +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + service: type: ClusterIP port: 80 From db506d60b8c80d18ee59f2ba84adc20fd5126af3 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Wed, 9 Aug 2023 15:35:23 +0900 Subject: [PATCH 11/33] Use default imagePullPolicy in Kubernetes by default Signed-off-by: Yasumasa Suenaga --- helm-chart/templates/deployment.yaml | 2 ++ helm-chart/values.yaml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/helm-chart/templates/deployment.yaml b/helm-chart/templates/deployment.yaml index 413873315..9acbef98d 100644 --- a/helm-chart/templates/deployment.yaml +++ b/helm-chart/templates/deployment.yaml @@ -32,7 +32,9 @@ spec: securityContext: {{- toYaml .Values.securityContext | nindent 12 }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + {{- with .Values.image.pullPolicy }} imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- end }} ports: - name: http containerPort: 80 diff --git a/helm-chart/values.yaml b/helm-chart/values.yaml index e93ae501a..fc6a95e89 100644 --- a/helm-chart/values.yaml +++ b/helm-chart/values.yaml @@ -6,7 +6,7 @@ replicaCount: 1 image: repository: ghcr.io/green-software-foundation/carbon-aware-sdk - pullPolicy: IfNotPresent + #pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. #tag: latest From 5019cfbb834df54ac5bead5569484c064e22bd09 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Wed, 9 Aug 2023 15:39:54 +0900 Subject: [PATCH 12/33] Restore ServiceAccount Signed-off-by: Yasumasa Suenaga --- docs/overview.md | 9 +++++++++ helm-chart/templates/serviceaccount.yaml | 13 +++++++++++++ helm-chart/values.yaml | 9 +++++++++ 3 files changed, 31 insertions(+) create mode 100644 helm-chart/templates/serviceaccount.yaml diff --git a/docs/overview.md b/docs/overview.md index 588ca6ce8..3e3875116 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -266,6 +266,15 @@ image: nameOverride: "" fullnameOverride: "" +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + podAnnotations: {} podSecurityContext: {} diff --git a/helm-chart/templates/serviceaccount.yaml b/helm-chart/templates/serviceaccount.yaml new file mode 100644 index 000000000..f12253289 --- /dev/null +++ b/helm-chart/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "carbon-aware-sdk.serviceAccountName" . }} + labels: + {{- include "carbon-aware-sdk.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: false +{{- end }} diff --git a/helm-chart/values.yaml b/helm-chart/values.yaml index fc6a95e89..3d32c9266 100644 --- a/helm-chart/values.yaml +++ b/helm-chart/values.yaml @@ -13,6 +13,15 @@ image: nameOverride: "" fullnameOverride: "" +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + podAnnotations: {} podSecurityContext: {} From 0ed709d6ba88334753d07ac715e843357e1586c5 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Wed, 9 Aug 2023 15:53:48 +0900 Subject: [PATCH 13/33] fix Signed-off-by: Yasumasa Suenaga --- helm-chart/templates/deployment.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helm-chart/templates/deployment.yaml b/helm-chart/templates/deployment.yaml index 9acbef98d..88fa88d98 100644 --- a/helm-chart/templates/deployment.yaml +++ b/helm-chart/templates/deployment.yaml @@ -25,6 +25,7 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} + serviceAccountName: {{ include "carbon-aware-sdk.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: @@ -33,7 +34,7 @@ spec: {{- toYaml .Values.securityContext | nindent 12 }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" {{- with .Values.image.pullPolicy }} - imagePullPolicy: {{ .Values.image.pullPolicy }} + imagePullPolicy: {{ . }} {{- end }} ports: - name: http From 19bcb0251c624c74672caf5129fb4a1b8147bb99 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Wed, 9 Aug 2023 15:56:43 +0900 Subject: [PATCH 14/33] Disable enableServiceLinks to reduce environment variables Signed-off-by: Yasumasa Suenaga --- helm-chart/templates/deployment.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/helm-chart/templates/deployment.yaml b/helm-chart/templates/deployment.yaml index 88fa88d98..3a9891b36 100644 --- a/helm-chart/templates/deployment.yaml +++ b/helm-chart/templates/deployment.yaml @@ -28,6 +28,7 @@ spec: serviceAccountName: {{ include "carbon-aware-sdk.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + enableServiceLinks: false containers: - name: {{ .Chart.Name }} securityContext: From 371905a8835f8a735b8b19b19dc3515bc8aa56b9 Mon Sep 17 00:00:00 2001 From: Christian Binder <43334159+xcbinder@users.noreply.github.com> Date: Tue, 22 Aug 2023 01:28:59 +0200 Subject: [PATCH 15/33] Update ElectricityMapsDataSource.cs (#365) Issue : I have tested a ElectricityMaps forecast scenario CLI: "emissions-forecasts -l westeurope -v" will return server error 500. Analysis: public async Task GetCurrentCarbonIntensityForecastAsync(Location location) is causing the EM server to return 500. Reason is that the "." in geolocation.Latitude will be passed as "," Fix: The following changes are fixing this bug. Signed-off-by: Christian Binder <43334159+xcbinder@users.noreply.github.com> --- .../src/ElectricityMapsDataSource.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMaps/src/ElectricityMapsDataSource.cs b/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMaps/src/ElectricityMapsDataSource.cs index ea4a99b0e..01e494bbd 100644 --- a/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMaps/src/ElectricityMapsDataSource.cs +++ b/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMaps/src/ElectricityMapsDataSource.cs @@ -45,8 +45,8 @@ public async Task GetCurrentCarbonIntensityForecastAsync(Loca { ForecastedCarbonIntensityData forecast; var geolocation = await this._locationSource.ToGeopositionLocationAsync(location); - if (geolocation.Latitude != null && geolocation.Latitude != null) - forecast = await this._electricityMapsClient.GetForecastedCarbonIntensityAsync (geolocation.Latitude.ToString() ?? "", geolocation.Longitude.ToString() ?? ""); + if (geolocation.Latitude != null && geolocation.Longitude != null) + forecast = await this._electricityMapsClient.GetForecastedCarbonIntensityAsync (geolocation.LatitudeAsCultureInvariantString(), geolocation.LongitudeAsCultureInvariantString()); else { forecast = await this._electricityMapsClient.GetForecastedCarbonIntensityAsync (geolocation.Name ?? ""); From 4e0b3a1db5d244494bf89e84280dd2b4342a703a Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Fri, 1 Sep 2023 09:32:33 +0900 Subject: [PATCH 16/33] Use a variable to specify repository owner --- .github/workflows/publish-helm-chart.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-helm-chart.yaml b/.github/workflows/publish-helm-chart.yaml index 84bbfb1ab..17e074f09 100644 --- a/.github/workflows/publish-helm-chart.yaml +++ b/.github/workflows/publish-helm-chart.yaml @@ -36,5 +36,6 @@ jobs: - name: Push charts to GHCR run: | - helm push carbon-aware-sdk-${{ env.CHART_VERSION }}.tgz "oci://ghcr.io/green-software-foundation/charts" + OWNER_LOWER=${GITHUB_REPOSITORY_OWNER,,} + helm push carbon-aware-sdk-${{ env.CHART_VERSION }}.tgz "oci://ghcr.io/$OWNER_LOWER/charts" shell: bash From cb4af960c566c21ab8040a86f68f3cc783890449 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Mon, 4 Sep 2023 09:34:42 +0900 Subject: [PATCH 17/33] EMFree data source should regard specified time range Signed-off-by: Yasumasa Suenaga --- .../Emissions/EmissionsCommandTests.cs | 4 +-- .../EmissionsForecastsCommandTests.cs | 4 +-- .../src/ElectricityMapsFreeDataSource.cs | 26 ++++++++++++++----- .../ElectricityMapsFreeDataSourceTests.cs | 12 ++++++--- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/CarbonAware.CLI/test/integrationTests/Commands/Emissions/EmissionsCommandTests.cs b/src/CarbonAware.CLI/test/integrationTests/Commands/Emissions/EmissionsCommandTests.cs index af0316ec5..8831dae25 100644 --- a/src/CarbonAware.CLI/test/integrationTests/Commands/Emissions/EmissionsCommandTests.cs +++ b/src/CarbonAware.CLI/test/integrationTests/Commands/Emissions/EmissionsCommandTests.cs @@ -72,7 +72,7 @@ public async Task Emissions_StartAndEndOptions_ReturnsExpectedData() _dataSourceMocker.SetupDataMock(start, end, location); // Act - var exitCode = await InvokeCliAsync($"emissions -l {location} -s 2022-09-01T02:01:00Z -e 2022-09-01T02:04:00Z"); + var exitCode = await InvokeCliAsync($"emissions -l {location} -s 2022-09-01T00:00:00Z -e 2022-09-01T00:04:00Z"); // Assert Assert.AreEqual(0, exitCode); @@ -117,7 +117,7 @@ public async Task Emissions_BestOption_ReturnsExpectedData() _dataSourceMocker.SetupDataMock(start, end, location); // Act - var exitCode = await InvokeCliAsync($"emissions -l {location} -s 2022-09-01T02:01:00Z -e 2022-09-01T02:04:00Z -b"); + var exitCode = await InvokeCliAsync($"emissions -l {location} -s 2022-09-01T00:00:00Z -e 2022-09-01T00:04:00Z -b"); // Assert Assert.AreEqual(0, exitCode); diff --git a/src/CarbonAware.CLI/test/integrationTests/Commands/EmissionsForecasts/EmissionsForecastsCommandTests.cs b/src/CarbonAware.CLI/test/integrationTests/Commands/EmissionsForecasts/EmissionsForecastsCommandTests.cs index e5703f974..2c232d187 100644 --- a/src/CarbonAware.CLI/test/integrationTests/Commands/EmissionsForecasts/EmissionsForecastsCommandTests.cs +++ b/src/CarbonAware.CLI/test/integrationTests/Commands/EmissionsForecasts/EmissionsForecastsCommandTests.cs @@ -71,8 +71,8 @@ public async Task EmissionsForecasts_StartAndEndOptions_ReturnsExpectedData() var location = "eastus"; var start = DateTimeOffset.UtcNow.AddMinutes(10); var end = start.AddHours(5); - var dataStartAt = start.ToString("yyyy-MM-ddTHH:mm:ss"); - var dataEndAt = end.ToString("yyyy-MM-ddTHH:mm:ss"); + var dataStartAt = start.ToString("yyyy-MM-ddTHH:mm:ssZ"); + var dataEndAt = end.ToString("yyyy-MM-ddTHH:mm:ssZ"); _dataSourceMocker.SetupForecastMock(); // Act diff --git a/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMapsFree/src/ElectricityMapsFreeDataSource.cs b/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMapsFree/src/ElectricityMapsFreeDataSource.cs index 60ad2a61c..f0a1687f7 100644 --- a/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMapsFree/src/ElectricityMapsFreeDataSource.cs +++ b/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMapsFree/src/ElectricityMapsFreeDataSource.cs @@ -86,15 +86,27 @@ public async Task> GetCarbonIntensityAsync(Location l } List EmissionsDataList = new List(); + var emissionDateTime = gridEmissionData.Data.Datetime; + var shouldReturn = true; + if (emissionDateTime != null && periodStartTime < periodEndTime) + { + // periodEndTime would be set periodStartTime in EmissionHandler if it is not specified. + // So we can assume we should return the most recent data if they equal. + // If not, we should return the data after checking it is within specified time range. + shouldReturn = periodStartTime <= emissionDateTime && emissionDateTime < periodEndTime; + } - var emissionData = new EmissionsData() + if (shouldReturn) { - Location = location.Name ?? "", - Time = gridEmissionData.Data.Datetime ?? new DateTimeOffset(), - Rating = gridEmissionData.Data.CarbonIntensity ?? 0.0, - Duration = new TimeSpan(0, 0, 0) - }; - EmissionsDataList.Add(emissionData); + var emissionData = new EmissionsData() + { + Location = location.Name ?? "", + Time = emissionDateTime ?? new DateTimeOffset(), + Rating = gridEmissionData.Data.CarbonIntensity ?? 0.0, + Duration = new TimeSpan(0, 0, 0) + }; + EmissionsDataList.Add(emissionData); + } return EmissionsDataList; } diff --git a/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMapsFree/test/ElectricityMapsFreeDataSourceTests.cs b/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMapsFree/test/ElectricityMapsFreeDataSourceTests.cs index 8a8eb39c8..21203ef35 100644 --- a/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMapsFree/test/ElectricityMapsFreeDataSourceTests.cs +++ b/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMapsFree/test/ElectricityMapsFreeDataSourceTests.cs @@ -36,8 +36,9 @@ public ElectricityMapsFreeDataSourceTests() _dataSource = new ElectricityMapsFreeDataSource(_logger.Object, _ElectricityMapsFreeClient.Object, _locationSource.Object); } - [Test] - public async Task GetCarbonIntensity_ReturnsResultsWhenRecordsFound() + [TestCase(false, TestName = "GetCarbonIntensity_ReturnsResultsWhenRecordsFound without emission date time")] + [TestCase(true, TestName = "GetCarbonIntensity_ReturnsResultsWhenRecordsFound with emission date time")] + public async Task GetCarbonIntensity_ReturnsResultsWhenRecordsFound(bool withEmissionDateTime) { var startDate = DateTimeOffset.UtcNow.AddHours(-10); var endDate = startDate.AddHours(1); @@ -49,6 +50,7 @@ public async Task GetCarbonIntensity_ReturnsResultsWhenRecordsFound() { Data = new Data() { + Datetime = withEmissionDateTime ? startDate.AddMinutes(30) : null, CarbonIntensity = expectedCarbonIntensity, } }; @@ -71,8 +73,9 @@ public async Task GetCarbonIntensity_ReturnsResultsWhenRecordsFound() this._locationSource.Verify(l => l.ToGeopositionLocationAsync(_defaultLocation)); } - [Test] - public async Task GetCarbonIntensity_UseRegionNameWhenCoordinatesNotAvailable() + [TestCase(false, TestName = "GetCarbonIntensity_UseRegionNameWhenCoordinatesNotAvailable without emission date time")] + [TestCase(true, TestName = "GetCarbonIntensity_UseRegionNameWhenCoordinatesNotAvailable with emission date time")] + public async Task GetCarbonIntensity_UseRegionNameWhenCoordinatesNotAvailable(bool withEmissionDateTime) { var startDate = new DateTimeOffset(2022, 4, 18, 12, 32, 42, TimeSpan.FromHours(-6)); var endDate = startDate.AddMinutes(1); @@ -84,6 +87,7 @@ public async Task GetCarbonIntensity_UseRegionNameWhenCoordinatesNotAvailable() { Data = new Data() { + Datetime = withEmissionDateTime ? startDate.AddSeconds(30) : null, CarbonIntensity = expectedCarbonIntensity, } }; From c2cb7300690214ca4243807456a539a5ec36986f Mon Sep 17 00:00:00 2001 From: nttDamien <125525959+nttDamien@users.noreply.github.com> Date: Tue, 12 Sep 2023 15:44:39 +0900 Subject: [PATCH 18/33] fixing 3 broken links in overview.md (#391) fixing 3 broken links in overview.md Signed-off-by: nttDamien <125525959+nttDamien@users.noreply.github.com> --- docs/overview.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/overview.md b/docs/overview.md index 6ceddccf9..b83998618 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -6,14 +6,14 @@ you different data than the WebAPI for the same query). We provide a number of different endpoints to provide the most flexibility to integrate to your environment: -- You can run the application using the [CLI](./src/CarbonAware.CLI) and refer +- You can run the application using the [CLI](../src/CarbonAware.CLI) and refer to more documentation [here](./carbon-aware-cli.md). -- You can build a container containing the [WebAPI](./src/CarbonAware.WebApi) +- You can build a container containing the [WebAPI](../src/CarbonAware.WebApi) and connect via REST requests and refer to more documentation [here](./carbon-aware-webapi.md). -- You can reference the [Carbon Aware C# Library](./src/GSF.CarbonAware) in your +- You can reference the [Carbon Aware C# Library](../src/GSF.CarbonAware) in your projects and make use of its functionalities and features. - (Future) You can install the Nuget package and make requests directly. From 25121e6d6ce63d1c873e7780652b7786b4678750 Mon Sep 17 00:00:00 2001 From: Roman Lutz Date: Tue, 12 Sep 2023 03:42:44 -0400 Subject: [PATCH 19/33] Fix quickstart.md (#375) Signed-off-by: Roman Lutz --- docs/quickstart.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/quickstart.md b/docs/quickstart.md index a3b68dfa7..463901e8e 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -96,7 +96,7 @@ Expected output: For example, to get emissions in the `eastus` and `uksouth` region between `2022-08-23 at 11:15am` and `2022-08-23 at 11:20am`, run: -`dotnet run -l eastus,uksouth -t 2022-08-23T11:15 --toTime 2022-08-23T11:20` +`dotnet run emissions -l eastus,uksouth -s 2022-08-23T11:15 -e 2022-08-23T11:20` Expected output: @@ -147,7 +147,7 @@ hour window on the 23rd of August in the regions: `eastus`, `westus`, `westus3`,`uksouth`, run the command: ```bash -dotnet run -l eastus,westus,westus3,uksouth -t 2022-08-23T00:00 --toTime 2022-08-23T23:59 --best +dotnet run -l eastus,westus,westus3,uksouth -s 2022-08-23T00:00 -e 2022-08-23T23:59 --best ``` Expected output: From 633becb1659b13fcb43066d7819580c87698f3f6 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Tue, 12 Sep 2023 17:23:55 +0900 Subject: [PATCH 20/33] Revert change of ADR-0004 Discussed about this in: - https://github.com/Green-Software-Foundation/carbon-aware-sdk/issues/392#issuecomment-1715147677 - https://github.com/Green-Software-Foundation/carbon-aware-sdk/pull/381#issuecomment-1715155302 Signed-off-by: Yasumasa Suenaga --- docs/architecture/decisions/0004-documentation.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/architecture/decisions/0004-documentation.md b/docs/architecture/decisions/0004-documentation.md index 3d950ce59..ba0e7fef1 100644 --- a/docs/architecture/decisions/0004-documentation.md +++ b/docs/architecture/decisions/0004-documentation.md @@ -110,6 +110,8 @@ following implementation of this ADR proposal: ┃ â”Ŗ carbon-aware-webapi.md ┃ ┗ carbon-aware-cli.md â”Ŗ samples/ + ┃ â”Ŗ helmexample/ + ┃ ┃ ┗ README.md ┃ ┗ python-proxy-server/ ┃ ┗ README.md â”Ŗ README.md From dd30d1f0e7c8e7753268bba148d769fa167137a7 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Tue, 12 Sep 2023 17:32:30 +0900 Subject: [PATCH 21/33] Add video for install demonstration with Helm Signed-off-by: Yasumasa Suenaga --- docs/overview.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/overview.md b/docs/overview.md index 3e3875116..77bd7a0e4 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -356,3 +356,7 @@ appsettings: |- } } ``` + +The video in below is demonstration to install Carbon Aware SDK via Helm. Note that installing the SDK from local directory ( ~/github-forked/carbon-aware-sdk/helm-chart ), not an OCI container. + +[!Demonstration to intall Carbon Aware SDK from local with Helm](https://github.com/Green-Software-Foundation/carbon-aware-sdk/assets/7421132/b09d8ab1-642b-442a-882f-abc802153070) From e6e1734724523f94e43cf149ef840d17a4b4b3df Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Tue, 12 Sep 2023 17:37:37 +0900 Subject: [PATCH 22/33] DCO Remediation Commit for Yasumasa Suenaga I, Yasumasa Suenaga , hereby add my Signed-off-by to this commit: 4e0b3a1db5d244494bf89e84280dd2b4342a703a Signed-off-by: Yasumasa Suenaga From d1cb14cb0d9c8ba0229c6a1e8beddad770a4a7cb Mon Sep 17 00:00:00 2001 From: Szymon Duchniewicz Date: Tue, 12 Sep 2023 10:47:51 +0200 Subject: [PATCH 23/33] Fix: verify-azure-function-with-packages #383 Signed-off-by: Szymon Duchniewicz --- .github/workflows/verify-azure-function-with-packages.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/verify-azure-function-with-packages.yaml b/.github/workflows/verify-azure-function-with-packages.yaml index d5faa3dba..0ef34fef0 100644 --- a/.github/workflows/verify-azure-function-with-packages.yaml +++ b/.github/workflows/verify-azure-function-with-packages.yaml @@ -26,10 +26,11 @@ jobs: continue-on-error: true run: docker rm -f ${{ env.CONTAINER_RUNTIME_NAME }} + # Build and tag final image, remove dangling images only if there are any - name: Docker Target Final run: | docker build --no-cache . -f ${{ env.DOCKERFILE_PATH }} -t ${{ env.CONTAINER_IMAGE_NAME }} - docker rmi -f $(docker images -f "dangling=true" -q) + docker images -qf dangling=true | xargs --no-run-if-empty docker rmi - name: Docker Run Container run: docker run -d --name ${{ env.CONTAINER_RUNTIME_NAME }} -p 8080:80 ${{ env.CONTAINER_IMAGE_NAME }} From 1695a63350892a40ae05de91d7c85b0789948182 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Tue, 19 Sep 2023 21:40:59 +0900 Subject: [PATCH 24/33] Return empty list when ElectricityMapsFree.GetCarbonIntensityAsync() receives request for forecast Signed-off-by: Yasumasa Suenaga --- .../src/ElectricityMapsFreeDataSource.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMapsFree/src/ElectricityMapsFreeDataSource.cs b/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMapsFree/src/ElectricityMapsFreeDataSource.cs index f0a1687f7..d4268e352 100644 --- a/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMapsFree/src/ElectricityMapsFreeDataSource.cs +++ b/src/CarbonAware.DataSources/CarbonAware.DataSources.ElectricityMapsFree/src/ElectricityMapsFreeDataSource.cs @@ -87,8 +87,10 @@ public async Task> GetCarbonIntensityAsync(Location l List EmissionsDataList = new List(); var emissionDateTime = gridEmissionData.Data.Datetime; - var shouldReturn = true; - if (emissionDateTime != null && periodStartTime < periodEndTime) + + // periodStartTime should be less than current date time because this method should not handle forecast data. + var shouldReturn = periodStartTime <= DateTimeOffset.UtcNow; + if (shouldReturn && emissionDateTime != null && periodStartTime < periodEndTime) { // periodEndTime would be set periodStartTime in EmissionHandler if it is not specified. // So we can assume we should return the most recent data if they equal. From 5e647af75eea8b85a58f9aab6c57428adf88f161 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Wed, 4 Oct 2023 11:17:52 +0900 Subject: [PATCH 25/33] Give number 5 to workflow for Helm chart Signed-off-by: Yasumasa Suenaga --- .../{publish-helm-chart.yaml => 5-publish-helm-chart.yaml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{publish-helm-chart.yaml => 5-publish-helm-chart.yaml} (97%) diff --git a/.github/workflows/publish-helm-chart.yaml b/.github/workflows/5-publish-helm-chart.yaml similarity index 97% rename from .github/workflows/publish-helm-chart.yaml rename to .github/workflows/5-publish-helm-chart.yaml index 17e074f09..4e017c950 100644 --- a/.github/workflows/publish-helm-chart.yaml +++ b/.github/workflows/5-publish-helm-chart.yaml @@ -1,4 +1,4 @@ -name: Publish Helm chart +name: 5-Publish Helm chart on: workflow_dispatch: From 61aab54a8d04a4e861d342fff859b3065d625e5a Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Sun, 29 Oct 2023 11:23:00 +0900 Subject: [PATCH 26/33] Update NOTES.txt Signed-off-by: Yasumasa Suenaga --- helm-chart/templates/NOTES.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helm-chart/templates/NOTES.txt b/helm-chart/templates/NOTES.txt index 48bbfd547..1519667b9 100644 --- a/helm-chart/templates/NOTES.txt +++ b/helm-chart/templates/NOTES.txt @@ -6,12 +6,12 @@ {{- end }} {{- end }} {{- else if contains "NodePort" .Values.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "carbon-aware-sdk.fullname" . }}) + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services webapi export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") echo http://$NODE_IP:$NODE_PORT {{- else if contains "LoadBalancer" .Values.service.type }} NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "carbon-aware-sdk.fullname" . }}' + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w webapi export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "carbon-aware-sdk.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") echo http://$SERVICE_IP:{{ .Values.service.port }} {{- else if contains "ClusterIP" .Values.service.type }} From ec06dc7aea1d02ec4728ed9b4272d84cc54b1587 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Sun, 29 Oct 2023 11:25:53 +0900 Subject: [PATCH 27/33] Align appVersion with the tag in GHCR Signed-off-by: Yasumasa Suenaga --- helm-chart/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm-chart/Chart.yaml b/helm-chart/Chart.yaml index 0037e6951..be8609521 100644 --- a/helm-chart/Chart.yaml +++ b/helm-chart/Chart.yaml @@ -21,4 +21,4 @@ version: 1.0.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "1.1.0" +appVersion: "v1.1.0" From 2c7d343debc2c773e606b748c37857c25d6ad0a2 Mon Sep 17 00:00:00 2001 From: Sophie Trinder <144015600+Sophietn@users.noreply.github.com> Date: Wed, 29 Nov 2023 14:57:03 +0300 Subject: [PATCH 28/33] Update CONTRIBUTING.md Signed-off-by: Sophie Trinder <144015600+Sophietn@users.noreply.github.com> --- CONTRIBUTING.md | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b5027ac65..d7085db07 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,25 +1,49 @@ # GSF Member Contribution Guide -Welcome to the GSF Carbon Aware SDK, and thank you for contributing to this +Welcome to the GSF Carbon Aware SDK, and thank you for your interest in contributing to this project. This guide outlines the steps for working within the Carbon Aware SDK and the approved contribution process that members should follow. -**Please contact the project owners for individual contributions. Working Group -meetings and the internal communication channels are only open to GSF Members.** +#### _Before contributing, please read the [GSF Opensource Working Group charter](https://github.com/Green-Software-Foundation/charter/blob/main/charter.md). Any contributions must comply with the charter._ #### ## Table of Contents - [GSF Member Contribution Guide](#gsf-member-contribution-guide) - [Table of Contents](#table-of-contents) - - [Summary Steps](#summary-steps) + - [Current Opportunities](#current-opportunities) + - [How To Get Started](#how-to-get-started) + - [Code Contribution Steps](#code-contribution-steps) - [Public Issues](#public-issues) + - [Collaborating with the OSWG](#collaborating-with-the-opensource-working-group) -## Summary Steps +## Current Opportunities +We have opportunities for both code and non code contributors. -For the following: +We're currently looking for contributions in the following areas: +1. Sample Creation +2. Documentation Updates, including getting docusaurus up and running +3. Video Content Creation (how to enable, demos etc) +4. Slide Deck Creation, available for presenter use, including real time video demo + +## How To Get Started +Introduce yourself on on our [discussions page](https://github.com/orgs/Green-Software-Foundation/discussions/65) and let us know where you think you can help. +Find the Project Key contacts in the [Confluence page](https://greensoftwarefoundation.atlassian.net/wiki/spaces/~612dd45e45cd76006a84071a/pages/17137665/Opensource+Carbon+Aware+SDK). + +GSF member organisation employees should: +Fill out the [Onboarding form](https://greensoftware.foundation/onboarding/) if you are new to the GSF; or +Fill out the [Subscribe form](https://greensoftware.foundation/subscribe/) if you are already part of the GSF but want to join this project. +Following this, you'll receive an invite to join the Carbon Aware SDK Weekly Meeting. + +Only members of the foundation can join meetings, but individual contributions are still welcome on our public Github repo. + +Any questions, email help@greensoftware.foundation. + +## Code Contribution Steps + +For the following code contribution: "Member and "Contributor" refer to the GSF member looking to make a feature -contribution. "Chair" refers to the Chair, Co-Chair or other accountable +code contribution. "Chair" refers to the Chair, Co-Chair or other accountable authority within GSF. 1. Submit a Public Issue using the Issue Template @@ -43,7 +67,7 @@ issue serves as a commitment by the contributor to developing the feature. The Issue is **not** a feature request, but tracks expected feature work. Please do **not** open an issue to request features. -## Collaborating With the WG +## Collaborating With The [Opensource Working Group](https://github.com/Green-Software-Foundation/opensource-wg) 1. Create a [new Issue](https://github.com/Green-Software-Foundation/standards_wg/issues/new) From 84af21efa1cc8c24cff6b4bc22e69266b0faf00e Mon Sep 17 00:00:00 2001 From: Sophie Trinder <144015600+Sophietn@users.noreply.github.com> Date: Wed, 29 Nov 2023 15:09:19 +0300 Subject: [PATCH 29/33] Update CONTRIBUTING.md Signed-off-by: Sophie Trinder <144015600+Sophietn@users.noreply.github.com> --- CONTRIBUTING.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d7085db07..6431f6d3a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,12 +29,15 @@ We're currently looking for contributions in the following areas: Introduce yourself on on our [discussions page](https://github.com/orgs/Green-Software-Foundation/discussions/65) and let us know where you think you can help. Find the Project Key contacts in the [Confluence page](https://greensoftwarefoundation.atlassian.net/wiki/spaces/~612dd45e45cd76006a84071a/pages/17137665/Opensource+Carbon+Aware+SDK). -GSF member organisation employees should: +If you are a GSF member organisation employee, you should: Fill out the [Onboarding form](https://greensoftware.foundation/onboarding/) if you are new to the GSF; or Fill out the [Subscribe form](https://greensoftware.foundation/subscribe/) if you are already part of the GSF but want to join this project. Following this, you'll receive an invite to join the Carbon Aware SDK Weekly Meeting. +Only members of the foundation can join meetings and internal conversations. -Only members of the foundation can join meetings, but individual contributions are still welcome on our public Github repo. +If you are NOT a GSF member organisation employee, individual contributions are still welcome on our public Github repo eg. raising PRs, joining discussions. + +Only our Project Leads have the right to merge PRs. Any questions, email help@greensoftware.foundation. @@ -58,6 +61,11 @@ authority within GSF. for Review" state 7. If the Chair accepts the PR, it merges into `GSF/carbon-aware-sdk/dev` +### Project Release Schedule: +At most once per month. +As frequent as possible. +We prioritise Security release over Feature release. Documentation release is not restricted. + ## Public Issues All contributions to the GSF are tracked through public issues. Please make a From 7f38ae8e57e3ad331a704985d0773a705ecc66f9 Mon Sep 17 00:00:00 2001 From: Dan Benitah Date: Tue, 12 Dec 2023 08:28:38 +0000 Subject: [PATCH 30/33] Update CHANGELOG.md Signed-off-by: Dan Benitah --- CHANGELOG.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 802f5c2ac..a42a4d17a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,39 @@ All notable changes to the Carbon Aware SDK will be documented in this file. -## [1.1.0] - 2023-18-07 +## [1.2.0] - 2023-12-12 + +### Added + +- Helm chart for deployment of the API to Kubernetes. This is available in the `helm` directory. +- + +### Fixed + +- + +### Changed + +- + +#### API + +- + +#### API Deployment + +- + +#### SDK + +- + + +#### Other + +- + +## [1.1.0] - 2023-07-18 ### Added From c1ae2a97981294c9639a42ea3adc82a555dfa479 Mon Sep 17 00:00:00 2001 From: Dan Benitah Date: Tue, 12 Dec 2023 09:35:58 +0000 Subject: [PATCH 31/33] Update CHANGELOG.md with first draft release notes for 1.2 Signed-off-by: Dan Benitah --- CHANGELOG.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a42a4d17a..80f1022f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,16 +6,19 @@ All notable changes to the Carbon Aware SDK will be documented in this file. ### Added -- Helm chart for deployment of the API to Kubernetes. This is available in the `helm` directory. -- +- [#381 Add Helm chart and workflow](https://github.com/Green-Software-Foundation/carbon-aware-sdk/pull/381) +- New package release for Helm charts available at https://github.com/Green-Software-Foundation/carbon-aware-sdk/pkgs/container/charts%2Fcarbon-aware-sdk ### Fixed -- +- [#232 Generating SDK client does not work on linux](https://github.com/Green-Software-Foundation/carbon-aware-sdk/issues/232) ### Changed -- +- [#425 Updating CONTRIBUTING.md](https://github.com/Green-Software-Foundation/carbon-aware-sdk/pull/425) +- [#393 Fix: verify-azure-function-with-packages](https://github.com/Green-Software-Foundation/carbon-aware-sdk/pull/393) +- [#391 fixing 3 broken links in overview.md](https://github.com/Green-Software-Foundation/carbon-aware-sdk/pull/391) +- [#389 EMFree data source should regard specified time range](https://github.com/Green-Software-Foundation/carbon-aware-sdk/pull/389) #### API @@ -32,7 +35,10 @@ All notable changes to the Carbon Aware SDK will be documented in this file. #### Other -- +- Improved process leveraging the project boards at https://github.com/orgs/Green-Software-Foundation/projects/15/views/2 + + +For more details, checkout [https://github.com/Green-Software-Foundation/carbon-aware-sdk/issues/232](https://github.com/Green-Software-Foundation/carbon-aware-sdk/issues?q=label%3Av1.2+is%3Aclosed+) ## [1.1.0] - 2023-07-18 From 28c20e9fac4af3f5b30f11cb6cbf5bb92f02d9a3 Mon Sep 17 00:00:00 2001 From: Dan Benitah Date: Tue, 19 Dec 2023 08:17:09 +0000 Subject: [PATCH 32/33] Update CHANGELOG.md Signed-off-by: Dan Benitah --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80f1022f1..1760c68d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,13 +12,13 @@ All notable changes to the Carbon Aware SDK will be documented in this file. ### Fixed - [#232 Generating SDK client does not work on linux](https://github.com/Green-Software-Foundation/carbon-aware-sdk/issues/232) +- [#393 Fix: verify-azure-function-with-packages](https://github.com/Green-Software-Foundation/carbon-aware-sdk/pull/393) +- [#391 fixing 3 broken links in overview.md](https://github.com/Green-Software-Foundation/carbon-aware-sdk/pull/391) +- [#389 EMFree data source should regard specified time range](https://github.com/Green-Software-Foundation/carbon-aware-sdk/pull/389) ### Changed - [#425 Updating CONTRIBUTING.md](https://github.com/Green-Software-Foundation/carbon-aware-sdk/pull/425) -- [#393 Fix: verify-azure-function-with-packages](https://github.com/Green-Software-Foundation/carbon-aware-sdk/pull/393) -- [#391 fixing 3 broken links in overview.md](https://github.com/Green-Software-Foundation/carbon-aware-sdk/pull/391) -- [#389 EMFree data source should regard specified time range](https://github.com/Green-Software-Foundation/carbon-aware-sdk/pull/389) #### API From ff92ce9b539fa1d433d690599ba741dbeb5e0670 Mon Sep 17 00:00:00 2001 From: Dan Benitah Date: Tue, 9 Jan 2024 10:55:16 +0000 Subject: [PATCH 33/33] Update CHANGELOG.md Updating release date Signed-off-by: Dan Benitah --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1760c68d2..491538c2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Carbon Aware SDK will be documented in this file. -## [1.2.0] - 2023-12-12 +## [1.2.0] - 2024-01 ### Added