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
27 changes: 27 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: build
on:
push:
branches:
- "main"
tags:
- "v*"
pull_request:
branches:
- "main"
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Checkout
uses: actions/checkout@v4
- name: setup-tools
uses: buildpacks/github-actions/setup-tools@v5.8.9
- name: setup-pack
uses: buildpacks/github-actions/setup-pack@v5.8.9
- name: Build and test
run: |
make build test
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
**/target

**/*.wasm

**/.projects.json
41 changes: 41 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
SHELL:=/usr/bin/env bash
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
.DEFAULT_GOAL:=help

## --------------------------------------
## Build
## --------------------------------------

##@ Build:

.PHONY: build
build: build-base-images build-builder ## Build all of the things \o/

.PHONY: build-base-images
build-base-images: ## Build the base images.
./base-images/build.sh wasm

.PHONY: build-builder
build-builder: ## Build the builder image.
pack builder create wasm/demo-builder:wasm --config ./builders/wasm/builder.toml


## --------------------------------------
## Test
## --------------------------------------

##@ Test:

.PHONY: test
test: test-js test-compose ## Run all tests.

.PHONY: test-compose
test-compose: ## Test the compose project.
pack build test-wasm-compose --builder wasm/demo-builder:wasm --path apps/compose

.PHONY: test-js
test-js: ## Test the JS app.
pack build test-wasm-js --builder wasm/demo-builder:wasm --path apps/js

help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[0-9a-zA-Z_-]+:.*?##/ { printf " \033[36m%-25s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
3 changes: 2 additions & 1 deletion apps/compose/app-js/componentize.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ const { component } = await componentize(jsSource, {
enableAot,
});

await writeFile("server.component.wasm", component);
let componentName = process.env.COMPONENT_NAME ?? "server.component.wasm";
await writeFile(componentName, component);
9 changes: 9 additions & 0 deletions apps/compose/app-js/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/compose/app-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@
},
"scripts": {
"build": "wkg wit fetch && node componentize.js"
},
"dependencies": {
"itty-router": "^5.0.18"
}
}
6 changes: 6 additions & 0 deletions apps/compose/compose.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"dependencies": {
"example:math": "service-go",
"example:server": "app-js"
}
}
18 changes: 18 additions & 0 deletions apps/compose/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions apps/compose/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"type": "module",
"scripts": {
"build": "echo 'faker!'"
},
"dependencies": {
"itty-router": "^5.0.18"
}
}
Binary file removed apps/compose/service-go/compose
Binary file not shown.
2 changes: 2 additions & 0 deletions apps/compose/service-go/go.world.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[target]
world = "adder"
3 changes: 2 additions & 1 deletion apps/js/componentize.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ const { component } = await componentize(jsSource, {
enableAot,
});

await writeFile("server.component.wasm", component);
let componentName = process.env.COMPONENT_NAME ?? "server.component.wasm";
await writeFile(componentName, component);
32 changes: 23 additions & 9 deletions base-images/build.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env bash
set -e
set -euo pipefail

DEFAULT_PREFIX=wasm/demo-base
DEFAULT_PLATFORM=linux/arm64
DEFAULT_PLATFORM="linux/amd64,linux/arm64"

REPO_PREFIX=${DEFAULT_PREFIX}
PLATFORM=${DEFAULT_PLATFORM}
Expand Down Expand Up @@ -50,26 +50,38 @@ fi

cd $(dirname $0)

IMAGE_DIR=$(realpath "${BASE_DIR}")
TAG=$(basename "${IMAGE_DIR}")
TAG="${ENV_VAR:-latest}"
BASE_IMAGE=heroku/heroku:24-build
RUN_IMAGE=${REPO_PREFIX}-run:${TAG}
BUILD_IMAGE=${REPO_PREFIX}-build:${TAG}
FROM_IMAGE=$(head -n1 "${IMAGE_DIR}"/base/Dockerfile | cut -d' ' -f2)

docker buildx ls

