Skip to content

Commit

Permalink
Merge pull request #1 from upbound/github-workflows
Browse files Browse the repository at this point in the history
added github workflows
  • Loading branch information
humoflife authored Dec 12, 2023
2 parents d133539 + 8336468 commit b9a66ba
Show file tree
Hide file tree
Showing 2 changed files with 202 additions and 27 deletions.
164 changes: 164 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
name: CI

on:
push:
branches:
- main
- release-*
pull_request: {}
workflow_dispatch:
inputs:
version:
description: Package version (e.g. v0.1.0)
required: false

env:
# Common versions
GO_VERSION: '1.21.4'
GOLANGCI_VERSION: 'v1.54.2'
DOCKER_BUILDX_VERSION: 'v0.11.2'

# These environment variables are important to the Crossplane CLI install.sh
# script. They determine what version it installs.
XP_CHANNEL: master # TODO(negz): Pin to stable once v1.14 is released.
XP_VERSION: current # TODO(negz): Pin to a version once v1.14 is released.

# This CI job will automatically push new builds to xpkg.upbound.io if the
# XPKG_ACCESS_ID and XPKG_TOKEN secrets are set in the GitHub respository (or
# organization) settings. Create a token at https://accounts.upbound.io.
XPKG_ACCESS_ID: ${{ secrets.XPKG_ACCESS_ID }}

# The package to push, without a version tag. The default matches GitHub. For
# example xpkg.upbound.io/crossplane/function-template-go.
XPKG: xpkg.upbound.io/${{ github.repository}}

# The package version to push. The default is 0.0.0-gitsha.
XPKG_VERSION: ${{ inputs.version }}

jobs:
lint:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}
cache: false # The golangci-lint action does its own caching.

- name: Lint
uses: golangci/golangci-lint-action@v3
with:
version: ${{ env.GOLANGCI_VERSION }}

unit-test:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}

- name: Run Unit Tests
run: go test -v -cover ./...

# We want to build most packages for the amd64 and arm64 architectures. To
# speed this up we build single-platform packages in parallel. We then upload
# those packages to GitHub as a build artifact. The push job downloads those
# artifacts and pushes them as a single multi-platform package.
build:
runs-on: ubuntu-22.04
strategy:
fail-fast: true
matrix:
arch:
- amd64
- arm64
steps:
- name: Setup QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: all

- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.DOCKER_BUILDX_VERSION }}
install: true

- name: Checkout
uses: actions/checkout@v4

# We ask Docker to use GitHub Action's native caching support to speed up
# the build, per https://docs.docker.com/build/cache/backends/gha/.
- name: Build Runtime
id: image
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/${{ matrix.arch }}
cache-from: type=gha
cache-to: type=gha,mode=max
target: image
build-args:
GO_VERSION=${{ env.GO_VERSION }}
outputs: type=docker,dest=runtime-${{ matrix.arch }}.tar

- name: Setup the Crossplane CLI
run: "curl -sL https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh | sh"

- name: Build Package
run: ./crossplane xpkg build --package-file=${{ matrix.arch }}.xpkg --package-root=package/ --embed-runtime-image-tarball=runtime-${{ matrix.arch }}.tar

- name: Upload Single-Platform Package
uses: actions/upload-artifact@v3
with:
name: packages
path: "*.xpkg"
if-no-files-found: error
retention-days: 1

# This job downloads the single-platform packages built by the build job, and
# pushes them as a multi-platform package. We only push the package it the
# XPKG_ACCESS_ID and XPKG_TOKEN secrets were provided.
push:
runs-on: ubuntu-22.04
needs:
- build
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Download Single-Platform Packages
uses: actions/download-artifact@v3
with:
name: packages
path: .

- name: Setup the Crossplane CLI
run: "curl -sL https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh | sh"

