diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2589d940..d3de231b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,11 +1,15 @@ name: main -on: [push] +on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Test heroku-18 - run: make test-heroku-18 + - uses: actions/checkout@v4 + - name: Test heroku-20 + run: make test-heroku-20 + - name: Test heroku-22 + run: make test-heroku-22 + - name: Test heroku-24 + run: make test-heroku-24 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d61a49e..682363ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,262 @@ # .NET Core Buildpack Changelog +## 2025-03-11 + +- Updated .NET Core 9.0.200 + +## 2024-11-19 + +- Updated .NET Core 9.0.100 + +## 2024-10-07 + +- Updated .NET Core 8.0.402 + +## 2024-05-15 + +- Updated .NET Core 8.0.300 + +## 2024-02-20 + +- Updated .NET Core 8.0.201 + +## 2023-11-15 + +- Updated .NET Core 8.0.100 + +## 2023-09-15 + +- Updated .NET Core 7.0.401 + +## 2023-08-10 + +- Updated .NET Core 7.0.400 + +## 2023-07-28 + +- Updated .NET Core 7.0.306 + +## 2023-06-14 + +- Updated .NET Core 7.0.304 + +## 2023-04-12 + +- Updated .NET Core 7.0.203 + +## 2023-02-17 + +- Updated .NET Core 7.0.200 + +## 2023-01-26 + +- Updated .NET Core 7.0.102 + +## 2022-11-13 + +- Updated .NET Core 7.0.100 + +## 2022-10-12 + +- Updated .NET Core 7.0.100-rc.2 + +## 2022-09-16 + +- Updated .NET Core 7.0.100-rc.1 + +## 2022-08-10 + +- Updated .NET Core 7.0.100-preview.7 + +## 2022-07-13 + +- Updated .NET Core 7.0.100-preview.6 + +## 2022-05-11 + +- Updated .NET Core 7.0.100-preview.5 + +## 2022-06-15 + +- Updated .NET Core 7.0.100-preview.4 + +## 2022-04-14 + +- Updated .NET Core 7.0.100-preview.3 + +## 2022-03-19 + +- Updated .NET Core 7.0.100-preview.2 + +## 2022-02-18 + +- Updated .NET Core 7.0.100-preview.1 + +## 2022-10-12 + +- Updated .NET SDK 6.0.402 + +## 2022-08-10 + +- Updated .NET SDK 6.0.400 + +## 2022-07-13 + +- Updated .NET SDK 6.0.302 + +## 2022-06-15 + +- Updated .NET SDK 6.0.301 + +## 2022-05-11 + +- Updated .NET SDK 6.0.300 + +## 2022-04-14 + +- Updated .NET SDK 6.0.202 + +## 2022-03-10 + +- Updated .NET SDK 6.0.201 + +## 2022-02-11 + +- Updated .NET SDK 6.0.102 + +## 2021-12-24 + +- Updated .NET SDK 6.0.101 + +## 2021-11-08 + +- Updated .NET 6 + +## 2021-10-13 + +- Updated .NET Core v5.0.402 +- Updated .NET Core 6.0.100-rc.2 + +## 2021-09-15 + +- Updated .NET Core v5.0.401 +- Updated .NET Core 6.0.100-rc.1 + +## 2021-08-12 + +- Updated .NET Core v5.0.400 +- Updated .NET Core v6.0.100-preview.7 + +## 2021-07-15 + +- Updated .NET Core v5.0.302 +- Updated .NET Core v6.0.100-preview.6 + +## 2021-06-18 + +- Updated .NET Core v5.0.301 +- Updated .NET Core v6.0.100-preview.5 + +## 2021-05-26 + +- Updated .NET Core v6.0.100-preview.4 + +## 2021-04-07 + +- Updated .NET Core v6.0.100-preview.4 + +## 2021-04-11 + +- Updated .NET Core v6.0.100-preview.3 + +## 2021-03-12 + + +- Updated .NET Core v5.0.201 + +- Updated .NET Core v6.0.100-preview.2.21155.3 + +## 2021-02-16 + +- Updated .NET Core v5.0.103 + +## 2021-01-13 + +- Updated .NET Core v5.0.102 + +## 2020-12-11 + +- Updated .NET Core v5.0.101 + +## 2020-11-11 + +- Updated .NET Core v5.0.100 + +## 2020-10-14 + +- Updated .NET Core v5.0.100-rc.2 +- Updated .NET Core v3.1.9 + +## 2020-09-15 + +- Updated .NET Core v5.0.100-rc.1 + +## 2020-09-09 + +- Updated .NET Core v3.1.8 + +## 2020-08-26 + +- Updated .NET Core v5.0.100-preview.8 + +## 2020-08-13 + +- Updated .NET Core v3.1.7 + +## 2020-07-15 + +- Updated .NET Core v3.1.6 + +## 2020-06-22 + +- Updated .NET Core v5.0.100-preview.7 + +## 2020-06-26 + +- Updated .NET Core v5.0.100-preview.6 + +## 2020-06-16 + +- Updated .NET Core v3.1.5 + +## 2020-06-10 + +- Updated .NET Core v5.0.100-preview.5 + +## 2020-05-20 + +- Updated .NET Core v5.0.100-preview.4 + +## 2020-05-13 + +- Updated .NET Core v3.1.4 + +## 2020-04-24 + +- Updated .NET Core v5.0.100-preview.3 + +## 2020-04-03 + +- Updated .NET Core v5.0.100-preview.2 + +## 2020-03-26 + +- Updated .NET Core v3.1.3 + +## 2020-03-17 + +- Updated .NET Core v5.0.100-preview.1 + ## 2020-02-20 - Updated .NET Core v3.1.2 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..a0ba0f0d --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,134 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +https://jincod.github.io. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available +at [https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations + diff --git a/Makefile b/Makefile index ffe29859..0d3d97e3 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,18 @@ -.PHONY: test test-heroku-18 test-heroku-16 +.PHONY: test test-heroku-20 -test: test-heroku-18 test-heroku-16 +test: test-heroku-24 -test-heroku-18: - @echo "Running tests in docker (heroku-18)..." - @docker run -v $(shell pwd):/buildpack:ro --rm -e "STACK=heroku-18" heroku/heroku:18 bash -c 'cp -r /buildpack /buildpack_test; cd /buildpack_test/; test/run;' +test-heroku-20: + @echo "Running tests in docker (heroku-20)..." + @docker run -v $(shell pwd):/buildpack:ro --rm -e "STACK=heroku-20" heroku/heroku:20 bash -c 'cp -r /buildpack /buildpack_test; cd /buildpack_test/; test/run;' @echo "" -test-heroku-16: - @echo "Running tests in docker (heroku-16)..." - @docker run -v $(shell pwd):/buildpack:ro --rm -e "STACK=heroku-16" heroku/heroku:16 bash -c 'cp -r /buildpack /buildpack_test; cd /buildpack_test/; test/run;' +test-heroku-22: + @echo "Running tests in docker (heroku-22)..." + @docker run -v $(shell pwd):/buildpack:ro --rm -e "STACK=heroku-22" heroku/heroku:22 bash -c 'cp -r /buildpack /buildpack_test; cd /buildpack_test/; test/run;' + @echo "" + +test-heroku-24: + @echo "Running tests in docker (heroku-24)..." + @docker run -v $(shell pwd):/buildpack:ro --rm -e "STACK=heroku-24" heroku/heroku:24 bash -c 'cp -r /buildpack ~/buildpack_test; cd ~/buildpack_test/; test/run;' @echo "" \ No newline at end of file diff --git a/README.md b/README.md index d042d7d0..f3f1a386 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,12 @@ heroku buildpacks:set jincod/dotnetcore heroku buildpacks:set https://github.com/jincod/dotnetcore-buildpack ``` +### .NET Core Preview release + +``` +heroku buildpacks:set https://github.com/jincod/dotnetcore-buildpack#preview +``` + ### Previous releases ``` @@ -42,6 +48,13 @@ You cannot run migrations with the `dotnet ef` commands using **.NET Local Tools ### Enabling Automatic Migrations +- Ensure there is a .NET local tool manifest file(dotnet-tools.json) which specifies the dotnet-ef tool: + +```bash +dotnet new tool-manifest +dotnet tool install dotnet-ef +``` + - Ensure the `ASPNETCORE_ENVIRONMENT` environment variable is set to `Production`. ASP.NET Core scaffolding tools may create files that explicitly set it to `Development`. Heroku config will override this (`heroku config:set ASPNETCORE_ENVIRONMENT=Production`). - Configure your app to automatically run migrations at startup by adding the following to the `.csproj` file: @@ -50,15 +63,32 @@ You cannot run migrations with the `dotnet ef` commands using **.NET Local Tools ``` - -- Configure your connection string string appropriately, for example, for PostgreSQL: - -`sslmode=Prefer;Trust Server Certificate=true` - ### Manually Running Migration Scripts on the Database - Manually run SQL scripts generated by Entity Framework Core in your app's database. For example, use PG Admin to connect your Heroku Postgres service. +## Setting Connection String for heroku PostgreSQL +If you are using Heroku Postgres addon, then Heroku provides the database connection string as environment variable `DATABASE_URL`. In order to use this in an Npgsql connection string, do something like following: +```c# +using System.Text.RegularExpressions; + +... + +// Replace AppContext with your own DbContext Class +builder.Services.AddDbContext(options => +{ + if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Production") + { + var m = Regex.Match(Environment.GetEnvironmentVariable("DATABASE_URL")!, @"postgres://(.*):(.*)@(.*):(.*)/(.*)"); + options.UseNpgsql($"Server={m.Groups[3]};Port={m.Groups[4]};User Id={m.Groups[1]};Password={m.Groups[2]};Database={m.Groups[5]};sslmode=Prefer;Trust Server Certificate=true"); + } + else // In Development Environment + { + // So, use a local Connection + options.UseNpgsql(builder.Configuration.GetValue("CONNECTION_STRING")); + } +}); +``` ## Node.js and NPM ```bash @@ -68,6 +98,21 @@ heroku buildpacks:add --index 1 heroku/nodejs [Using Multiple Buildpacks for an App](https://devcenter.heroku.com/articles/using-multiple-buildpacks-for-an-app) +## herokuish support + +```bash +heroku config:set HEROKUISH=true +``` + +## Multiple Process Types +If you have multiple projects in a monorepo and wish to treat them as separate process types: +1. Build the projects simultaneously by setting the `PROJECT_FILE` config var to a solution file that references them. +2. Provide a custom `Procfile` that enumerates the desired process types, for example: +```Procfile +web: cd $HOME/heroku_output && ./MySolution.Web +worker: cd $HOME/heroku_output && ./MySolution.Worker +``` + ## Example [ASP.NET Core Demo App](https://github.com/jincod/AspNet5DemoApp) diff --git a/bin/compile b/bin/compile index 68900190..59c053bc 100755 --- a/bin/compile +++ b/bin/compile @@ -7,8 +7,8 @@ set -o pipefail # don't ignore exit codes when piping output set -o nounset # fail on unset variables unset GIT_DIR # Avoid GIT_DIR leak from previous build steps -if [ "$STACK" != "heroku-16" ] && [ "$STACK" != "heroku-18" ]; then - echo "Need heroku-16 or heroku-18 stack" +if [ "$STACK" == "cedar-14" ]; then + echo "cedar-14 isn't supported" exit 1 fi @@ -17,6 +17,7 @@ BUILD_DIR=${1:-} CACHE_DIR=${2:-} ENV_DIR=${3:-} BP_DIR=$(cd $(dirname ${0:-}); cd ..; pwd) +OUTPUT_DIR=${OUTPUT_DIR:-heroku_output} mkdir -p $BUILD_DIR/.profile.d cp $BP_DIR/profile/* $BUILD_DIR/.profile.d/ @@ -29,8 +30,8 @@ export NUGET_XMLDOC_MODE=${NUGET_XMLDOC_MODE:-skip} export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=${DOTNET_SKIP_FIRST_TIME_EXPERIENCE:-1} export DOTNET_CLI_TELEMETRY_OPTOUT=${DOTNET_CLI_TELEMETRY_OPTOUT:-1} -DOTNET_SDK_VERSION=${DOTNET_SDK_VERSION:-3.1.102} -DOTNET_RUNTIME_VERSION=${DOTNET_RUNTIME_VERSION:-3.1.2} +DOTNET_SDK_VERSION=${DOTNET_SDK_VERSION:-9.0.200} +DOTNET_RUNTIME_VERSION=${DOTNET_RUNTIME_VERSION:-9.0.2} BUILD_CONFIGURATION=${BUILD_CONFIGURATION:-Release} info "Installing dotnet" @@ -65,10 +66,10 @@ if [ -n "$(cat $PROJECT_FILE | grep 'netcoreapp2.0')" ]; then fi export NUGET_PACKAGES="${CACHE_DIR}/nuget/cache" -info "publish ${PROJECT_FILE} for ${BUILD_CONFIGURATION}" -dotnet publish $PROJECT_FILE --output ${BUILD_DIR}/heroku_output --configuration ${BUILD_CONFIGURATION} --runtime linux-x64 +info "publish ${PROJECT_FILE} for ${BUILD_CONFIGURATION} on ${OUTPUT_DIR}" +dotnet publish $PROJECT_FILE --output ${BUILD_DIR}/${OUTPUT_DIR} --configuration ${BUILD_CONFIGURATION} --runtime linux-x64 --self-contained -if [ -f ${BUILD_DIR}/Procfile ] && grep -q '^web:' ${BUILD_DIR}/Procfile ; then +if [ -f ${BUILD_DIR}/Procfile ]; then topic "WARNING" echo "Be careful with custom Procfile" | indent else @@ -77,3 +78,8 @@ else web: cd \$HOME/heroku_output && ./${PROJECT_NAME} EOT fi + +if [ -n ${HEROKUISH:-""} ]; then + echo "Override Procfile for herokuish" | indent + echo "web: \$HOME/heroku_output/${PROJECT_NAME}" > ${BUILD_DIR}/Procfile +fi diff --git a/test/fixtures/dotnet-6.0/Program.cs b/test/fixtures/dotnet-6.0/Program.cs new file mode 100644 index 00000000..42ee4532 --- /dev/null +++ b/test/fixtures/dotnet-6.0/Program.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; + +namespace dotnet_6_0 +{ + public class Program + { + public static void Main(string[] args) + { + BuildWebHost(args).Run(); + } + + public static IWebHost BuildWebHost(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup() + .Build(); + } +} diff --git a/test/fixtures/dotnet-6.0/Startup.cs b/test/fixtures/dotnet-6.0/Startup.cs new file mode 100644 index 00000000..c3d335aa --- /dev/null +++ b/test/fixtures/dotnet-6.0/Startup.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace dotnet_6_0 +{ + public class Startup + { + public void ConfigureServices(IServiceCollection services) + { + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.Run(async (context) => + { + await context.Response.WriteAsync("Hello World!"); + }); + } + } +} diff --git a/test/fixtures/dotnet-6.0/dotnet-6.0.csproj b/test/fixtures/dotnet-6.0/dotnet-6.0.csproj new file mode 100644 index 00000000..e948168d --- /dev/null +++ b/test/fixtures/dotnet-6.0/dotnet-6.0.csproj @@ -0,0 +1,7 @@ + + + + net6.0 + + + diff --git a/test/fixtures/dotnetcore-5.0/Program.cs b/test/fixtures/dotnetcore-5.0/Program.cs new file mode 100644 index 00000000..5decf7c7 --- /dev/null +++ b/test/fixtures/dotnetcore-5.0/Program.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; + +namespace dotnetcore_5_0 +{ + public class Program + { + public static void Main(string[] args) + { + BuildWebHost(args).Run(); + } + + public static IWebHost BuildWebHost(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup() + .Build(); + } +} diff --git a/test/fixtures/dotnetcore-5.0/Startup.cs b/test/fixtures/dotnetcore-5.0/Startup.cs new file mode 100644 index 00000000..0120d71a --- /dev/null +++ b/test/fixtures/dotnetcore-5.0/Startup.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace dotnetcore_5_0 +{ + public class Startup + { + public void ConfigureServices(IServiceCollection services) + { + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.Run(async (context) => + { + await context.Response.WriteAsync("Hello World!"); + }); + } + } +} diff --git a/test/fixtures/dotnetcore-5.0/dotnetcore-5.0.csproj b/test/fixtures/dotnetcore-5.0/dotnetcore-5.0.csproj new file mode 100644 index 00000000..dd9e3685 --- /dev/null +++ b/test/fixtures/dotnetcore-5.0/dotnetcore-5.0.csproj @@ -0,0 +1,7 @@ + + + + netcoreapp5.0 + + + diff --git a/test/run b/test/run index 3a97ff5e..525e1398 100755 --- a/test/run +++ b/test/run @@ -42,6 +42,18 @@ testDotNetCore31() { assertCapturedSuccess } +testDotNetCore5() { + compile "dotnetcore-5.0" + assertCaptured "dotnetcore-5.0 ->" + assertCapturedSuccess +} + +testDotNet6() { + compile "dotnet-6.0" + assertCaptured "dotnet-6.0 ->" + assertCapturedSuccess +} + testLocalTools() { compile "local-tools" assertCaptured "Restore was successful."