Skip to content

Conversation

crazy-max
Copy link
Member

@crazy-max crazy-max commented Jul 2, 2025

fixes #3197

Adds unixtimestampparse similar to terraform unix_timestamp_parse function.

cc @sdavids

@crazy-max crazy-max changed the title bake: add rfc339parse function bake: add rfc3339parse function Jul 2, 2025
@sdavids
Copy link

sdavids commented Jul 2, 2025

One uses SOURCE_DATE_EPOCH as follows:

$ SOURCE_DATE_EPOCH=0 docker buildx bake
$ SOURCE_DATE_EPOCH=42 docker buildx bake

Does this PR support this use case?

SOURCE_DATE_EPOCH is used to pass a fixed timestamp from the outside into the build.

Having this rfc3339parse function is appreciated as well …

@crazy-max
Copy link
Member Author

crazy-max commented Jul 2, 2025

One uses SOURCE_DATE_EPOCH as follows:

$ SOURCE_DATE_EPOCH=0 docker buildx bake
$ SOURCE_DATE_EPOCH=42 docker buildx bake

Does this PR support this use case?

SOURCE_DATE_EPOCH is used to pass a fixed timestamp from the outside into the build.

This is already supported as a standardized environment variable

Edit: We only have docs for it in https://docs.docker.com/build/ci/github-actions/reproducible-builds/ but I think we should also have some for build and bake. Maybe in https://docs.docker.com/build/building/variables/#build-tool-configuration-variables. cc @ArthurFlag

@sdavids
Copy link

sdavids commented Jul 2, 2025

Maybe I was not clear enough in #3197:

$ SOURCE_DATE_EPOCH=0 docker buildx bake
labels = {
    "org.opencontainers.image.created" = "how do I get SOURCE_DATE_EPOCH as an RFC3339-formatted string here"
}

The label should look like "org.opencontainers.image.created"="1970-01-01T00:00:00.000Z" and not "org.opencontainers.image.created"="0"

@crazy-max crazy-max force-pushed the bake-rdc339parse branch 2 times, most recently from 33d0ecb to ec0bb73 Compare July 3, 2025 10:35
@crazy-max crazy-max changed the title bake: add rfc3339parse function bake: add rfc3339parse and unixtimestampparse functions Jul 13, 2025
@crazy-max
Copy link
Member Author

crazy-max commented Jul 13, 2025

Maybe I was not clear enough in #3197:

$ SOURCE_DATE_EPOCH=0 docker buildx bake
labels = {
    "org.opencontainers.image.created" = "how do I get SOURCE_DATE_EPOCH as an RFC3339-formatted string here"
}

The label should look like "org.opencontainers.image.created"="1970-01-01T00:00:00.000Z" and not "org.opencontainers.image.created"="0"

Pushed extra commit to add unixtimestampparse similar to terraform unix_timestamp_parse function and update examples in docs: https://github.com/crazy-max/buildx/blob/bake-rdc339parse/docs/bake-stdlib.md#-rfc3339parse

* `year_day` (Number) The day of the year for the timestamp, in the range 1-365 for non-leap years, and 1-366 in leap years.
* `day` (Number) The day of the month for the timestamp.
* `month` (Number) The month of the year for the timestamp.
* `month_name` (String) The name of the month for the timestamp (ex. "January").
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work in different locales?

january/Januar/janvier/Январь/มกราคม

Maybe not expose this attribute even if the underlying implementation supports it?


This comment also applies for weekday_name (and both in unixtimestampparse).

"iso_week": cty.Number,
})),
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
ts := args[0].AsString()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for args to be empty?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it would fail earlier because an arg is required for this func

"iso_week": cty.Number,
})),
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
ts, _ := args[0].AsBigFloat().Int64()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above

Copy link

@sdavids sdavids Jul 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to also handle the error.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to also handle the error.

.Int64() does not return an error as second value but accuracy: https://pkg.go.dev/math/big#Float.Int64

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my note for the tests … someone could conceivably supply the following values -1, 0, 1.2, and "0"

