Skip to content
12 changes: 12 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,15 @@ jobs:
with:
go-version-file: go.mod
- run: go run github.com/onsi/ginkgo/v2/ginkgo run -r --keep-going --skip-package integration

cross-compile-linux-arm64: # <- name

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It might be nice to apply a similar matrix patters in this GH action as in https://github.com/cloudfoundry/bosh-dns-release/pull/184/changes

# Verifies the agent cross-compiles for linux/arm64 (AWS Graviton and other
# ARM64 targets). Pure-Go build, so this runs on the standard amd64 runner
# and needs no ARM64 hardware.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v7
with:
go-version-file: go.mod
- run: GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build ./...
9 changes: 9 additions & 0 deletions bin/build-linux-arm64
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -eu -o pipefail

ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"

export GOARCH=arm64
export GOOS=linux

"${ROOT_DIR}/bin/build"
50 changes: 42 additions & 8 deletions ci/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
# Image providing the BOSH-packaged Go toolchain. Overridable so arm64 builds can
# use the arm64 golang-release image (tag "latest-arm64"). The default is the
# exact amd64 image used today, so the amd64 build is unchanged.
# RFC: https://github.com/cloudfoundry/community/pull/1530
ARG GOLANG_RELEASE_IMAGE=ghcr.io/cloudfoundry/bosh/golang-release
FROM ${GOLANG_RELEASE_IMAGE} AS golang-release

FROM ubuntu
ARG BOSH_CLI_VERSION
ARG CREDHUB_CLI_VERSION
ARG JQ_VERSION

# TARGETARCH is provided automatically by BuildKit (e.g. "amd64", "arm64") and
# lets this image build for arm64 (Graviton) in addition to amd64. It defaults
# to amd64 so a plain `docker build` without BuildKit reproduces today's image.
# RFC: cloudfoundry/community#1530.
ARG TARGETARCH=amd64
Comment thread
vighes marked this conversation as resolved.
Resolved

RUN \
apt-get update \
&& apt-get -y upgrade \
Expand All @@ -18,17 +31,38 @@ RUN \
shellcheck \
&& apt-get clean


RUN wget -nv https://github.com/cloudfoundry/bosh-cli/releases/download/v${BOSH_CLI_VERSION}/bosh-cli-${BOSH_CLI_VERSION}-linux-amd64 \
RUN wget -nv https://github.com/cloudfoundry/bosh-cli/releases/download/v${BOSH_CLI_VERSION}/bosh-cli-${BOSH_CLI_VERSION}-linux-${TARGETARCH} \
-O /usr/local/bin/bosh && chmod +x /usr/local/bin/bosh

RUN wget -nv https://github.com/stedolan/jq/releases/download/${JQ_VERSION}/jq-linux64 \
-O /usr/local/bin/jq && chmod +x /usr/local/bin/jq
# amd64 is the unchanged original (stedolan/jq, jq-linux64). stedolan/jq is
# archived and ships no arm64 asset, so arm64 uses the maintained jqlang/jq,
# which publishes jq-linux-arm64. Fail on any other arch rather than silently
# installing the wrong jq. RFC: cloudfoundry/community#1530.
RUN case "${TARGETARCH}" in \
amd64) wget -nv https://github.com/stedolan/jq/releases/download/${JQ_VERSION}/jq-linux64 \
-O /usr/local/bin/jq ;; \
arm64) wget -nv https://github.com/jqlang/jq/releases/download/${JQ_VERSION}/jq-linux-arm64 \
-O /usr/local/bin/jq ;; \
*) echo "Unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \
esac \
&& chmod +x /usr/local/bin/jq

RUN wget -nv https://github.com/cloudfoundry-incubator/credhub-cli/releases/download/${CREDHUB_CLI_VERSION}/credhub-linux-amd64-${CREDHUB_CLI_VERSION}.tgz -O - | \
tar -zx --directory=/usr/local/bin

