Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Excluded from the Docker build context for ALL Dockerfiles in this repo.
#
# .modcache is the Go proxy-layout module cache consumed by musl.Dockerfile
# (see its header). It is ~5 GB, so it must never be part of `COPY . .` image
# layers; instead it is passed to the build as a *named build context*
# (--build-context modcache=.modcache, or automatically via the musl-hub
# target in docker-bake.hcl) and bind-mounted only where the build needs it.
# It is git-ignored (see .gitignore) and populated by:
# ./build-production-image.sh musl
# or manually:
# cp -R "$(go env GOMODCACHE)/cache/download/." .modcache/
.modcache
29 changes: 29 additions & 0 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,43 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
with:
# Fetch full history including tags so that `git describe --tags`
# (used for VERSION in the Makefile) works inside the docker build.
fetch-depth: 0
- name: Build Docker container
env:
# Token with read access to the private go module dependencies
# (e.g. github.com/fetchai/priv_wasmd_sec). Must be set as a repo/org
# secret; the default GITHUB_TOKEN cannot read other private repos.
GH_PRIVATE_DEP_TOKEN: ${{ secrets.GH_PRIVATE_DEP_TOKEN }}
run: |
if [ -z "$GH_PRIVATE_DEP_TOKEN" ]; then
echo "::error::GH_PRIVATE_DEP_TOKEN secret is not set. Add a fine-grained PAT with read access to the private go module deps as a repo/org secret." >&2
exit 1
fi
# Fail fast with a clear diagnosis if the token cannot read the
# private dep repos (bad scope, expired, not SSO-authorized, ...).
for repo in priv_wasmd_sec priv_wasmvm_sec; do
code=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $GH_PRIVATE_DEP_TOKEN" \
"https://api.github.com/repos/fetchai/$repo") || code="curl_error"
if [ "$code" != "200" ]; then
echo "::error::GH_PRIVATE_DEP_TOKEN cannot access fetchai/$repo (API status: $code). Check the token's repository access/permissions (fine-grained: Contents=Read-only on the repo; classic: 'repo' scope + SSO authorization)." >&2
exit 1
fi
done
umask 077
printf 'machine github.com\nlogin x-access-token\npassword %s\n' "$GH_PRIVATE_DEP_TOKEN" \
> "$RUNNER_TEMP/netrc"
docker build \
--no-cache \
--progress plain \
--secret id=netrc,src="$RUNNER_TEMP/netrc" \
--tag fetch_cosmos_wasmd:$GITHUB_SHA \
--file ./ci.Dockerfile \
./
rm -f "$RUNNER_TEMP/netrc"
- name: Run make test
run: |
docker run --rm fetch_cosmos_wasmd:$GITHUB_SHA \
Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/build_push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ name: Build and push images
on:
push:
tags:
# Run for every tag push EXCEPT the v0.15.1 release tag (that release's
# images are built/pushed manually via
# build-production-image-with-push-and-pull.sh).
# Tag patterns are anchored full-string matches, so 'v0.15.1' matches
# ONLY the exact tag (v0.15.1-rc0 etc. still trigger this workflow).
# NOTE: for future releases, extend the negated pattern (e.g. a
# '!v[0-9]*.[0-9]*.[0-9]*' pattern would exclude ALL plain semver
# release tags, but also any tag with a suffix like -rc0).
- '!v0.15.1'
- '*'

jobs:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# OS
.DS_Store
.modcache/
*.swp
*.swo
*.swl
Expand Down
25 changes: 22 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,30 @@ WORKDIR /cosmwasm

COPY . .

RUN make install

# Optional Go runtime setting, empty by default. Set via --build-arg only where
# needed, e.g. GODEBUG=asyncpreempt=0 when building linux/amd64 under CPU
# emulation (QEMU/Rosetta on Apple Silicon), where emulated signal delivery
# can crash the go toolchain (SIGSEGV in runtime.suspendG). On native builds
# (Linux CI) leave it unset. The ARG value is exposed as an environment
# variable to the RUN steps below; no ENV needed.
ARG GODEBUG=""

