Skip to content

fix: treat amd64 as equivalent to x86-64 for lifecycle binary selection#2544

Merged
jjbustamante merged 1 commit intobuildpacks:mainfrom
Onyx2406:fix/amd64-lifecycle-arch-warning
Mar 12, 2026
Merged

fix: treat amd64 as equivalent to x86-64 for lifecycle binary selection#2544
jjbustamante merged 1 commit intobuildpacks:mainfrom
Onyx2406:fix/amd64-lifecycle-arch-warning

Conversation

@Onyx2406
Copy link
Contributor

@Onyx2406 Onyx2406 commented Mar 7, 2026

Summary

  • Map amd64 architecture to x86-64 when constructing lifecycle binary download URLs
  • Eliminates the spurious warning on standard AMD64 systems (e.g. GitHub Actions ubuntu-24.04)

Motivation

Fixes #2528 — On AMD64 systems, pack builder create emits a misleading warning:

Warning: failed to find a lifecycle binary for requested architecture 'amd64', defaulting to 'x86-64'

The correct binary was always downloaded since the default is x86-64, but the warning is confusing because amd64 and x86-64 are the same architecture.

Root Cause

uriFromLifecycleVersion checks SupportedLinuxArchitecture(architecture) which only recognizes arm64, ppc64le, and s390x. When the architecture is amd64, it falls to the warning branch even though lifecycle releases name x86-64 binaries as x86-64.

Changes

  • pkg/client/create_builder.go: Normalize amd64x86-64 before the architecture check, and also accept x86-64 as a valid architecture alongside those from SupportedLinuxArchitecture

Test plan

  • amd64 architecture → no warning, downloads x86-64 binary
  • x86-64 architecture → no warning, downloads x86-64 binary
  • arm64, ppc64le, s390x → unchanged behavior
  • Unknown architecture → warning still emitted (unchanged)

@Onyx2406 Onyx2406 requested review from a team as code owners March 7, 2026 18:40
@github-actions github-actions bot added the type/enhancement Issue that requests a new feature or improvement. label Mar 7, 2026
@github-actions github-actions bot added this to the 0.41.0 milestone Mar 7, 2026
Copy link
Member

@jjbustamante jjbustamante left a comment

Choose a reason for hiding this comment

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

Thanks for the fix! Two things to address before this can be merged:

1. DCO failure

The CI check is failing because your commit is missing the required Signed-off-by trailer. You can fix it by amending your commit:

git commit --amend --signoff
git push --force-with-lease

The trailer should look like:

Signed-off-by: Your Name <your-email@example.com>

See the DCO app for more details.


2. Test coverage

The fix should be accompanied by a test. There are already tests following the exact same pattern in pkg/client/create_builder_test.go that you can use as a guide — specifically the arm64 case at line 616:

it("should download from predetermined uri for arm64", func() {
    prepareFetcherWithBuildImage()
    prepareFetcherWithRunImages()
    opts.Config.Lifecycle.URI = ""
    opts.Config.Lifecycle.Version = "3.4.5"
    h.AssertNil(t, fakeBuildImage.SetArchitecture("arm64"))

    mockDownloader.EXPECT().Download(
        gomock.Any(),
        "https://github.com/buildpacks/lifecycle/releases/download/v3.4.5/lifecycle-v3.4.5+linux.arm64.tgz",
    ).Return(
        blob.NewBlob(filepath.Join("testdata", "lifecycle", "platform-0.4")), nil,
    )

    err := subject.CreateBuilder(context.TODO(), opts)
    h.AssertNil(t, err)
})

Please add the following two cases inside the same when("only lifecycle version is provided", ...) block, alongside the existing arm64 test:

Case 1 — amd64 maps to x86-64 with no warning:

it("should download x86-64 lifecycle when architecture is amd64", func() {
    prepareFetcherWithBuildImage()
    prepareFetcherWithRunImages()
    opts.Config.Lifecycle.URI = ""
    opts.Config.Lifecycle.Version = "3.4.5"
    h.AssertNil(t, fakeBuildImage.SetArchitecture("amd64"))

    mockDownloader.EXPECT().Download(
        gomock.Any(),
        "https://github.com/buildpacks/lifecycle/releases/download/v3.4.5/lifecycle-v3.4.5+linux.x86-64.tgz",
    ).Return(
        blob.NewBlob(filepath.Join("testdata", "lifecycle", "platform-0.4")), nil,
    )

    err := subject.CreateBuilder(context.TODO(), opts)
    h.AssertNil(t, err)
    h.AssertNotContains(t, outBuf.String(), "failed to find a lifecycle binary")
})

Case 2 — unknown architecture still emits a warning (regression guard):