COPY --from=ghcr.io/cloudfoundry/bosh/golang-release /var/vcap/packages/golang-1-linux/ /usr/local/go
COPY --from=golang-release /var/vcap/packages/golang-1-linux/ /usr/local/go
ENV GOROOT=/usr/local/go PATH=/usr/local/go/bin:$PATH

# amd64 is the unchanged original: download the linux-amd64 credhub CLI release
# tarball. credhub-cli publishes amd64 release binaries only, so arm64 builds the
# CLI from source at the pinned tag with the Go toolchain copied in above. Fail
# on any other arch rather than silently installing the wrong CLI.
# RFC: cloudfoundry/community#1530.
RUN case "${TARGETARCH}" in \
amd64) wget -nv https://github.com/cloudfoundry-incubator/credhub-cli/releases/download/${CREDHUB_CLI_VERSION}/credhub-linux-amd64-${CREDHUB_CLI_VERSION}.tgz -O - | \
tar -zx --directory=/usr/local/bin ;; \
arm64) git clone --depth 1 --branch "${CREDHUB_CLI_VERSION}" \
https://github.com/cloudfoundry/credhub-cli.git /tmp/credhub-cli \
&& ( cd /tmp/credhub-cli && go build -o /usr/local/bin/credhub . ) \
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
&& rm -rf /tmp/credhub-cli ;; \
*) echo "Unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \
esac

RUN useradd --create-home --shell /bin/bash bosh
143 changes: 143 additions & 0 deletions ci/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,17 @@ resources:
owner: stedolan
repository: jq

# arm64 jq source. stedolan/jq is archived at 1.6 and ships no arm64 asset, so
# the arm64 CI image uses the maintained jqlang/jq, which publishes
# jq-linux-arm64. Kept separate from jq-github-release so the amd64 image build
# is unchanged. RFC: cloudfoundry/community#1530.
- name: jq-github-release-arm64
type: github-release
source:
access_token: ((github_public_repo_token))
owner: jqlang
repository: jq

- name: bosh-ecosystem-concourse
type: git
source:
Expand All @@ -105,11 +116,48 @@ resources:
username: ((github_read_write_packages.username))
password: ((github_read_write_packages.password))

# arm64 (Graviton) CI image, published under "latest-arm64" by
# build-docker-image-arm64 so the amd64 "latest" image is never overwritten.
# RFC: cloudfoundry/community#1530.
- name: bosh-agent-docker-image-arm64
type: registry-image
source:
repository: ghcr.io/cloudfoundry/bosh-agent
tag: latest-arm64
username: ((github_read_write_packages.username))
password: ((github_read_write_packages.password))

- name: bosh-agent-registry-image-arm64
type: registry-image
source:
repository: ghcr.io/cloudfoundry/bosh-agent
tag: latest-arm64
username: ((github_read_write_packages.username))
password: ((github_read_write_packages.password))

# Stock multi-arch base used to run build-docker-args on arm64 workers.
- name: ubuntu-image
type: registry-image
source:
repository: ubuntu
tag: noble
username: ((docker.username))
password: ((docker.password))

- name: golang-release-image
type: registry-image
source:
repository: ghcr.io/cloudfoundry/bosh/golang-release

# arm64 golang-release image published by cloudfoundry/bosh-package-golang-release
# (build-docker-image-arm64). Triggers the arm64 agent CI image rebuild.
# RFC: cloudfoundry/community#1530.
- name: golang-release-image-arm64
type: registry-image
source:
repository: ghcr.io/cloudfoundry/bosh/golang-release
tag: latest-arm64

- name: integration-postgres-15-image
type: registry-image
source:
Expand Down Expand Up @@ -330,6 +378,77 @@ jobs:
params:
image: image/image.tar