echo "BUILDING ${BUILD_IMAGE}..."
docker buildx build --load \
docker buildx build \
--platform "${PLATFORM}" \
--build-arg "BASE_IMAGE=${BASE_IMAGE}" \
-t "${BUILD_IMAGE}" \
"${IMAGE_DIR}/build"
"${BASE_DIR}/build"

echo "BUILDING ${RUN_IMAGE}..."
docker buildx build --load \
--build-arg "BASE_IMAGE=${BASE_IMAGE}" \
-t "${BUILD_IMAGE}" \
"${BASE_DIR}/build"

docker buildx build --load -t "${BUILD_IMAGE}" ${BASE_DIR}/build

echo "BUILDING ${RUN_IMAGE}..."
docker buildx build \
--platform "${PLATFORM}" \
--build-arg "BASE_IMAGE=${BUILD_IMAGE}" \
-t "${RUN_IMAGE}" \
"${IMAGE_DIR}/run"
"${BASE_DIR}/run"

docker buildx build --load \
--build-arg "BASE_IMAGE=${BUILD_IMAGE}" \
-t "${RUN_IMAGE}" \
"${BASE_DIR}/run"

echo
echo "BASE IMAGES BUILT!"
Expand All @@ -78,3 +90,5 @@ echo "Images:"
for IMAGE in "${BASE_IMAGE}" "${BUILD_IMAGE}" "${RUN_IMAGE}"; do
echo " ${IMAGE}"
done

docker image ls
20 changes: 19 additions & 1 deletion base-images/wasm/build/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
ARG BASE_IMAGE=heroku/heroku:24-build
FROM ${BASE_IMAGE} AS base
FROM --platform=${BUILDPLATFORM} ${BASE_IMAGE} AS base

ARG TARGETOS
ARG TARGETARCH

