Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support default web process type #242

Merged
merged 5 commits into from
Mar 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions buildpacks/dotnet/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- The buildpack will now set the process type `web` for a single web application within a solution. When a solution contains multiple web applications, the process type is derived from the project assembly name. ([#242](https://github.com/heroku/buildpacks-dotnet/pull/242))

## [0.3.6] - 2025-03-20

### Changed
Expand Down
64 changes: 61 additions & 3 deletions buildpacks/dotnet/src/launch_process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::dotnet::project::ProjectType;
use crate::dotnet::solution::Solution;
use crate::Project;
use libcnb::data::launch::{Process, ProcessBuilder, ProcessType};
use libcnb::data::process_type;
use std::path::{Path, PathBuf};

/// Detects processes in a solution's projects
Expand All @@ -25,7 +26,23 @@ fn project_launch_process(solution: &Solution, project: &Project) -> Option<Proc

let command = build_command(&relative_executable_path, project.project_type);

Some(ProcessBuilder::new(project_process_type(project), ["bash", "-c", &command]).build())
let process_type = match project.project_type {
// If project is a web application, and there's only one web application in the solution,
// set the process type to `web`.
ProjectType::WebApplication
if solution
.projects
.iter()
.filter(|p| p.project_type == ProjectType::WebApplication)
.count()
== 1 =>
{
process_type!("web")
}
_ => project_process_type(project),
};

Some(ProcessBuilder::new(process_type, ["bash", "-c", &command]).build())
}

/// Constructs the shell command for launching the process
Expand Down Expand Up @@ -111,7 +128,7 @@ mod tests {
}

#[test]
fn test_detect_solution_processes_web_app() {
fn test_detect_solution_processes_single_web_app() {
let solution = Solution {
path: PathBuf::from("/tmp/foo.sln"),
projects: vec![create_test_project(
Expand All @@ -122,7 +139,7 @@ mod tests {
};

let expected_processes = vec![Process {
r#type: process_type!("bar"),
r#type: process_type!("web"),
command: vec![
"bash".to_string(),
"-c".to_string(),
Expand All @@ -136,6 +153,47 @@ mod tests {
assert_eq!(detect_solution_processes(&solution), expected_processes);
}

#[test]
fn test_detect_solution_processes_multiple_web_apps() {
let solution = Solution {
path: PathBuf::from("/tmp/foo.sln"),
projects: vec![
create_test_project("/tmp/bar/bar.csproj", "bar", ProjectType::WebApplication),
create_test_project("/tmp/baz/baz.csproj", "baz", ProjectType::WebApplication),
],
};
assert_eq!(
detect_solution_processes(&solution)
.iter()
.map(|process| process.r#type.clone())
.collect::<Vec<ProcessType>>(),
vec![process_type!("bar"), process_type!("baz")]
);
}

#[test]
fn test_detect_solution_processes_single_web_app_and_console_app() {
let solution = Solution {
path: PathBuf::from("/tmp/foo.sln"),
projects: vec![
create_test_project("/tmp/qux/qux.csproj", "qux", ProjectType::Unknown),
create_test_project("/tmp/bar/bar.csproj", "bar", ProjectType::WebApplication),
create_test_project(
"/tmp/baz/baz.csproj",
"baz",
ProjectType::ConsoleApplication,
),
],
};
assert_eq!(
detect_solution_processes(&solution)
.iter()
.map(|process| process.r#type.clone())
.collect::<Vec<ProcessType>>(),
vec![process_type!("web"), process_type!("baz")]
);
}

#[test]
fn test_detect_solution_processes_with_spaces() {
let solution = Solution {
Expand Down
4 changes: 2 additions & 2 deletions buildpacks/dotnet/tests/dotnet_publish_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ fn test_dotnet_publish_process_registration_with_procfile() {
indoc! { r"
- Process types
- Detecting process types from published artifacts
- Found `foo`: bash -c cd bin/publish; ./foo --urls http://*:$PORT
- Found `web`: bash -c cd bin/publish; ./foo --urls http://*:$PORT
- Procfile detected
- Skipping process type registration (add process types to your Procfile as needed)"}
);
Expand All @@ -120,7 +120,7 @@ fn test_dotnet_publish_process_registration_without_procfile() {
indoc! { r"
- Process types
- Detecting process types from published artifacts
- Found `foo`: bash -c cd bin/publish; ./foo --urls http://*:$PORT
- Found `web`: bash -c cd bin/publish; ./foo --urls http://*:$PORT
- No Procfile detected
- Registering detected process types as launch processes"}
);
Expand Down