# arm64 (Graviton) CI image. RFC: cloudfoundry/community#1530.
# Mirrors build-docker-image on an arm64 worker; the Dockerfile selects arm64
# CLI binaries via TARGETARCH. Pushed under a separate "latest-arm64" tag so the
# amd64 "latest" image is never overwritten. build-docker-args runs in a stock
# multi-arch ubuntu image because the arm64 agent image does not exist before
# its first build. Dormant until an `arm64`-tagged worker is registered (RFC D3
# / Open Question 2) and the golang-release image the Dockerfile copies Go from
# is published for arm64.
- name: build-docker-image-arm64
plan:
- in_parallel:
- get: bosh-agent
tags: [ arm64 ]
- get: bosh-agent-ci
tags: [ arm64 ]
- get: ubuntu-image
tags: [ arm64 ]
- get: bosh-cli-github-release
resource: bosh-cli
trigger: true
params:
globs:
- "no-files-needed"
tags: [ arm64 ]
- get: credhub-cli-github-release
trigger: true
params:
globs:
- "no-files-needed"
tags: [ arm64 ]
- get: jq-github-release
resource: jq-github-release-arm64
trigger: true
params:
globs:
- "no-files-needed"
tags: [ arm64 ]
- get: golang-release-image
resource: golang-release-image-arm64
trigger: true
tags: [ arm64 ]
- task: build-docker-args
file: bosh-agent-ci/ci/docker/build-args.yml
image: ubuntu-image
tags: [ arm64 ]
- task: build-image
privileged: true
tags: [ arm64 ]
config:
platform: linux
image_resource:
type: registry-image
source:
repository: concourse/oci-build-task
inputs:
- name: bosh-agent-ci
- name: docker-build-args
outputs:
- name: image
params:
CONTEXT: bosh-agent-ci/ci/docker
BUILD_ARGS_FILE: docker-build-args/docker-build-args.yml
BUILD_ARG_GOLANG_RELEASE_IMAGE: ghcr.io/cloudfoundry/bosh/golang-release:latest-arm64
run:
path: build
- put: bosh-agent-docker-image-arm64
no_get: true
tags: [ arm64 ]
params:
image: image/image.tar

- name: test-unit
plan:
- get: bosh-agent
Expand All @@ -341,6 +460,26 @@ jobs:
image: bosh-agent-registry-image
file: bosh-agent-ci/ci/tasks/test-unit.yml

# arm64 (Graviton) unit tests. RFC: cloudfoundry/community#1530.
# Mirrors the amd64 test-unit job but pins the task to an arm64 worker so the
# suite runs natively on aarch64. This job is dormant until the platform team
# registers a Concourse worker with the `arm64` tag (RFC D3 / Open Question 2:
# ARM64 CI worker ownership). Until then Concourse reports it as pending with
# "no workers"; it never blocks the amd64 jobs, which are unchanged.
- name: test-unit-arm64
plan:
- get: bosh-agent
trigger: true
- get: bosh-agent-ci
- get: bosh-agent-registry-image
resource: bosh-agent-registry-image-arm64
trigger: true
tags: [ arm64 ]
- task: test-unit
image: bosh-agent-registry-image
file: bosh-agent-ci/ci/tasks/test-unit.yml
tags: [ arm64 ]

- name: test-unit-windows
serial: true
plan:
Expand Down Expand Up @@ -976,12 +1115,16 @@ jobs:
- task: build-linux
image: bosh-agent-registry-image
file: bosh-agent-ci/ci/tasks/build-linux.yml
- task: build-linux-arm64
image: bosh-agent-registry-image
file: bosh-agent-ci/ci/tasks/build-linux-arm64.yml
- task: build-windows
image: bosh-agent-registry-image
file: bosh-agent-ci/ci/tasks/build-windows.yml
- put: bosh-agent-index
params:
files:
- compiled-linux-amd64/*
- compiled-linux-arm64/*
- compiled-windows-amd64/*
version: version-semver/number
24 changes: 24 additions & 0 deletions ci/tasks/build-linux-arm64.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
platform: linux

image_resource:
type: registry-image
source:
repository: bosh/agent
tag: latest

inputs:
- name: bosh-agent
- name: bosh-agent-ci
- name: version-semver

outputs:
- name: compiled-linux-arm64

params:
OUTPUT_DIR: compiled-linux-arm64
GOARCH: arm64
GOOS: linux

run:
path: bosh-agent-ci/ci/tasks/build.sh