# GitHub token for private repos (GOPRIVATE) is mounted from the host at build
# time; it is never baked into the image layers. Passed via buildx/bake as
# secret id=netrc (a .netrc file readable by git over HTTPS).
RUN --mount=type=secret,id=netrc,target=/root/.netrc make install

RUN GOPATH="$(go env GOPATH)"
RUN ARCH=`uname -m` && ln -s $GOPATH/pkg/mod/github.com/\!cosm\!wasm/wasmvm/v*/internal/api/libwasmvm.${ARCH}.so /usr/lib/libwasmvm.${ARCH}.so
# Resolve the wasmvm module's actual cache directory via go list -m, so this
# works regardless of any `replace` directives in go.mod (e.g. the private
# github.com/fetchai/priv_wasmvm_sec replacement) or if they are later dropped.
RUN ARCH=$(uname -m) && \
WASMVM_DIR=$(go list -m -f '{{.Dir}}' github.com/CosmWasm/wasmvm/v3) && \
ln -s "${WASMVM_DIR}/internal/api/libwasmvm.${ARCH}.so" /usr/lib/libwasmvm.${ARCH}.so && \
test -e /usr/lib/libwasmvm.${ARCH}.so || \
{ echo "ERROR: /usr/lib/libwasmvm.${ARCH}.so is a dangling symlink;" >&2; \
echo " go list could not resolve github.com/CosmWasm/wasmvm/v3 —" >&2; \
echo " check go.mod and GOPRIVATE settings." >&2; exit 1; }

# ##################################

Expand Down
92 changes: 91 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

PACKAGES_NOSIMULATION=$(shell go list ./... | grep -v '/simulation')
PACKAGES_SIMTEST=$(shell go list ./... | grep '/simulation')
VERSION := $(shell echo $(shell git describe --tags))
VERSION := $(shell git describe --tags --long --always --dirty 2> /dev/null || echo v0.0.0-dev)
COMMIT := $(shell git log -1 --format='%H')
LEDGER_ENABLED ?= true
BINDIR ?= $(GOPATH)/bin
Expand All @@ -14,6 +14,7 @@ DOCKER_BUF := docker run -v $(shell pwd):/workspace --workdir /workspace bufbuil
PROJECT_NAME = $(shell git remote get-url origin | xargs basename -s .git)

export GO111MODULE = on
export GOPRIVATE=github.com/fetchai/priv_wasmd_sec,github.com/fetchai/priv_wasmvm_sec

# process build tags

Expand Down Expand Up @@ -101,6 +102,95 @@ endif
install: go.sum
go install -mod=readonly $(BUILD_FLAGS) ./cmd/fetchd

# Static (musl) builds: link fetchd against the static wasmvm archive
# (libwasmvm_muslc.<arch>.a) instead of the dynamic libwasmvm.<arch>.so, so the
# resulting binary is fully static and the .so libraries do not need to be
# distributed/shipped alongside it.
#
# Requirements:
# - the build must run on a musl-based system (e.g. Alpine Linux) with
# gcc, make and xz available; the static-pie link mode used below is
# supported by musl but NOT by glibc
# - write access to /lib (the extracted archive must live in a default
# linker search path, because the wasmvm cgo bindings link it via
# -lwasmvm_muslc.<arch>; in Docker/container builds this is a given)

UNAME_M := $(shell uname -m)
STATIC_WASMVM_MODULE := github.com/CosmWasm/wasmvm/v3
STATIC_WASMVM_VERSION := $(shell go list -mod=readonly -m -f '{{.Version}}' $(STATIC_WASMVM_MODULE))
STATIC_WASMVM_LIB := /lib/libwasmvm_muslc.$(UNAME_M).a
STATIC_BUILD_TAGS := muslc
STATIC_LDFLAGS := -linkmode=external -extldflags=-static

