mirror of https://github.com/helm/helm
Parse SOURCE_DATE_EPOCH in CLI commands and pass it through action.Package and downloader.Manager so library code stays free of environment reads. Invalid values are rejected at the CLI instead of being silently ignored. Signed-off-by: Lohit Kolluri <lohitkolluri@gmail.com>pull/32162/head
parent
4dec37abd2
commit
3e3c7a4ca7
@ -0,0 +1,54 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
chart "helm.sh/helm/v4/internal/chart/v3"
|
||||
)
|
||||
|
||||
// ParseSourceDateEpochValue parses SOURCE_DATE_EPOCH per https://reproducible-builds.org/docs/source-date-epoch/.
|
||||
func ParseSourceDateEpochValue(epochStr string) (time.Time, error) {
|
||||
epoch, err := strconv.ParseInt(epochStr, 10, 64)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
if epoch < 0 {
|
||||
return time.Time{}, strconv.ErrRange
|
||||
}
|
||||
return time.Unix(epoch, 0).UTC(), nil
|
||||
}
|
||||
|
||||
// ApplySourceDateEpoch sets timestamps on the chart (and dependencies) to epoch.
|
||||
func ApplySourceDateEpoch(c *chart.Chart, epoch time.Time) {
|
||||
applySourceDateEpoch(c, epoch)
|
||||
}
|
||||
|
||||
func applySourceDateEpoch(c *chart.Chart, epoch time.Time) {
|
||||
c.ModTime = epoch
|
||||
if len(c.Schema) > 0 {
|
||||
c.SchemaModTime = epoch
|
||||
}
|
||||
if c.Lock != nil {
|
||||
c.Lock.Generated = epoch
|
||||
}
|
||||
|
||||
for _, f := range c.Raw {
|
||||
if f != nil {
|
||||
f.ModTime = epoch
|
||||
}
|
||||
}
|
||||
for _, f := range c.Templates {
|
||||
if f != nil {
|
||||
f.ModTime = epoch
|
||||
}
|
||||
}
|
||||
for _, f := range c.Files {
|
||||
if f != nil {
|
||||
f.ModTime = epoch
|
||||
}
|
||||
}
|
||||
for _, dep := range c.Dependencies() {
|
||||
applySourceDateEpoch(dep, epoch)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
chart "helm.sh/helm/v4/pkg/chart/v2"
|
||||
)
|
||||
|
||||
// ParseSourceDateEpochValue parses SOURCE_DATE_EPOCH per https://reproducible-builds.org/docs/source-date-epoch/.
|
||||
func ParseSourceDateEpochValue(epochStr string) (time.Time, error) {
|
||||
epoch, err := strconv.ParseInt(epochStr, 10, 64)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
if epoch < 0 {
|
||||
return time.Time{}, strconv.ErrRange
|
||||
}
|
||||
return time.Unix(epoch, 0).UTC(), nil
|
||||
}
|
||||
|
||||
// ApplySourceDateEpoch sets timestamps on the chart (and dependencies) to epoch.
|
||||
func ApplySourceDateEpoch(c *chart.Chart, epoch time.Time) {
|
||||
applySourceDateEpoch(c, epoch)
|
||||
}
|
||||
|
||||
func applySourceDateEpoch(c *chart.Chart, epoch time.Time) {
|
||||
c.ModTime = epoch
|
||||
if len(c.Schema) > 0 {
|
||||
c.SchemaModTime = epoch
|
||||
}
|
||||
if c.Lock != nil {
|
||||
c.Lock.Generated = epoch
|
||||
}
|
||||
|
||||
for _, f := range c.Raw {
|
||||
if f != nil {
|
||||
f.ModTime = epoch
|
||||
}
|
||||
}
|
||||
for _, f := range c.Templates {
|
||||
if f != nil {
|
||||
f.ModTime = epoch
|
||||
}
|
||||
}
|
||||
for _, f := range c.Files {
|
||||
if f != nil {
|
||||
f.ModTime = epoch
|
||||
}
|
||||
}
|
||||
for _, dep := range c.Dependencies() {
|
||||
applySourceDateEpoch(dep, epoch)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright The Helm Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
|
||||
)
|
||||
|
||||
// sourceDateEpochFromEnv returns SOURCE_DATE_EPOCH when set, or nil when unset.
|
||||
func sourceDateEpochFromEnv() (*time.Time, error) {
|
||||
epochStr, ok := os.LookupEnv("SOURCE_DATE_EPOCH")
|
||||
if !ok || epochStr == "" {
|
||||
return nil, nil
|
||||
}
|
||||
epoch, err := chartutil.ParseSourceDateEpochValue(epochStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid SOURCE_DATE_EPOCH: %w", err)
|
||||
}
|
||||
return &epoch, nil
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright The Helm Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSourceDateEpochFromEnv(t *testing.T) {
|
||||
t.Setenv("SOURCE_DATE_EPOCH", "1609459200")
|
||||
|
||||
got, err := sourceDateEpochFromEnv()
|
||||
if err != nil {
|
||||
t.Fatalf("sourceDateEpochFromEnv() error: %v", err)
|
||||
}
|
||||
if got == nil {
|
||||
t.Fatal("expected non-nil epoch")
|
||||
}
|
||||
want := time.Unix(1609459200, 0).UTC()
|
||||
if !got.Equal(want) {
|
||||
t.Fatalf("expected %v, got %v", want, *got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSourceDateEpochFromEnvUnset(t *testing.T) {
|
||||
t.Setenv("SOURCE_DATE_EPOCH", "")
|
||||
|
||||
got, err := sourceDateEpochFromEnv()
|
||||
if err != nil {
|
||||
t.Fatalf("sourceDateEpochFromEnv() error: %v", err)
|
||||
}
|
||||
if got != nil {
|
||||
t.Fatalf("expected nil epoch, got %v", *got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSourceDateEpochFromEnvInvalid(t *testing.T) {
|
||||
t.Setenv("SOURCE_DATE_EPOCH", "not-a-number")
|
||||
|
||||
if _, err := sourceDateEpochFromEnv(); err == nil {
|
||||
t.Fatal("expected error for invalid SOURCE_DATE_EPOCH")
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue