diff --git a/.github/workflows/delivery-archlinux.yml b/.github/workflows/delivery-archlinux.yml index fa9a6e695..0a1b66d2e 100644 --- a/.github/workflows/delivery-archlinux.yml +++ b/.github/workflows/delivery-archlinux.yml @@ -18,7 +18,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Determine version - uses: actions/github-script@v6 + uses: actions/github-script@v7 id: version with: result-encoding: string @@ -76,7 +76,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Determine version - uses: actions/github-script@v6 + uses: actions/github-script@v7 id: version with: result-encoding: string @@ -95,7 +95,7 @@ jobs: mkdir -p ${{ env.PACKAGE_NAME }}/ cp .github/workflows/delivery/archlinux/${{ env.PACKAGE_NAME }}/PKGBUILD ${{ env.PACKAGE_NAME }}/PKGBUILD - name: Lookup assets - uses: actions/github-script@v6 + uses: actions/github-script@v7 id: assets with: script: | diff --git a/.github/workflows/delivery-chocolatey.yml b/.github/workflows/delivery-chocolatey.yml index 6531d3819..799b754ac 100644 --- a/.github/workflows/delivery-chocolatey.yml +++ b/.github/workflows/delivery-chocolatey.yml @@ -23,7 +23,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Determine version - uses: actions/github-script@v6 + uses: actions/github-script@v7 id: version with: result-encoding: string @@ -40,7 +40,7 @@ jobs: return updatedTag; - name: Setup working dir run: | - mkdir ${{ env.CHOCO_PATH }} + mkdir -p ${{ env.CHOCO_PATH }}/source cp -r .github/workflows/delivery/chocolatey/. ${{ env.CHOCO_PATH }}/ ls -R ${{ env.CHOCO_PATH }} - name: Download and unzip Pack (Windows) @@ -69,7 +69,7 @@ jobs: - name: build-release uses: crazy-max/ghaction-chocolatey@v3 with: - args: pack ${{ env.CHOCO_PATH }}/pack.nuspec --outputdirectory ${{ env.CHOCO_PATH}} + args: pack ${{ env.CHOCO_PATH }}/pack.nuspec --outputdirectory ${{ env.CHOCO_PATH}}/source - name: list files run: | ls ${{ env.CHOCO_PATH }} @@ -77,10 +77,10 @@ jobs: - name: Test Release uses: crazy-max/ghaction-chocolatey@v3 with: - args: install pack -s ${{ env.CHOCO_PATH }}/pack.${{ env.PACK_VERSION }}.nupkg + args: install pack -s ${{ env.CHOCO_PATH }}/source - name: Ensure Pack Installed run: pack help - name: Upload Release uses: crazy-max/ghaction-chocolatey@v3 with: - args: push ${{ env.CHOCO_PATH }}/pack.${{ env.PACK_VERSION }}.nupkg -s https://push.chocolatey.org/ -k ${{ secrets.CHOCO_KEY }} + args: push ${{ env.CHOCO_PATH }}/source/pack.${{ env.PACK_VERSION }}.nupkg -s https://push.chocolatey.org/ -k ${{ secrets.CHOCO_KEY }} diff --git a/.github/workflows/delivery-docker.yml b/.github/workflows/delivery-docker.yml index 3a9f67eb4..a2f9452d6 100644 --- a/.github/workflows/delivery-docker.yml +++ b/.github/workflows/delivery-docker.yml @@ -34,7 +34,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Determine version - uses: actions/github-script@v6 + uses: actions/github-script@v7 id: version with: result-encoding: string @@ -60,7 +60,7 @@ jobs: password: ${{ secrets.DOCKER_PASSWORD }} - uses: docker/setup-qemu-action@v3 - uses: docker/setup-buildx-action@v3 - - uses: buildpacks/github-actions/setup-tools@v5.5.0 + - uses: buildpacks/github-actions/setup-tools@v5.5.1 - name: Buildx Build/Publish run: | docker buildx build . \ diff --git a/.github/workflows/delivery-homebrew.yml b/.github/workflows/delivery-homebrew.yml index 77ab19249..547f27482 100644 --- a/.github/workflows/delivery-homebrew.yml +++ b/.github/workflows/delivery-homebrew.yml @@ -24,7 +24,7 @@ jobs: - name: Copy pack.rb run: cp .github/workflows/delivery/homebrew/pack.rb homebrew-tap/Formula/pack.rb - name: Lookup assets - uses: actions/github-script@v6 + uses: actions/github-script@v7 id: assets with: script: | diff --git a/.github/workflows/delivery-ubuntu.yml b/.github/workflows/delivery-ubuntu.yml index 6b7d5a87c..49c37f784 100644 --- a/.github/workflows/delivery-ubuntu.yml +++ b/.github/workflows/delivery-ubuntu.yml @@ -32,7 +32,7 @@ jobs: echo "date=$(date +"%a, %d %b %Y %T %z")" >> $GITHUB_OUTPUT - name: Determine version - uses: actions/github-script@v6 + uses: actions/github-script@v7 id: version with: result-encoding: string diff --git a/.github/workflows/privileged-pr-process.yml b/.github/workflows/privileged-pr-process.yml index 3b783d4e6..b1bcd376c 100644 --- a/.github/workflows/privileged-pr-process.yml +++ b/.github/workflows/privileged-pr-process.yml @@ -8,14 +8,14 @@ jobs: label: runs-on: ubuntu-latest steps: - - uses: actions/labeler@main + - uses: actions/labeler@v4 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" add-milestone: runs-on: ubuntu-latest steps: - name: Add milestone - uses: actions/github-script@v6 + uses: actions/github-script@v7 id: assets with: script: | diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index edff79cd4..699092698 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -21,11 +21,11 @@ import ( "github.com/buildpacks/lifecycle/api" dockertypes "github.com/docker/docker/api/types" "github.com/docker/docker/client" - "github.com/ghodss/yaml" "github.com/google/go-containerregistry/pkg/name" "github.com/pelletier/go-toml" "github.com/sclevine/spec" "github.com/sclevine/spec/report" + yaml "gopkg.in/yaml.v3" "github.com/buildpacks/pack/acceptance/assertions" "github.com/buildpacks/pack/acceptance/buildpacks" diff --git a/cmd/cmd.go b/cmd/cmd.go index ace01f3f2..7ece55f1e 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -45,15 +45,16 @@ func NewPackCommand(logger ConfigurableLogger) (*cobra.Command, error) { Short: "CLI for building apps using Cloud Native Buildpacks", PersistentPreRun: func(cmd *cobra.Command, args []string) { if fs := cmd.Flags(); fs != nil { - if flag, err := fs.GetBool("no-color"); err == nil && flag { - color.Disable(flag) + if forceColor, err := fs.GetBool("force-color"); err == nil && !forceColor { + if flag, err := fs.GetBool("no-color"); err == nil && flag { + color.Disable(flag) + } + + _, canDisplayColor := term.IsTerminal(logging.GetWriterForLevel(logger, logging.InfoLevel)) + if !canDisplayColor { + color.Disable(true) + } } - - _, canDisplayColor := term.IsTerminal(logging.GetWriterForLevel(logger, logging.InfoLevel)) - if !canDisplayColor { - color.Disable(true) - } - if flag, err := fs.GetBool("quiet"); err == nil { logger.WantQuiet(flag) } @@ -68,6 +69,7 @@ func NewPackCommand(logger ConfigurableLogger) (*cobra.Command, error) { } rootCmd.PersistentFlags().Bool("no-color", false, "Disable color output") + rootCmd.PersistentFlags().Bool("force-color", false, "Force color output") rootCmd.PersistentFlags().Bool("timestamps", false, "Enable timestamps in output") rootCmd.PersistentFlags().BoolP("quiet", "q", false, "Show less output") rootCmd.PersistentFlags().BoolP("verbose", "v", false, "Show more output") diff --git a/go.mod b/go.mod index 95ac60f31..c4bf64760 100644 --- a/go.mod +++ b/go.mod @@ -12,8 +12,7 @@ require ( github.com/docker/go-connections v0.4.0 github.com/dustin/go-humanize v1.0.1 github.com/gdamore/tcell/v2 v2.6.0 - github.com/ghodss/yaml v1.0.0 - github.com/go-git/go-git/v5 v5.10.0 + github.com/go-git/go-git/v5 v5.10.1 github.com/golang/mock v1.6.0 github.com/google/go-cmp v0.6.0 github.com/google/go-containerregistry v0.16.1 @@ -21,7 +20,7 @@ require ( github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 github.com/heroku/color v0.0.6 github.com/mitchellh/ioprogress v0.0.0-20180201004757-6a23b12fa88e - github.com/onsi/gomega v1.29.0 + github.com/onsi/gomega v1.30.0 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0-rc5 github.com/pelletier/go-toml v1.9.5 @@ -29,13 +28,13 @@ require ( github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 github.com/sclevine/spec v1.4.0 - github.com/spf13/cobra v1.7.0 - golang.org/x/crypto v0.14.0 - golang.org/x/mod v0.13.0 - golang.org/x/oauth2 v0.13.0 - golang.org/x/sync v0.4.0 - golang.org/x/term v0.13.0 - golang.org/x/text v0.13.0 + github.com/spf13/cobra v1.8.0 + golang.org/x/crypto v0.16.0 + golang.org/x/mod v0.14.0 + golang.org/x/oauth2 v0.15.0 + golang.org/x/sync v0.5.0 + golang.org/x/term v0.15.0 + golang.org/x/text v0.14.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -52,7 +51,6 @@ require ( github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect - github.com/acomagu/bufpipe v1.0.4 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/aws/aws-sdk-go-v2 v1.18.1 // indirect github.com/aws/aws-sdk-go-v2/config v1.18.27 // indirect @@ -110,17 +108,16 @@ require ( github.com/rivo/uniseg v0.4.3 // indirect github.com/sergi/go-diff v1.2.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/skeema/knownhosts v1.2.0 // indirect + github.com/skeema/knownhosts v1.2.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/vbatts/tar-split v0.11.3 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.15.0 // indirect golang.org/x/tools v0.13.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gotest.tools/v3 v3.4.0 // indirect ) diff --git a/go.sum b/go.sum index 9e8069522..ad486a673 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,6 @@ github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5 github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek= github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= -github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= -github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= @@ -95,8 +93,6 @@ github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20230522190001-adf1bafd791a h1:rW+dV12c0WD3+O4Zs8Qt4+oqnr8ecXeyg8g3yB73ZKA= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20230522190001-adf1bafd791a/go.mod h1:1mvdZLjy932pV2fhj1jjwUSHaF5Ogq2gk5bvi/6ngEU= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= -github.com/buildpacks/imgutil v0.0.0-20230626185301-726f02e4225c h1:HlRuSz+JGAzudNtNCfHIzXe0AEuHX6Vx8uZgmjvX02o= -github.com/buildpacks/imgutil v0.0.0-20230626185301-726f02e4225c/go.mod h1:mBG5M3GJW5nknCEOOqtmMHyPYnSpw/5GEiciuYU/COw= github.com/buildpacks/imgutil v0.0.0-20231102131059-84d632186b59 h1:5g+dMdOO6Ufx/bDa5gUH/Aw9FN6wt7T3HzKSkHVvue4= github.com/buildpacks/imgutil v0.0.0-20231102131059-84d632186b59/go.mod h1:PsazEB9yz+NG/cgm0Z1oQ0Xq6rD/U7eNMt5Su41afYY= github.com/buildpacks/lifecycle v0.17.2 h1:CfJYWHIC5v996idgjDamYHBTk+G+c1Qt7Yk80MlbWpw= @@ -113,6 +109,7 @@ github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNA github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY= github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= @@ -146,16 +143,14 @@ github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo github.com/gdamore/tcell/v2 v2.4.1-0.20210905002822-f057f0a857a1/go.mod h1:Az6Jt+M5idSED2YPGtwnfJV0kXohgdCBPmHGSYc1r04= github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg= github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git/v5 v5.10.0 h1:F0x3xXrAWmhwtzoCokU4IMPcBdncG+HAAqi9FcOOjbQ= -github.com/go-git/go-git/v5 v5.10.0/go.mod h1:1FOZ/pQnqw24ghP2n7cunVl0ON55BsjPYvhWHvZGhoo= +github.com/go-git/go-git/v5 v5.10.1 h1:tu8/D8i+TWxgKpzQ3Vc43e+kkhXqtsZCKI/egajKnxk= +github.com/go-git/go-git/v5 v5.10.1/go.mod h1:uEuHjxkHap8kAl//V5F/nNWwqIYtP/402ddd05mp0wg= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= @@ -221,8 +216,6 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= -github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -254,8 +247,8 @@ github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= -github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= @@ -292,13 +285,13 @@ github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM= -github.com/skeema/knownhosts v1.2.0/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo= +github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= +github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -341,15 +334,15 @@ golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -364,11 +357,11 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= -golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -376,8 +369,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -405,8 +398,8 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -414,8 +407,8 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -424,8 +417,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/internal/build/lifecycle_execution.go b/internal/build/lifecycle_execution.go index 716317725..1180771d8 100644 --- a/internal/build/lifecycle_execution.go +++ b/internal/build/lifecycle_execution.go @@ -239,9 +239,16 @@ func (l *LifecycleExecution) Run(ctx context.Context, phaseFactoryCreator PhaseF } } + var ( + ephemeralRunImage string + err error + ) currentRunImage := l.runImageAfterExtensions() - if currentRunImage != "" && currentRunImage != l.opts.RunImage { - if err := l.opts.FetchRunImage(currentRunImage); err != nil { + if l.runImageChanged() || l.hasExtensionsForRun() { + if currentRunImage == "" { // sanity check + return nil + } + if ephemeralRunImage, err = l.opts.FetchRunImageWithLifecycleLayer(currentRunImage); err != nil { return err } } @@ -269,7 +276,7 @@ func (l *LifecycleExecution) Run(ctx context.Context, phaseFactoryCreator PhaseF if l.platformAPI.AtLeast("0.12") && l.hasExtensionsForRun() { group.Go(func() error { l.logger.Info(style.Step("EXTENDING (RUN)")) - return l.ExtendRun(ctx, kanikoCache, phaseFactory) + return l.ExtendRun(ctx, kanikoCache, phaseFactory, ephemeralRunImage) }) } @@ -518,8 +525,6 @@ func (l *LifecycleExecution) Restore(ctx context.Context, buildCache Cache, kani l.withLogLevel()..., ), WithNetwork(l.opts.Network), - If(l.hasExtensionsForRun(), WithPostContainerRunOperations( - CopyOutToMaybe(l.mountPaths.cnbDir(), l.tmpDir))), // FIXME: this is hacky; we should get the lifecycle binaries from the lifecycle image cacheBindOp, dockerOp, flagsOp, @@ -712,7 +717,7 @@ func (l *LifecycleExecution) ExtendBuild(ctx context.Context, kanikoCache Cache, return extend.Run(ctx) } -func (l *LifecycleExecution) ExtendRun(ctx context.Context, kanikoCache Cache, phaseFactory PhaseFactory) error { +func (l *LifecycleExecution) ExtendRun(ctx context.Context, kanikoCache Cache, phaseFactory PhaseFactory, runImageName string) error { flags := []string{"-app", l.mountPaths.appDir(), "-kind", "run"} configProvider := NewPhaseConfigProvider( @@ -725,8 +730,7 @@ func (l *LifecycleExecution) ExtendRun(ctx context.Context, kanikoCache Cache, p WithFlags(flags...), WithNetwork(l.opts.Network), WithRoot(), - WithImage(l.runImageAfterExtensions()), - WithBinds(fmt.Sprintf("%s:%s", filepath.Join(l.tmpDir, "cnb"), l.mountPaths.cnbDir())), + WithImage(runImageName), WithBinds(fmt.Sprintf("%s:%s", kanikoCache.Name(), l.mountPaths.kanikoCacheDir())), ) diff --git a/internal/build/lifecycle_execution_test.go b/internal/build/lifecycle_execution_test.go index 7902d9ee3..99db923b5 100644 --- a/internal/build/lifecycle_execution_test.go +++ b/internal/build/lifecycle_execution_test.go @@ -124,7 +124,7 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) { calledWithArgAtCall: make(map[int]string), } withFakeFetchRunImageFunc := func(opts *build.LifecycleOptions) { - opts.FetchRunImage = newFakeFetchRunImageFunc(&fakeFetcher) + opts.FetchRunImageWithLifecycleLayer = newFakeFetchRunImageFunc(&fakeFetcher) } lifecycleOps = append(lifecycleOps, fakes.WithBuilder(fakeBuilder), withFakeFetchRunImageFunc) @@ -1971,7 +1971,7 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) { when("#ExtendRun", func() { it.Before(func() { - err := lifecycle.ExtendRun(context.Background(), fakeKanikoCache, fakePhaseFactory) + err := lifecycle.ExtendRun(context.Background(), fakeKanikoCache, fakePhaseFactory, "some-run-image") h.AssertNil(t, err) lastCallIndex := len(fakePhaseFactory.NewCalledWithProvider) - 1 @@ -1990,15 +1990,6 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) { h.AssertEq(t, configProvider.ContainerConfig().Image, "some-run-image") }) - when("extensions change the run image", func() { - extensionsRunImage = "some-new-run-image" - providedOrderExt = dist.Order{dist.OrderEntry{Group: []dist.ModuleRef{ /* don't care */ }}} - - it("runs the phase with the new run image", func() { - h.AssertEq(t, configProvider.ContainerConfig().Image, "some-new-run-image") - }) - }) - it("configures the phase with the expected arguments", func() { h.AssertSliceContainsInOrder(t, configProvider.ContainerConfig().Entrypoint, "") // the run image may have an entrypoint configured, override it h.AssertSliceContainsInOrder(t, configProvider.ContainerConfig().Cmd, "-log-level", "debug") @@ -2008,7 +1999,7 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) { it("configures the phase with binds", func() { expectedBinds := providedVolumes - expectedBinds = append(expectedBinds, "some-kaniko-cache:/kaniko", fmt.Sprintf("%s:/cnb", filepath.Join(tmpDir, "cnb"))) + expectedBinds = append(expectedBinds, "some-kaniko-cache:/kaniko") h.AssertSliceContains(t, configProvider.HostConfig().Binds, expectedBinds...) }) @@ -2453,9 +2444,9 @@ func newFakeImageCache() *fakes.FakeCache { return c } -func newFakeFetchRunImageFunc(f *fakeImageFetcher) func(name string) error { - return func(name string) error { - return f.fetchRunImage(name) +func newFakeFetchRunImageFunc(f *fakeImageFetcher) func(name string) (string, error) { + return func(name string) (string, error) { + return fmt.Sprintf("ephemeral-%s", name), f.fetchRunImage(name) } } diff --git a/internal/build/lifecycle_executor.go b/internal/build/lifecycle_executor.go index e3dd7d00d..9a20a926d 100644 --- a/internal/build/lifecycle_executor.go +++ b/internal/build/lifecycle_executor.go @@ -66,40 +66,40 @@ type Termui interface { } type LifecycleOptions struct { - AppPath string - Image name.Reference - Builder Builder - BuilderImage string // differs from Builder.Name() and Builder.Image().Name() in that it includes the registry context - LifecycleImage string - LifecycleApis []string // optional - populated only if custom lifecycle image is downloaded, from that lifecycle's container's Labels. - RunImage string - FetchRunImage func(name string) error - ProjectMetadata files.ProjectMetadata - ClearCache bool - Publish bool - TrustBuilder bool - UseCreator bool - Interactive bool - Layout bool - Termui Termui - DockerHost string - Cache cache.CacheOpts - CacheImage string - HTTPProxy string - HTTPSProxy string - NoProxy string - Network string - AdditionalTags []string - Volumes []string - DefaultProcessType string - FileFilter func(string) bool - Workspace string - GID int - PreviousImage string - ReportDestinationDir string - SBOMDestinationDir string - CreationTime *time.Time - Keychain authn.Keychain + AppPath string + Image name.Reference + Builder Builder + BuilderImage string // differs from Builder.Name() and Builder.Image().Name() in that it includes the registry context + LifecycleImage string + LifecycleApis []string // optional - populated only if custom lifecycle image is downloaded, from that lifecycle's container's Labels. + RunImage string + FetchRunImageWithLifecycleLayer func(name string) (string, error) + ProjectMetadata files.ProjectMetadata + ClearCache bool + Publish bool + TrustBuilder bool + UseCreator bool + Interactive bool + Layout bool + Termui Termui + DockerHost string + Cache cache.CacheOpts + CacheImage string + HTTPProxy string + HTTPSProxy string + NoProxy string + Network string + AdditionalTags []string + Volumes []string + DefaultProcessType string + FileFilter func(string) bool + Workspace string + GID int + PreviousImage string + ReportDestinationDir string + SBOMDestinationDir string + CreationTime *time.Time + Keychain authn.Keychain } func NewLifecycleExecutor(logger logging.Logger, docker DockerClient) *LifecycleExecutor { diff --git a/internal/build/mount_paths.go b/internal/build/mount_paths.go index 525a90003..ad4bd9113 100644 --- a/internal/build/mount_paths.go +++ b/internal/build/mount_paths.go @@ -30,10 +30,6 @@ func (m mountPaths) join(parts ...string) string { return strings.Join(parts, m.separator) } -func (m mountPaths) cnbDir() string { - return m.join(m.volume, "cnb") -} - func (m mountPaths) layersDir() string { return m.join(m.volume, "layers") } diff --git a/internal/build/phase_config_provider.go b/internal/build/phase_config_provider.go index 93861633a..15434c7a7 100644 --- a/internal/build/phase_config_provider.go +++ b/internal/build/phase_config_provider.go @@ -66,7 +66,7 @@ func NewPhaseConfigProvider(name string, lifecycleExec *LifecycleExecution, ops provider.ctrConf.Entrypoint = []string{""} // override entrypoint in case it is set provider.ctrConf.Cmd = append([]string{"/cnb/lifecycle/" + name}, provider.ctrConf.Cmd...) - lifecycleExec.logger.Debugf("Running the %s on OS %s with:", style.Symbol(provider.Name()), style.Symbol(provider.os)) + lifecycleExec.logger.Debugf("Running the %s on OS %s from image %s with:", style.Symbol(provider.Name()), style.Symbol(provider.os), style.Symbol(provider.ctrConf.Image)) lifecycleExec.logger.Debug("Container Settings:") lifecycleExec.logger.Debugf(" Args: %s", style.Symbol(strings.Join(provider.ctrConf.Cmd, " "))) lifecycleExec.logger.Debugf(" System Envs: %s", style.Symbol(strings.Join(sanitized(provider.ctrConf.Env), " "))) diff --git a/internal/builder/writer/yaml_test.go b/internal/builder/writer/yaml_test.go index e1450922b..3ab2c9156 100644 --- a/internal/builder/writer/yaml_test.go +++ b/internal/builder/writer/yaml_test.go @@ -6,13 +6,12 @@ import ( "fmt" "testing" - "github.com/ghodss/yaml" - "github.com/Masterminds/semver" "github.com/buildpacks/lifecycle/api" "github.com/heroku/color" "github.com/sclevine/spec" "github.com/sclevine/spec/report" + yaml "gopkg.in/yaml.v3" pubbldr "github.com/buildpacks/pack/builder" "github.com/buildpacks/pack/internal/builder" diff --git a/pkg/blob/downloader.go b/pkg/blob/downloader.go index c082669ad..9e00d97c1 100644 --- a/pkg/blob/downloader.go +++ b/pkg/blob/downloader.go @@ -57,6 +57,10 @@ func (d *downloader) Download(ctx context.Context, pathOrURI string) (Blob, erro path, err = paths.URIToFilePath(pathOrURI) case "http", "https": path, err = d.handleHTTP(ctx, pathOrURI) + if err != nil { + // retry as we sometimes see `wsarecv: An existing connection was forcibly closed by the remote host.` on Windows + path, err = d.handleHTTP(ctx, pathOrURI) + } default: err = fmt.Errorf("unsupported protocol %s in URI %s", style.Symbol(parsedURL.Scheme), style.Symbol(pathOrURI)) } diff --git a/pkg/blob/downloader_test.go b/pkg/blob/downloader_test.go index f4c97e29e..e1bc7952c 100644 --- a/pkg/blob/downloader_test.go +++ b/pkg/blob/downloader_test.go @@ -141,6 +141,10 @@ func testDownloader(t *testing.T, when spec.G, it spec.S) { server.AppendHandlers(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(404) }) + + server.AppendHandlers(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(404) + }) }) it("should return error", func() { diff --git a/pkg/client/build.go b/pkg/client/build.go index 4371e311b..2cc15a390 100644 --- a/pkg/client/build.go +++ b/pkg/client/build.go @@ -1,10 +1,14 @@ package client import ( + "archive/tar" "context" "crypto/rand" + "crypto/sha256" + "encoding/hex" "encoding/json" "fmt" + "io" "os" "path/filepath" "runtime" @@ -12,8 +16,6 @@ import ( "strings" "time" - "github.com/buildpacks/pack/buildpackage" - "github.com/Masterminds/semver" "github.com/buildpacks/imgutil" "github.com/buildpacks/imgutil/layout" @@ -26,6 +28,7 @@ import ( "github.com/pkg/errors" ignore "github.com/sabhiram/go-gitignore" + "github.com/buildpacks/pack/buildpackage" "github.com/buildpacks/pack/internal/build" "github.com/buildpacks/pack/internal/builder" internalConfig "github.com/buildpacks/pack/internal/config" @@ -509,10 +512,6 @@ func (c *Client) Build(ctx context.Context, opts BuildOptions) error { } } - fetchRunImage := func(name string) error { - _, err := c.imageFetcher.Fetch(ctx, name, fetchOptions) - return err - } lifecycleOpts := build.LifecycleOptions{ AppPath: appPath, Image: imageRef, @@ -520,7 +519,6 @@ func (c *Client) Build(ctx context.Context, opts BuildOptions) error { BuilderImage: builderRef.Name(), LifecycleImage: ephemeralBuilder.Name(), RunImage: runImageName, - FetchRunImage: fetchRunImage, ProjectMetadata: projectMetadata, ClearCache: opts.ClearCache, Publish: opts.Publish, @@ -559,6 +557,140 @@ func (c *Client) Build(ctx context.Context, opts BuildOptions) error { return errors.Errorf("Lifecycle %s does not have an associated lifecycle image. Builder must be trusted.", lifecycleVersion.String()) } + lifecycleOpts.FetchRunImageWithLifecycleLayer = func(runImageName string) (string, error) { + ephemeralRunImageName := fmt.Sprintf("pack.local/run-image/%x:latest", randString(10)) + runImage, err := c.imageFetcher.Fetch(ctx, runImageName, fetchOptions) + if err != nil { + return "", err + } + ephemeralRunImage, err := local.NewImage(ephemeralRunImageName, c.docker, local.FromBaseImage(runImage.Name())) + if err != nil { + return "", err + } + tmpDir, err := os.MkdirTemp("", "extend-run-image-scratch") // we need to write to disk because manifest.json is last in the tar + if err != nil { + return "", err + } + defer os.RemoveAll(tmpDir) + lifecycleImageTar, err := func() (string, error) { + lifecycleImageTar := filepath.Join(tmpDir, "lifecycle-image.tar") + lifecycleImageReader, err := c.docker.ImageSave(context.Background(), []string{lifecycleOpts.LifecycleImage}) // this is fast because the lifecycle image is based on distroless static + if err != nil { + return "", err + } + defer lifecycleImageReader.Close() + lifecycleImageWriter, err := os.Create(lifecycleImageTar) + if err != nil { + return "", err + } + defer lifecycleImageWriter.Close() + if _, err = io.Copy(lifecycleImageWriter, lifecycleImageReader); err != nil { + return "", err + } + return lifecycleImageTar, nil + }() + if err != nil { + return "", err + } + advanceTarToEntryWithName := func(tarReader *tar.Reader, wantName string) (*tar.Header, error) { + var ( + header *tar.Header + err error + ) + for { + header, err = tarReader.Next() + if err == io.EOF { + break + } + if err != nil { + return nil, err + } + if header.Name != wantName { + continue + } + return header, nil + } + return nil, fmt.Errorf("failed to find header with name: %s", wantName) + } + lifecycleLayerName, err := func() (string, error) { + lifecycleImageReader, err := os.Open(lifecycleImageTar) + if err != nil { + return "", err + } + defer lifecycleImageReader.Close() + tarReader := tar.NewReader(lifecycleImageReader) + if _, err = advanceTarToEntryWithName(tarReader, "manifest.json"); err != nil { + return "", err + } + type descriptor struct { + Layers []string + } + type manifestJSON []descriptor + var manifestContents manifestJSON + if err = json.NewDecoder(tarReader).Decode(&manifestContents); err != nil { + return "", err + } + if len(manifestContents) < 1 { + return "", errors.New("missing manifest entries") + } + return manifestContents[0].Layers[len(manifestContents[0].Layers)-1], nil // we can assume the lifecycle layer is the last in the tar + }() + if err != nil { + return "", err + } + if lifecycleLayerName == "" { + return "", errors.New("failed to find lifecycle layer") + } + lifecycleLayerTar, err := func() (string, error) { + lifecycleImageReader, err := os.Open(lifecycleImageTar) + if err != nil { + return "", err + } + defer lifecycleImageReader.Close() + tarReader := tar.NewReader(lifecycleImageReader) + var header *tar.Header + if header, err = advanceTarToEntryWithName(tarReader, lifecycleLayerName); err != nil { + return "", err + } + lifecycleLayerTar := filepath.Join(filepath.Dir(lifecycleImageTar), filepath.Dir(lifecycleLayerName)+".tar") + lifecycleLayerWriter, err := os.OpenFile(lifecycleLayerTar, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode)) + if err != nil { + return "", err + } + defer lifecycleLayerWriter.Close() + if _, err = io.Copy(lifecycleLayerWriter, tarReader); err != nil { + return "", err + } + return lifecycleLayerTar, nil + }() + if err != nil { + return "", err + } + diffID, err := func() (string, error) { + lifecycleLayerReader, err := os.Open(lifecycleLayerTar) + if err != nil { + return "", err + } + defer lifecycleLayerReader.Close() + hasher := sha256.New() + if _, err = io.Copy(hasher, lifecycleLayerReader); err != nil { + return "", err + } + // it's weird that this doesn't match lifecycleLayerTar + return hex.EncodeToString(hasher.Sum(nil)), nil + }() + if err != nil { + return "", err + } + if err = ephemeralRunImage.AddLayerWithDiffID(lifecycleLayerTar, "sha256:"+diffID); err != nil { + return "", err + } + if err = ephemeralRunImage.Save(); err != nil { + return "", err + } + return ephemeralRunImageName, nil + } + if err = c.lifecycleExecutor.Execute(ctx, lifecycleOpts); err != nil { return fmt.Errorf("executing lifecycle: %w", err) }