# Install packages that we want to make available at build time
USER root
RUN apt update && \
apt install -y git wget jq musl-tools && \
rm -rf /var/lib/apt/lists/*

ENV GO_RELEASE=1.24.1
RUN wget -q https://dl.google.com/go/go${GO_RELEASE}.${TARGETOS}-${TARGETARCH}.tar.gz && \
tar xf go${GO_RELEASE}.${TARGETOS}-${TARGETARCH}.tar.gz -C /usr/local && \
find /usr/local/go -mindepth 1 -maxdepth 1 ! -name 'src' ! -name 'VERSION' ! -name 'bin' ! -name 'pkg' ! -name 'go.env' -exec rm -rf {} +

ENV TINYGO_RELEASE=0.37.0
RUN wget -q https://github.com/tinygo-org/tinygo/releases/download/v${TINYGO_RELEASE}/tinygo${TINYGO_RELEASE}.${TARGETOS}-${TARGETARCH}.tar.gz && \
tar xf tinygo${TINYGO_RELEASE}.${TARGETOS}-${TARGETARCH}.tar.gz -C /usr/local

ENV PATH=${PATH}:/usr/local/tinygo/bin
ENV PATH=${PATH}:/usr/local/go/bin
ENV GOPATH=/home/heroku/go
ENV PATH=${PATH}:/home/heroku/go/bin
RUN wget -q https://github.com/mikefarah/yq/releases/latest/download/yq_linux_${TARGETARCH} -O /usr/local/bin/yq && chmod +x /usr/local/bin/yq

USER heroku
# Get Rust
ENV CARGO_HOME=/home/heroku/.cargo
Expand Down
2 changes: 2 additions & 0 deletions base-images/wasm/run/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
FROM gcr.io/distroless/static:nonroot AS final
LABEL io.buildpacks.stack.id="heroku-24"
LABEL io.buildpacks.base.homepage="https://github.com/devigned/wasm-packs"
LABEL io.buildpacks.base.maintainer="devigned"
38 changes: 27 additions & 11 deletions builders/wasm/builder.toml
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
description = "A builder for WebAssembly"

[build]
image = "wasm/demo-base-build:wasm"
image = "wasm/demo-base-build:latest"
[run]
[[run.images]]
image = "wasm/demo-base-run:wasm"
image = "wasm/demo-base-run:latest"

[lifecycle]
version = "0.20.5"
version = "0.20.7"

[[buildpacks]]
uri = "docker://docker.io/heroku/buildpack-deb-packages@sha256:f2c0162a2fb5f9cb7e6b3c5c59907089483a328824c9323a85cc67d47ab9198c"

[[buildpacks]]
uri = "../../meta-buildpacks/nodejs"
uri = "../../meta-buildpacks/wasm"

[[buildpacks]]
uri = "docker://docker.io/heroku/buildpack-nodejs-engine:3.4.11"

[[buildpacks]]
uri = "docker://docker.io/heroku/buildpack-nodejs-corepack:3.4.11"
# [[buildpacks]]
# uri = "docker://docker.io/heroku/buildpack-nodejs-corepack:3.4.11"

[[buildpacks]]
uri = "docker://docker.io/heroku/buildpack-nodejs-npm-engine:3.4.11"
# [[buildpacks]]
# uri = "docker://docker.io/heroku/buildpack-nodejs-npm-engine:3.4.11"

[[buildpacks]]
uri = "docker://docker.io/heroku/buildpack-nodejs-npm-install:3.4.11"
# [[buildpacks]]
# uri = "docker://docker.io/heroku/buildpack-nodejs-npm-install:3.4.11"

# [[buildpacks]]
# id = "heroku/go"
# uri = "docker://docker.io/heroku/buildpack-go:0.5.6"

[[buildpacks]]
uri = "../../buildpacks/js"
Expand All @@ -36,9 +40,21 @@ uri = "../../buildpacks/wasmtime-engine"
[[buildpacks]]
uri = "../../buildpacks/wasm-tools"

[[buildpacks]]
uri = "../../buildpacks/wac-analyzer"

[[buildpacks]]
uri = "../../buildpacks/wac-composer"

[[buildpacks]]
uri = "../../buildpacks/wasm-finalizer"

[[buildpacks]]
uri = "../../buildpacks/golang"

[[order]]
[[order.group]]
id = "devigned/nodejs"
id = "devigned/wasm"
version = "0.0.1"

[[targets]]
Expand Down
56 changes: 56 additions & 0 deletions buildpacks/golang/bin/build
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env bash

set -euo pipefail

CGO_ENABLED=0 go install go.bytecodealliance.org/cmd/wit-bindgen-go@latest

# We have a compose.wac file, so we are a composition project
if [ -f "compose.wac" ]; then
wasm_component_layer="${CNB_LAYERS_DIR}/wasm-golang-components"
mkdir -p "${wasm_component_layer}"
cat > "${wasm_component_layer}.toml" << EOL
[types]
launch = false
cache = false
build = true
EOL
# find each JS project listed in the .projects.json file and build them
for project in $(jq -r '.go[]' .projects.json); do
echo "wasm/golang: Building golang ${project}"
cd "${project}"
# build the project
world=$(yq -r '.target.world' go.world.toml)
component_name="${project}.component.wasm"
go generate
tinygo build -target=wasip2 -o "${component_name}" --wit-package ./wit --wit-world "${world}" .
echo "---> wasm/golang: Copying ${component_name} to layer ${wasm_component_layer}"
cp "${component_name}" "${wasm_component_layer}"
done
exit 0 # exit here as we don't want to run the rest of the script
fi

# Wasm Golang project was found, but it is not a composition project
wasm_component_layer="${CNB_LAYERS_DIR}/wasm-golang-components"
mkdir -p "${wasm_component_layer}"
cat > "${wasm_component_layer}.toml" << EOL
[types]
launch = true
cache = false
build = false
EOL

world=$(yq -r '.target.world' go.world.toml)
component_name="${project}.component.wasm"
go generate
tinygo build -target=wasip2 -o "${component_name}" --wit-package ./wit --wit-world "${world}" .
cp "${component_name}" "${wasm_component_layer}"

# Set default start command
cat > "${CNB_LAYERS_DIR}/launch.toml" << EOL
[[processes]]
type = "web"
command = ["wasmtime", "serve", "-S", "cli", "${CNB_LAYERS_DIR}/wasm-golang-components/${component_name}"]
default = true
EOL

exit 0
Loading