it("should warn and default to x86-64 for unknown architecture", func() {
    prepareFetcherWithBuildImage()
    prepareFetcherWithRunImages()
    opts.Config.Lifecycle.URI = ""
    opts.Config.Lifecycle.Version = "3.4.5"
    h.AssertNil(t, fakeBuildImage.SetArchitecture("riscv64"))

    mockDownloader.EXPECT().Download(
        gomock.Any(),
        "https://github.com/buildpacks/lifecycle/releases/download/v3.4.5/lifecycle-v3.4.5+linux.x86-64.tgz",
    ).Return(
        blob.NewBlob(filepath.Join("testdata", "lifecycle", "platform-0.4")), nil,
    )

    err := subject.CreateBuilder(context.TODO(), opts)
    h.AssertNil(t, err)
    h.AssertContains(t, outBuf.String(), "failed to find a lifecycle binary")
})

The h.AssertContains / h.AssertNotContains helpers and outBuf are already available in the test file.

@Onyx2406
Copy link
Contributor Author

Thanks for the fix! Two things to address before this can be merged:

1. DCO failure

The CI check is failing because your commit is missing the required Signed-off-by trailer. You can fix it by amending your commit:

git commit --amend --signoff
git push --force-with-lease

The trailer should look like:

Signed-off-by: Your Name <your-email@example.com>

See the DCO app for more details.

2. Test coverage

The fix should be accompanied by a test. There are already tests following the exact same pattern in pkg/client/create_builder_test.go that you can use as a guide — specifically the arm64 case at line 616:

it("should download from predetermined uri for arm64", func() {
    prepareFetcherWithBuildImage()
    prepareFetcherWithRunImages()
    opts.Config.Lifecycle.URI = ""
    opts.Config.Lifecycle.Version = "3.4.5"
    h.AssertNil(t, fakeBuildImage.SetArchitecture("arm64"))

    mockDownloader.EXPECT().Download(
        gomock.Any(),
        "https://github.com/buildpacks/lifecycle/releases/download/v3.4.5/lifecycle-v3.4.5+linux.arm64.tgz",
    ).Return(
        blob.NewBlob(filepath.Join("testdata", "lifecycle", "platform-0.4")), nil,
    )

    err := subject.CreateBuilder(context.TODO(), opts)
    h.AssertNil(t, err)
})

Please add the following two cases inside the same when("only lifecycle version is provided", ...) block, alongside the existing arm64 test:

Case 1 — amd64 maps to x86-64 with no warning:

it("should download x86-64 lifecycle when architecture is amd64", func() {
    prepareFetcherWithBuildImage()
    prepareFetcherWithRunImages()
    opts.Config.Lifecycle.URI = ""
    opts.Config.Lifecycle.Version = "3.4.5"
    h.AssertNil(t, fakeBuildImage.SetArchitecture("amd64"))

    mockDownloader.EXPECT().Download(
        gomock.Any(),
        "https://github.com/buildpacks/lifecycle/releases/download/v3.4.5/lifecycle-v3.4.5+linux.x86-64.tgz",
    ).Return(
        blob.NewBlob(filepath.Join("testdata", "lifecycle", "platform-0.4")), nil,
    )

    err := subject.CreateBuilder(context.TODO(), opts)
    h.AssertNil(t, err)
    h.AssertNotContains(t, outBuf.String(), "failed to find a lifecycle binary")
})

Case 2 — unknown architecture still emits a warning (regression guard):

it("should warn and default to x86-64 for unknown architecture", func() {
    prepareFetcherWithBuildImage()
    prepareFetcherWithRunImages()
    opts.Config.Lifecycle.URI = ""
    opts.Config.Lifecycle.Version = "3.4.5"
    h.AssertNil(t, fakeBuildImage.SetArchitecture("riscv64"))

    mockDownloader.EXPECT().Download(
        gomock.Any(),
        "https://github.com/buildpacks/lifecycle/releases/download/v3.4.5/lifecycle-v3.4.5+linux.x86-64.tgz",
    ).Return(
        blob.NewBlob(filepath.Join("testdata", "lifecycle", "platform-0.4")), nil,
    )

    err := subject.CreateBuilder(context.TODO(), opts)
    h.AssertNil(t, err)
    h.AssertContains(t, outBuf.String(), "failed to find a lifecycle binary")
})

The h.AssertContains / h.AssertNotContains helpers and outBuf are already available in the test file.

done

@Onyx2406 Onyx2406 requested a review from jjbustamante March 10, 2026 13:13
Map amd64 architecture to x86-64 when constructing lifecycle binary
download URLs to eliminate the spurious warning on standard AMD64
systems. Add tests for amd64 mapping and unknown architecture warning.

Fixes buildpacks#2528

Signed-off-by: Onyx2406 <yashsancheti24@gmail.com>
@Onyx2406 Onyx2406 force-pushed the fix/amd64-lifecycle-arch-warning branch from 6b96b4a to c1956ba Compare March 11, 2026 19:11
Copy link
Member

@jjbustamante jjbustamante left a comment

Choose a reason for hiding this comment

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

LGTM

@jjbustamante jjbustamante merged commit 3237947 into buildpacks:main Mar 12, 2026
15 checks passed
@jjbustamante jjbustamante modified the milestones: 0.41.0, 0.40.2 Mar 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/enhancement Issue that requests a new feature or improvement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Spurious "failed to find a lifecycle binary for requested architecture" warning when using amd64

3 participants