require.Error(t, err)
}

func TestUnixTimestampParseFunc(t *testing.T) {
Copy link

@sdavids sdavids Jul 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to add tests for -1, 0, 1.2, and "0".


func TestRfc3339ParseFunc(t *testing.T) {
fn := rfc3339ParseFunc()
input := cty.StringVal("2024-06-01T15:04:05Z")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to add tests for "" and an syntactically incorrect timestamp.


```hcl
# docker-bake.hcl
variable "BUILD_TIME" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is a convention that we would want to promote. Users should set SOURCE_DATE_EPOCH in the env as UNIX timestamp, not BUILD_TIME as string, so that bake uses the same convention as other apps.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, this was just for example purpose, renamed SOURCE_DATE_EPOCH to BUILD_TIMESTAMP.

* `iso_year` (Number) The ISO 8601 year number.
* `iso_week` (Number) The ISO 8601 week number.

```hcl
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about

variable "SOURCE_DATE_EPOCH" {
  type    = number
  default = formattimestamp("X", "2015-10-21T00:00:00Z")
}

target "default" {
  args = {
    SOURCE_DATE_EPOCH = SOURCE_DATE_EPOCH
    BUILD_TIME = formattimestamp("YYYY-MM-DD'T'00:00:00Z", SOURCE_DATE_EPOCH)
  }
}

I'm also ok for special formatting for rfc3399 for less verbosity.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at forking FormatDateFunc func as they are not willing to accept timestamp format: zclconf/go-cty#130 (comment) but there's quite a lot to fork and it might be better to be aligned so users are not confused. So that's why I opted for the terraform unix_timestamp_parse function func instead.

Copy link
Member

@tonistiigi tonistiigi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(looks like github skipped my main review message, reposing in case it doesn't appear)

Still somewhat confused about this.

  • what is the use case for rfc4449parse? We would want to the SOURCE_DATE_EPOCH to be the source of truth that is picked up from env as that is the convention and that is already unix.
  • Is returning a big struct like these new functions do some kind of convention. Can't find anything similar from current stdlib. The current convention seems to be formatdate. If we don't want to modify formatdate to have the capability to take date as UNIX timestamp (and maybe to return it) then would it make sense to add a new function, eg. formattimestamp that is the superset of the existing function (and then hide/deprecate the previous formatdate).

@crazy-max crazy-max modified the milestones: v0.26.0, v0.27.0 Jul 15, 2025
@crazy-max crazy-max removed this from the v0.27.0 milestone Aug 11, 2025
@crazy-max crazy-max changed the title bake: add rfc3339parse and unixtimestampparse functions bake: add unixtimestampparse function Aug 25, 2025
@crazy-max crazy-max added this to the v0.28.0 milestone Aug 25, 2025
@crazy-max
Copy link
Member Author

(looks like github skipped my main review message, reposing in case it doesn't appear)

Still somewhat confused about this.

  • what is the use case for rfc4449parse? We would want to the SOURCE_DATE_EPOCH to be the source of truth that is picked up from env as that is the convention and that is already unix.

Removed rfc4449parse func and just keep unixtimestampparse one to be consistent with Terraform unix_timestamp_parse function func.

  • Is returning a big struct like these new functions do some kind of convention. Can't find anything similar from current stdlib. The current convention seems to be formatdate. If we don't want to modify formatdate to have the capability to take date as UNIX timestamp (and maybe to return it) then would it make sense to add a new function, eg. formattimestamp that is the superset of the existing function (and then hide/deprecate the previous formatdate).

Yes I think as follow-up we could have a formattimestamp func.

@crazy-max crazy-max requested a review from tonistiigi August 25, 2025 13:08
@tonistiigi tonistiigi modified the milestones: v0.28.0, v0.29.0 Aug 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

buildx bake: provide access to SOURCE_DATE_EPOCH as an RFC3339 timestamp string
3 participants