Skip to content

Releases: HewlettPackard/dockerfile-parser-rs

v0.9.0-alpha.1 allow from flags

20 Jul 14:27
e974fa5
Compare
Choose a tag to compare
Pre-release

What's Changed

New Contributors

Thanks

Full Changelog: v0.8.0...v0.9.0-alpha.1

v0.8.0: Track Spans for additional instructions

14 Dec 17:53
a3b7e52
Compare
Choose a tag to compare

What's Changed

Breaking Changes

  • Most instructions that contained a String payload now return a SpannedString struct that includes the Span information as well as the string contents. For now it implements Display and AsRef<str> but no other String-like utilities. String contents should be accessed directly by <spanned_string>.content. Span data is accessed by <spanned_string>.span.
  • Various Instructions now return their data as a combined SpannedString instead of separate String and Span fields. For example, the FromInstruction no longer uses f.image and f.image_span, but can be accessed as f.image.content and f.image.span
  • Span now implements Copy trait which might raise new lint warnings.

New Contributors

Thanks

  • @dsherret for implementing SpannedString features!
  • @jonmcquillan for enabling dependabot configuration and testing version bumps to get this project rolling again

Full Changelog: v0.7.1...v0.8.0-alpha.1

v0.8.0-alpha.1: Track Spans for additional instructions

01 Dec 17:33
a3b7e52
Compare
Choose a tag to compare

What's Changed

Breaking Changes

  • Most instructions that contained a String payload now return a SpannedString struct that includes the Span information as well as the string contents. For now it implements Display and AsRef<str> but no other String-like utilities. String contents should be accessed directly by <spanned_string>.content. Span data is accessed by <spanned_string>.span.
  • Various Instructions now return their data as a combined SpannedString instead of separate String and Span fields. For example, the FromInstruction no longer uses f.image and f.image_span, but can be accessed as f.image.content and f.image.span
  • Span now implements Copy trait which might raise new lint warnings.

New Contributors

Thanks

  • @dsherret for implementing SpannedString features!
  • @jonmcquillan for enabling dependabot configuration and testing version bumps to get this project rolling again

Full Changelog: v0.7.1...v0.8.0-alpha.1

Line continuation overhaul (0.7.1)

02 Nov 23:19
5eff26d
Compare
Choose a tag to compare

Summary of breaking changes

This release changes a number of API datatypes from simple String values to use a new BreakableString wrapper type. The Display implementation should provide equivalent functionality in most cases, except where previous parsed values were technically incorrect (e.g. improperly including comments).

If necessary, simply call .to_string() on any BreakableString value:

