-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
22 changed files
with
713 additions
and
910 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,92 +1,75 @@ | ||
use crate::{GradleBuildpack, GradleBuildpackError, GRADLE_TASK_NAME_HEROKU_START_DAEMON}; | ||
use indoc::{formatdoc, indoc}; | ||
use libcnb::build::BuildContext; | ||
use libcnb::data::layer_content_metadata::LayerTypes; | ||
use libcnb::data::layer_name; | ||
use libcnb::generic::GenericMetadata; | ||
use libcnb::layer::{ExistingLayerStrategy, Layer, LayerData, LayerResult, LayerResultBuilder}; | ||
use libcnb::layer::{ | ||
CachedLayerDefinition, InvalidMetadataAction, LayerState, RestoredLayerAction, | ||
}; | ||
use libcnb::layer_env::{LayerEnv, ModificationBehavior, Scope}; | ||
use libcnb::Buildpack; | ||
use libcnb::Env; | ||
use std::fs; | ||
use std::path::Path; | ||
|
||
pub(crate) struct GradleHomeLayer; | ||
|
||
impl Layer for GradleHomeLayer { | ||
type Buildpack = GradleBuildpack; | ||
type Metadata = GenericMetadata; | ||
|
||
fn types(&self) -> LayerTypes { | ||
LayerTypes { | ||
launch: true, | ||
pub(crate) fn handle_gradle_home_layer( | ||
context: &BuildContext<GradleBuildpack>, | ||
env: &mut Env, | ||
) -> libcnb::Result<(), GradleBuildpackError> { | ||
let layer_ref = context.cached_layer( | ||
layer_name!("home"), | ||
CachedLayerDefinition { | ||
build: true, | ||
cache: true, | ||
} | ||
} | ||
launch: true, | ||
invalid_metadata_action: &|_| InvalidMetadataAction::DeleteLayer, | ||
restored_layer_action: &|_: &GenericMetadata, _| RestoredLayerAction::KeepLayer, | ||
}, | ||
)?; | ||
|
||
fn create( | ||
&mut self, | ||
_context: &BuildContext<Self::Buildpack>, | ||
layer_path: &Path, | ||
) -> Result<LayerResult<Self::Metadata>, <Self::Buildpack as Buildpack>::Error> { | ||
// https://docs.gradle.org/8.3/userguide/build_environment.html#sec:gradle_configuration_properties | ||
fs::write( | ||
layer_path.join("gradle.properties"), | ||
indoc! {" | ||
match layer_ref.state { | ||
LayerState::Restored { .. } => { | ||
// Remove daemon metadata from the cached directory. Among other things, it contains a list | ||
// of PIDs from previous runs that will clutter up the output and aren't meaningful with | ||
// containerized builds anyway. | ||
let daemon_dir_path = layer_ref.path().join("daemon"); | ||
if daemon_dir_path.is_dir() { | ||
// We explicitly ignore potential errors since not being able to remove this directory | ||
// should not fail the build as it's mostly for output cosmetics only. | ||
let _ignored_result = fs::remove_dir_all(daemon_dir_path); | ||
} | ||
} | ||
LayerState::Empty { .. } => { | ||
// https://docs.gradle.org/8.3/userguide/build_environment.html#sec:gradle_configuration_properties | ||
fs::write( | ||
layer_ref.path().join("gradle.properties"), | ||
indoc! {" | ||
org.gradle.welcome=never | ||
org.gradle.caching=true | ||
"}, | ||
) | ||
.map_err(GradleBuildpackError::WriteGradlePropertiesError)?; | ||
) | ||
.map_err(GradleBuildpackError::WriteGradlePropertiesError)?; | ||
|
||
// We're adding this empty task to all projects to ensure we have a task we can run when | ||
// we start the Gradle daemon that doesn't side-effect or output anything to the console. | ||
// https://docs.gradle.org/8.3/userguide/init_scripts.html | ||
fs::write( | ||
layer_path.join("init.gradle.kts"), | ||
formatdoc! {" | ||
// We're adding this empty task to all projects to ensure we have a task we can run when | ||
// we start the Gradle daemon that doesn't side-effect or output anything to the console. | ||
// https://docs.gradle.org/8.3/userguide/init_scripts.html | ||
fs::write( | ||
layer_ref.path().join("init.gradle.kts"), | ||
formatdoc! {" | ||
allprojects {{ | ||
tasks.register(\"{task_name}\") | ||
}}", | ||
task_name = GRADLE_TASK_NAME_HEROKU_START_DAEMON | ||
}, | ||
) | ||
.map_err(GradleBuildpackError::WriteGradleInitScriptError)?; | ||
task_name = GRADLE_TASK_NAME_HEROKU_START_DAEMON | ||
}, | ||
) | ||
.map_err(GradleBuildpackError::WriteGradleInitScriptError)?; | ||
|
||
LayerResultBuilder::new(None) | ||
.env(LayerEnv::new().chainable_insert( | ||
layer_ref.write_env(LayerEnv::new().chainable_insert( | ||
Scope::All, | ||
ModificationBehavior::Override, | ||
"GRADLE_USER_HOME", | ||
layer_path, | ||
)) | ||
.build() | ||
} | ||
|
||
fn existing_layer_strategy( | ||
&mut self, | ||
_context: &BuildContext<Self::Buildpack>, | ||
_layer_data: &LayerData<Self::Metadata>, | ||
) -> Result<ExistingLayerStrategy, <Self::Buildpack as Buildpack>::Error> { | ||
Ok(ExistingLayerStrategy::Update) | ||
} | ||
|
||
fn update( | ||
&mut self, | ||
_context: &BuildContext<Self::Buildpack>, | ||
layer_data: &LayerData<Self::Metadata>, | ||
) -> Result<LayerResult<Self::Metadata>, <Self::Buildpack as Buildpack>::Error> { | ||
// Remove daemon metadata from the cached directory. Among other things, it contains a list | ||
// of PIDs from previous runs that will clutter up the output and aren't meaningful with | ||
// containerized builds anyway. | ||
let daemon_dir_path = layer_data.path.join("daemon"); | ||
if daemon_dir_path.is_dir() { | ||
// We explicitly ignore potential errors since not being able to remove this directory | ||
// should not fail the build as it's mostly for output cosmetics only. | ||
let _ignored_result = fs::remove_dir_all(daemon_dir_path); | ||
layer_ref.path(), | ||
))?; | ||
} | ||
|
||
LayerResultBuilder::new(layer_data.content_metadata.metadata.clone()) | ||
.env(layer_data.env.clone()) | ||
.build() | ||
} | ||
|
||
*env = layer_ref.read_env()?.apply(Scope::Build, env); | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.