Skip to content

Commit

Permalink
feat: Fail on cache artifact use (#305)
Browse files Browse the repository at this point in the history
* docs: Update readme since BuildKit is Docker default builder

* build: Chmod as int instead of string

* feat: Manage LintSession and messages

* feat: Error message

* feat: Error message

* style: Format

* fix: Better error management

* test: Add unit tests

* build(deps): Update dependencies

* fix: Some improvments
  • Loading branch information
taorepoara authored Nov 14, 2024
1 parent effb589 commit 6b0033f
Show file tree
Hide file tree
Showing 17 changed files with 876 additions and 403 deletions.
347 changes: 152 additions & 195 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ strict = []
serde = "1.0"
serde_yaml = "0.9.34"
serde_json = { version = "1.0.132", optional = true }
thiserror = "1.0.67"
thiserror = "2.0"
clap = { version = "4.5", features = ["derive"], optional = true }
schemars = { version = "0.8.21", optional = true, features = ["url"] }
regex = "1.11.1"
Expand Down
10 changes: 2 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,7 @@
Dofigen is a Dockerfile generator using a simplified description in YAML or JSON format.
It defines default values and behaviors that simplify the creation of Dockerfiles.

Dofigen is also made to use the Buildkit optimizations that speed-up the Docker image build by parallelizing the layer builds.
It uses the [`--link` option](https://docs.docker.com/engine/reference/builder/#benefits-of-using---link) when adding files and the [`--mount=type=cache` option](https://docs.docker.com/engine/reference/builder/#run---mounttypecache) when running scripts (when you define `caches` attribute).
You can use Buildkit with the [`docker buildx build` subcommand](https://docs.docker.com/engine/reference/commandline/buildx_build/) like this:

```bash
docker buildx build --cache-to=type=local,dest=.dockercache --cache-from=type=local,src=.dockercache -t my-app:latest --load .
```
Dofigen is also made to use the Buildkit, which is now the default Docker build engine, optimizations that speed-up the Docker image build by parallelizing the layer builds.

A french DevOps said about it:
> C'est une bouffée, Dofigen, dans ce monde de con...teneurs.
Expand Down Expand Up @@ -78,7 +72,7 @@ You can download the Dofigen binary from [the release page](https://github.com/l
You can run Dofigen directly from its Docker image with the following command:

```bash
docker run --rm -it -v $(pwd):/app lenra/dofigen
docker run --rm -it -v $(pwd):/app lenra/dofigen --help
```

<p align="right">(<a href="#top">back to top</a>)</p>
Expand Down
4 changes: 2 additions & 2 deletions dofigen.lock
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ effective: |
images: {}
resources:
dofigen.yml:
hash: 07744cc5d5e65e7ebf07298fca4f239bf7296f9109c0fb60b177236291ccf61c
hash: 95a420edbdb40b289e59dda6f5ff2c0295aacf48a229ce39e86fddaa17eea59c
content: |
# Runtime
workdir: /app
Expand All @@ -26,7 +26,7 @@ resources:
copy:
- paths: builds/${TARGETPLATFORM}/dofigen
target: /bin/dofigen
chmod: "555"
chmod: 555
entrypoint: /bin/dofigen
cmd: --help
context:
Expand Down
2 changes: 1 addition & 1 deletion dofigen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ arg:
copy:
- paths: builds/${TARGETPLATFORM}/dofigen
target: /bin/dofigen
chmod: "555"
chmod: 555
entrypoint: /bin/dofigen
cmd: --help
context:
Expand Down
2 changes: 1 addition & 1 deletion src/bin/commands/effective.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct Effective {

impl CliCommand for Effective {
fn run(self) -> Result<()> {
let path = get_file_path(&self.options.file);
let path = get_file_path(&self.options.file)?;
let lockfile_path = get_lockfile_path(path.clone());
let lockfile = load_lockfile(lockfile_path.clone());
let mut context = lockfile
Expand Down
38 changes: 34 additions & 4 deletions src/bin/commands/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
use super::{get_file_path, get_image_from_path, get_lockfile_path, load_lockfile};
use crate::{CliCommand, GlobalOptions};
use clap::Args;
use colored::{Color, Colorize};
use dofigen_lib::{
generate_dockerfile, generate_dockerignore,
generate_dockerignore,
lock::{Lock, LockFile},
DofigenContext, Error, Result,
DofigenContext, Error, GenerationContext, MessageLevel, Result,
};
use std::{fs, path::PathBuf};

Expand Down Expand Up @@ -48,7 +49,7 @@ impl Generate {

impl CliCommand for Generate {
fn run(self) -> Result<()> {
let path = get_file_path(&self.options.file);
let path = get_file_path(&self.options.file)?;
let lockfile_path = get_lockfile_path(path.clone());
let lockfile = load_lockfile(lockfile_path.clone());
let mut context = lockfile
Expand Down Expand Up @@ -88,7 +89,36 @@ impl CliCommand for Generate {
locked_image
};

let dockerfile_content = generate_dockerfile(&dofigen)?;
let mut generation_context = GenerationContext::from(&dofigen);

let dockerfile_content = generation_context.generate_dockerfile(&dofigen)?;

let messages = generation_context.get_lint_messages().clone();

messages.iter().for_each(|message| {
eprintln!(
"{}[path={}]: {}",
match message.level {
MessageLevel::Error => "error".color(Color::Red).bold(),
MessageLevel::Warn => "warning".color(Color::Yellow).bold(),
},
message.path.join(".").color(Color::Blue).bold(),
message.message
);
});

let errors = messages
.iter()
.filter(|m| m.level == MessageLevel::Error)
.count();

if errors > 0 {
return Err(Error::Custom(format!(
"Could not generate the Dockerfile due to {} previous error{}",
errors,
if errors > 1 { "s" } else { "" }
)));
}

if self.output == "-" {
print!("{}", dockerfile_content);
Expand Down
11 changes: 5 additions & 6 deletions src/bin/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use dofigen_lib::{lock::LockFile, Dofigen, DofigenContext, Resource, Result};
use dofigen_lib::{lock::LockFile, Dofigen, DofigenContext, Error, Resource, Result};
use std::path::PathBuf;

pub mod effective;
Expand All @@ -7,17 +7,16 @@ pub mod generate;
pub mod schema;
pub mod update;

pub(crate) fn get_file_path(path: &Option<String>) -> String {
pub(crate) fn get_file_path(path: &Option<String>) -> Result<String> {
if let Some(path) = path {
path.clone()
Ok(path.clone())
} else {
let mut files = vec!["dofigen.yml", "dofigen.yaml", "dofigen.json"];
files.retain(|f| std::path::Path::new(f).exists());
if files.is_empty() {
eprintln!("No Dofigen file found");
std::process::exit(1);
return Err(Error::Custom("No Dofigen file found".into()));
}
files[0].into()
Ok(files[0].into())
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/bin/commands/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub struct Update {
impl CliCommand for Update {
fn run(self) -> Result<()> {
// Get lock file from the file
let path = get_file_path(&self.options.file);
let path = get_file_path(&self.options.file)?;
if path == "-" {
return Err(Error::Custom(
"Update command can't be used with stdin".into(),
Expand Down
3 changes: 2 additions & 1 deletion src/bin/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use clap::{Args, Parser, Subcommand};
use colored::{Color, Colorize};
#[cfg(feature = "json_schema")]
use commands::schema::Schema;
use commands::{effective::Effective, generate::Generate, update::Update};
Expand Down Expand Up @@ -65,7 +66,7 @@ impl Command {

fn main() {
Cli::parse().command.run().unwrap_or_else(|e| {
eprintln!("{}", e);
eprintln!("{}: {}", "error".color(Color::Red).bold(), e);
std::process::exit(1);
});
}
Expand Down
1 change: 1 addition & 0 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub struct DofigenContext {
load_resource_stack: Vec<Resource>,
resources: HashMap<Resource, ResourceVersion>,
used_resources: HashSet<Resource>,

// Images tags
images: HashMap<ImageName, DockerTag>,
used_images: HashSet<ImageName>,
Expand Down
8 changes: 6 additions & 2 deletions src/dofigen_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,10 @@ pub struct Cache {
pub id: Option<String>,

/// The target path of the cache
#[cfg_attr(
not(feature = "strict"),
patch(attribute(serde(alias = "dst", alias = "destination")))
)]
pub target: String,

/// Defines if the cache is readonly
Expand All @@ -253,7 +257,7 @@ pub struct Cache {
#[patch(name = "FromContextPatch", attribute(serde(flatten)))]
pub from: FromContext,

/// Subpath in the from to mount
/// Subpath in the from to mount. Defaults to the root of the from
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<String>,

Expand Down Expand Up @@ -297,7 +301,7 @@ pub struct Bind {
#[patch(name = "FromContextPatch", attribute(serde(flatten)))]
pub from: FromContext,

/// Subpath in the from to mount
/// Source path in the from. Defaults to the root of the from
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<String>,

Expand Down
2 changes: 1 addition & 1 deletion src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub type Result<T, E = Error> = std::result::Result<T, E>;

#[derive(Error, Debug)]
pub enum Error {
#[error("Error while deserializing the document{}: {0}", location_into(.0.location()))]
#[error("Error while deserializing the document{loc}: {0}", loc = location_into(.0.location()))]
Deserialize(#[from] serde_yaml::Error),
#[error("Error while parsing: {0}")]
ParseFromStr(#[from] serde::de::value::Error),
Expand Down
Loading

0 comments on commit 6b0033f

Please sign in to comment.