let dockerfile = Dockerfile::parse(indoc!(r#"
  FROM alpine
  RUN apk add --no-cache \
      curl
"#)?;

assert_eq!(
  &dockerfile.instructions[1]
    .as_run().unwrap()
    .as_shell().unwrap()
    .to_string(),
  "apk add --no-cache     curl"
);

Comments and spans for individual text segments of any BreakableString value are available in BreakableString.components.

v0.7.1 note

This patch release publicly exports BreakableString as it wasn't made properly available in v0.7.0.

Details

This release improves parsing of line continuations and adds support for embedded comments and empty lines in all positions that support line continuations, for example:

RUN foo && \ 
    # test comment
    bar && \
    baz

CMD [ \
  # comment
  "foo" \
  "bar" \
]

ENV \
  foo=a \
  # comment
  bar=b \

  # empty lines too

  baz=c

COPY \
  --from=foo \
  # comment
  /src \
  /dest

Previously, comments were included inline with actual content in the parse result, if they parsed properly at all (empty lines, multiple unescaped comments, and other situations were not considered valid). Docker strips these comments at runtime so they aren't part of the embedded bash script, but simply stripping these out could make it challenging to modify values while preserving user comments.

Where these continuation-friendly values are directly exposed (e.g. RUN, CMD, ENTRYPOINT, ENV), plain String values have been replaced with BreakableString, a new wrapper type that splits and categorizes all text segments in a broken string along with their text spans. The type's Display implementation omits comments and line continuations to produce a single, joined line that should match what Docker actually executes in, for example, a shell-style RUN instruction.

Additionally, new conversion helper functions have been added to various enum types, particularly Instruction and the various RUN-like instructions:

  • Instruction::into_run() -> Option<RunInstruction>: consumes the instruction and attempts to convert it to its inner value (repeated for all other instruction types; also, as_* for references)
  • RunInstruction::into_shell() -> Option<BreakableString>: consumes the instruction and returns a breakable string if it's a Shell instruction (repeated for CmdInstruction and EntrypointInstruction; similarly supports .as_shell())
  • RunInstruction::into_exec() -> Option<Vec<String>>: as above, but for Exec form

Line continuation overhaul

30 Oct 23:51
ab6b845
Compare
Choose a tag to compare

Summary of breaking changes

This release changes a number of API datatypes from simple String values to use a new BreakableString wrapper type. The Display implementation should provide equivalent functionality in most cases, except where previous parsed values were technically incorrect (e.g. improperly including comments).

If necessary, simply call .to_string() on any BreakableString value:

let dockerfile = Dockerfile::parse(indoc!(r#"
  FROM alpine
  RUN apk add --no-cache \
      curl
"#)?;

assert_eq!(
  &dockerfile.instructions[1]
    .as_run().unwrap()
    .as_shell().unwrap()
    .to_string(),
  "apk add --no-cache     curl"
);

Comments and spans for individual text segments of any BreakableString value are available in BreakableString.components.

Details

This release improves parsing of line continuations and adds support for embedded comments and empty lines in all positions that support line continuations, for example:

RUN foo && \ 
    # test comment
    bar && \
    baz

CMD [ \
  # comment
  "foo" \
  "bar" \
]

ENV \
  foo=a \
  # comment
  bar=b \

  # empty lines too

  baz=c

COPY \
  --from=foo \
  # comment
  /src \
  /dest

Previously, comments were included inline with actual content in the parse result, if they parsed properly at all (empty lines, multiple unescaped comments, and other situations were not considered valid). Docker strips these comments at runtime so they aren't part of the embedded bash script, but simply stripping these out could make it challenging to modify values while preserving user comments.

Where these continuation-friendly values are directly exposed (e.g. RUN, CMD, ENTRYPOINT, ENV), plain String values have been replaced with BreakableString, a new wrapper type that splits and categorizes all text segments in a broken string along with their text spans. The type's Display implementation omits comments and line continuations to produce a single, joined line that should match what Docker actually executes in, for example, a shell-style RUN instruction.

Additionally, new conversion helper functions have been added to various enum types, particularly Instruction and the various RUN-like instructions:

  • Instruction::into_run() -> Option<RunInstruction>: consumes the instruction and attempts to convert it to its inner value (repeated for all other instruction types; also, as_* for references)
  • RunInstruction::into_shell() -> Option<BreakableString>: consumes the instruction and returns a breakable string if it's a Shell instruction (repeated for CmdInstruction and EntrypointInstruction; similarly supports .as_shell())
  • RunInstruction::into_exec() -> Option<Vec<String>>: as above, but for Exec form

Add spans to `ArgInstruction`

19 Oct 20:33
7306008
Compare
Choose a tag to compare

Adds spans to ArgInstruction along with a Dockerfile::get_global_arg(&self, &str) helper function to find a globally- scoped ArgInstruction by name.

Add `resolve_vars_with_context` to find variable names in an image

19 Oct 20:05
87f2970
Compare
Choose a tag to compare

Building on v0.6.0's ImageRef::resolve_vars(&self, &dockerfile), this adds an additional function, ImageRef::resolve_vars_with_context(&self &dockerfile), to additionally return a HashSet of all variables referenced (both directly and indirectly) in the image string.

Additionally, Stage::arg_index(&self, &str) was added to determine if a given stage references a particular ARG, and if so, after which instruction index it becomes available to other instructions within that stage. As the Dockerfile's scoping rules require build stages to redefine all ARGs, the presence of a duplicate ARG instruction should reliably indicate whether or not a build stage actually used a given ARG outside of its FROM.

These two functions can be used together to help determine if a particular ARG is actually used within a given Dockerfile or if a parameterized image string can be automatically replaced with its variable-free equivalent.

Add function to resolve variables in image references

16 Oct 22:55
b14c9dd
Compare
Choose a tag to compare

This release adds a new function to resolve variable substitutions in image references.

For example, given this Dockerfile:

ARG IMAGE=alpine
ARG TAG=3.12
FROM ${IMAGE}:${TAG}

... previously the image would be parsed as:

ImageRef { registry: None, image: "${IMAGE}", tag: Some("${TAG}"), hash: None }

...which is obviously unhelpful. This default behavior remains unchanged, however the new function ImageRef::resolve_vars(&self, &Dockerfile) can be called to resolve these variable references when possible:

let d = Dockerfile::parse(indoc!(r#"
  ARG image=alpine
  ARG unnecessarily_nested=${image}
  ARG tag=3.12
  FROM ${unnecessarily_nested}:${tag}
"#)).unwrap();

let from: &FromInstruction = d.instructions
  .get(3).unwrap()
  .try_into().unwrap();

assert_eq!(
  from.image_parsed.resolve_vars(&d),
  Some(ImageRef::parse("alpine:3.12"))
);

Note that this adds dependencies on regex and lazy_static.

Fix an issue where certain string escapes could cause a stack overflow

15 Oct 21:53
4b1a28c
Compare
Choose a tag to compare

This release includes a fix for an issue where certain quoted strings containing invalid escapes could cause a stack overflow, for example:

ARG FOO="hello\/world"

The error is now properly reported without causing an overflow, however strings like the example are still (for now) considered invalid. Docker may handle invalid escape sequences differently (and seems to consider this particular escape valid despite it being nonsensical).

Properly parse images containing hashes

25 Jun 21:58
3e66e75
Compare
Choose a tag to compare

This release tweaks the image parser to properly handle docker image strings containing hashes or digests, for example:

docker pull hello-world@sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042

This is another minor breaking change for any downstream dependencies that instantiate ImageRef directly in e.g. unit tests, as a new field has been added to the struct.