- name: Login to Upbound
uses: docker/login-action@v3
if: env.XPKG_ACCESS_ID != ''
with:
registry: xpkg.upbound.io
username: ${{ secrets.XPKG_ACCESS_ID }}
password: ${{ secrets.XPKG_TOKEN }}

# If a version wasn't explicitly passed as a workflow_dispatch input we
# default to version v0.0.0-<git-commit-date>-<git-short-sha>, for example
# v0.0.0-20231101115142-1091066df799. This is a simple implementation of
# Go's pseudo-versions: https://go.dev/ref/mod#pseudo-versions.
- name: Set Default Multi-Platform Package Version
if: env.XPKG_VERSION == ''
run: echo "XPKG_VERSION=v0.0.0-$(date -d@$(git show -s --format=%ct) +%Y%m%d%H%M%S)-$(git rev-parse --short=12 HEAD)" >> $GITHUB_ENV

- name: Push Multi-Platform Package to Upbound
if: env.XPKG_ACCESS_ID != ''
run: "./crossplane --verbose xpkg push --package-files $(echo *.xpkg|tr ' ' ,) ${{ env.XPKG }}:${{ env.XPKG_VERSION }}"
65 changes: 38 additions & 27 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,35 +1,46 @@
FROM golang:1.21 as build-stage
# syntax=docker/dockerfile:1

WORKDIR /fn

COPY go.mod go.sum ./
RUN go mod download

COPY . ./

RUN CGO_ENABLED=0 go build -o /function .

FROM debian:12.1-slim as package-stage

# TODO(negz): Use a proper Crossplane package building tool. We're abusing the
# fact that this image won't have an io.crossplane.pkg: base annotation. This
# means Crossplane package manager will pull this entire ~100MB image, which
# also happens to contain a valid Function runtime.
# https://github.com/crossplane/crossplane/blob/v1.13.2/contributing/specifications/xpkg.md
WORKDIR /package
COPY package/ ./
# We use the latest Go 1.x version unless asked to use something else.
# The GitHub Actions CI job sets this argument for a consistent Go version.
ARG GO_VERSION=1

RUN cat crossplane.yaml > /package.yaml
# Setup the base environment. The BUILDPLATFORM is set automatically by Docker.
# The --platform=${BUILDPLATFORM} flag tells Docker to build the function using
# the OS and architecture of the host running the build, not the OS and
# architecture that we're building the function for.
FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build

FROM gcr.io/distroless/base-debian11 AS build-release-stage
WORKDIR /fn

# Most functions don't want or need CGo support, so we disable it.
ENV CGO_ENABLED=0

# We run go mod download in a separate step so that we can cache its results.
# This lets us avoid re-downloading modules if we don't need to. The type=target
# mount tells Docker to mount the current directory read-only in the WORKDIR.
# The type=cache mount tells Docker to cache the Go modules cache across builds.
RUN --mount=target=. --mount=type=cache,target=/go/pkg/mod go mod download

# The TARGETOS and TARGETARCH args are set by docker. We set GOOS and GOARCH to
# these values to ask Go to compile a binary for these architectures. If
# TARGETOS and TARGETOS are different from BUILDPLATFORM, Go will cross compile
# for us (e.g. compile a linux/amd64 binary on a linux/arm64 build machine).
ARG TARGETOS
ARG TARGETARCH

# Build the function binary. The type=target mount tells Docker to mount the
# current directory read-only in the WORKDIR. The type=cache mount tells Docker
# to cache the Go modules cache across builds.
RUN --mount=target=. \
--mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o /function .

# Produce the Function image. We use a very lightweight 'distroless' image that
# does not include any of the build tools used in previous stages.
FROM gcr.io/distroless/base-debian11 AS image
WORKDIR /

COPY --from=build-stage /function /function
COPY --from=package-stage /package.yaml /package.yaml

COPY --from=build /function /function
EXPOSE 9443

USER nonroot:nonroot

ENTRYPOINT ["/function"]

0 comments on commit b9a66ba

Please sign in to comment.