# Extract the static (musl) wasmvm archive shipped inside the module that
# satisfies github.com/CosmWasm/wasmvm/v3 (following any `replace` directives
# in go.mod) into /lib, so that the external linker (gcc) finds it when the
# `muslc` build tag makes the wasmvm cgo bindings link it
# (-lwasmvm_muslc.<arch>).
#
# The module dir is resolved *inside the recipe shell* (not via a Make
# $(shell) expansion) so that the resolution provably happens after the
# `go mod download` that precedes it. GOPRIVATE is cleared for the go
# commands so the file:// GOPROXY cache is used for the private module
# instead of an authenticated VCS fetch.
.PHONY: static-wasmvm-lib
static-wasmvm-lib: go.sum
@echo "--> Extracting static wasmvm library ($(STATIC_WASMVM_VERSION)) to $(STATIC_WASMVM_LIB)"
@dir=$$(GOPRIVATE= go list -mod=readonly -m -f '{{.Dir}}' $(STATIC_WASMVM_MODULE)); \
if [ -z "$$dir" ]; then \
GOPRIVATE= go mod download $(STATIC_WASMVM_MODULE); \
dir=$$(GOPRIVATE= go list -mod=readonly -m -f '{{.Dir}}' $(STATIC_WASMVM_MODULE)); \
fi; \
if [ -z "$$dir" ]; then \
echo "ERROR: could not resolve module dir for $(STATIC_WASMVM_MODULE)" >&2; \
exit 1; \
fi; \
unxz -c "$$dir/internal/api/libwasmvm_muslc.$(UNAME_M).a.xz" > "$(STATIC_WASMVM_LIB)"
@chmod 644 "$(STATIC_WASMVM_LIB)"

# Generic static build: no wasmvm archive checksum pinning. Use this for
# non-release builds (e.g. local Alpine builds, CI builds from master). For
# release builds use the version-pinned target below instead.
install-static: static-wasmvm-lib
$(MAKE) install \
LEDGER_ENABLED=$(LEDGER_ENABLED) \
BUILD_TAGS=$(STATIC_BUILD_TAGS) \
LDFLAGS="$(STATIC_LDFLAGS)"

build-static: static-wasmvm-lib
$(MAKE) build \
LEDGER_ENABLED=$(LEDGER_ENABLED) \
BUILD_TAGS=$(STATIC_BUILD_TAGS) \
LDFLAGS="$(STATIC_LDFLAGS)"

# Release-pinned static build for v0.15.1: asserts the exact wasmvm version
# resolved from go.mod and the SHA256 of the *decompressed* static archive
# before building. The checksums are for github.com/fetchai/priv_wasmvm_sec/v3
# v3.0.8-rc.2 (the go.mod replace target of github.com/CosmWasm/wasmvm/v3);
# update them whenever the wasmvm pin changes.
verify-static-wasmvm-lib-v0.15.1: WASMVM_VERSION := v3.0.8-rc.2
verify-static-wasmvm-lib-v0.15.1: WASMVM_SHA256_x86_64 := 6863af60cebf04d094bc3bcf22a2777e1e1b4f1295d54e3b9a1082a3b359de8a
verify-static-wasmvm-lib-v0.15.1: WASMVM_SHA256_aarch64 := 46f4d0913331096f2926f28d5d0f4405eb700f571be229cf8774d942619370a4
verify-static-wasmvm-lib-v0.15.1: static-wasmvm-lib
@echo "--> Verifying wasmvm version pin for fetchd v0.15.1"
@if [ "$(WASMVM_VERSION)" != "$(STATIC_WASMVM_VERSION)" ]; then \
echo "ERROR: wasmvm module version is '$(STATIC_WASMVM_VERSION)', but fetchd" >&2; \
echo " v0.15.1 is pinned to '$(WASMVM_VERSION)'." >&2; \
exit 1; \
fi
@echo "--> Verifying static wasmvm library checksum"
@if [ "$$(sha256sum $(STATIC_WASMVM_LIB) | cut -d' ' -f1)" != "$(WASMVM_SHA256_$(UNAME_M))" ]; then \
echo "ERROR: SHA256 mismatch for $(STATIC_WASMVM_LIB)" >&2; \
echo " expected: $(WASMVM_SHA256_$(UNAME_M))" >&2; \
echo " actual: $$(sha256sum $(STATIC_WASMVM_LIB) | cut -d' ' -f1)" >&2; \
exit 1; \
fi
@echo " OK"

install-static-v0.15.1: verify-static-wasmvm-lib-v0.15.1 install-static

.PHONY: install-static build-static verify-static-wasmvm-lib-v0.15.1 install-static-v0.15.1

########################################
### Tools & dependencies

Expand Down
Loading
Loading