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
17 changes: 15 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- "**"
- "!bump-version/**"
- "!dependabot/**"
tags:
- 'v[0-9]+\.[0-9]+\.[0-9]+-?**'
Expand Down Expand Up @@ -100,16 +101,28 @@ jobs:
if: startsWith(github.ref, 'refs/tags/') || (github.ref == 'refs/heads/main' && contains(steps.interface_version.outputs.VERSION, '-'))
run: make publish
env:
PUBLISH_LOG: "${{ runner.temp }}/published.txt"
REPOSITORY: "ghcr.io/${{ github.repository }}"
VERSION: "${{ case(github.ref == 'refs/heads/main', steps.interface_version.outputs.VERSION, steps.tag_version.outputs.VERSION) }}"
- name: Draft release notes
run: |
{
echo "## Published components"
echo
echo "| File | Image |"
echo "| --- | --- |"
while read -r file image ; do
echo "| \`${file}\` | \`${image}\` |"
done < "${RUNNER_TEMP}/published.txt"
} > "${RUNNER_TEMP}/release-notes.md"
cat "${RUNNER_TEMP}/release-notes.md"
- name: Draft GitHub Release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v3
with:
draft: true
body_path: ${{ runner.temp }}/release-notes.md
files: |
target/components/*.wasm
target/components/*/*.wasm
components.tar
fail_on_unmatched_files: true
token: ${{ secrets.GITHUB_TOKEN }}
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ members = [
"crates/test-harness",
]

[workspace.package]
version = "0.1.1-dev"

[workspace.dependencies]
bytes = "1"
http = "1"
Expand Down
44 changes: 4 additions & 40 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ $(foreach dir,$(WKG_DIRS),$(eval $(call FETCH_WIT,$(dir))))

# sign published components with cosign, `SIGN=false` to push without signing, e.g. to a local registry
SIGN ?= true
# append each published file and its image to this file, e.g. `gate.wasm ghcr.io/componentized/http/gate:0.1.0@sha256:...`
PUBLISH_LOG ?=

# the files that can be published, e.g. gate.wasm, published from target/components/gate/gate.wasm
PUBLISH_FILES := interface.wasm $(foreach component,$(filter-out dep-% test-%,$(COMPONENTS)),$(component).wasm $(component).debug.wasm)
Expand All @@ -168,43 +170,5 @@ publish: $(addprefix publish-,$(PUBLISH_FILES))

.PHONY: $(addprefix publish-,$(PUBLISH_FILES))
$(addprefix publish-,$(PUBLISH_FILES)): publish-%: | $(call tool,wkg)
ifndef VERSION
$(error VERSION is undefined)
endif
ifndef REPOSITORY
$(error REPOSITORY is undefined)
endif
@$(eval FILE := $(@:publish-%=%))
@$(eval COMPONENT := $(patsubst %.wasm,%,$(patsubst %.debug.wasm,%,$(FILE))))
# components are in a directory of their own, the interface is not, e.g. gate/gate.wasm and interface.wasm
@$(eval COMPONENT_FILE := $(if $(filter interface.wasm,$(FILE)),$(FILE),$(COMPONENT)/$(FILE)))
@$(eval README := ${COMPONENTS_DIR}/$(dir $(COMPONENT_FILE))README.md)
@$(eval TITLE := $(subst /,:,$(GITHUB_REPOSITORY))$(if $(filter interface,$(COMPONENT)),,-$(COMPONENT))$(if $(filter %.debug.wasm,$(FILE)), (debug)))
@$(eval DESCRIPTION := $(shell head -n 3 "$(README)" | tail -n 1))
@$(eval COMMIT := $(shell git rev-parse HEAD))
@$(eval README_DIR := $(if $(wildcard components/$(COMPONENT)/README.md),/components/$(COMPONENT)))
@$(eval URL := https://github.com/${GITHUB_REPOSITORY}/tree/${COMMIT}${README_DIR})
@$(eval REVISION := ${COMMIT}$(shell git diff --quiet HEAD || echo "+dirty"))
@$(eval COMPONENT_VERSION := $(if $(filter %.debug.wasm,$(FILE)),${VERSION}+debug,${VERSION}))
@$(eval TAG := $(patsubst v%,%,$(subst +,_,$(COMPONENT_VERSION))))
@$(eval IMAGE := $(if $(filter interface.wasm,$(FILE)),${REPOSITORY}:${TAG},${REPOSITORY}/${COMPONENT}:${TAG}))

@echo "::group::${FILE} -> ${IMAGE}"
@set -o pipefail ; \
DIGEST=$$( \
wkg oci push \
--annotation "org.opencontainers.image.title=${TITLE}" \
--annotation "org.opencontainers.image.description=${DESCRIPTION}" \
--annotation "org.opencontainers.image.version=${COMPONENT_VERSION}" \
--annotation "org.opencontainers.image.url=${URL}" \
--annotation "org.opencontainers.image.source=https://github.com/${GITHUB_REPOSITORY}.git" \
--annotation "org.opencontainers.image.revision=${REVISION}" \
--annotation "org.opencontainers.image.licenses=Apache-2.0" \
"${IMAGE}" \
"${COMPONENTS_DIR}/${COMPONENT_FILE}" \
2>&1 \
| tee /dev/stderr \
| grep -o 'sha256:[a-f0-9]\{64\}' \
) && \
$(if $(filter true,$(SIGN)),cosign sign --yes "${IMAGE}@$${DIGEST}",echo "Not signing ${IMAGE}@$${DIGEST}, SIGN=${SIGN}")
@echo "::endgroup::"
@VERSION="$(VERSION)" REPOSITORY="$(REPOSITORY)" COMPONENTS_DIR="$(COMPONENTS_DIR)" SIGN="$(SIGN)" PUBLISH_LOG="$(PUBLISH_LOG)" \
scripts/publish.sh $*
105 changes: 105 additions & 0 deletions scripts/publish.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/usr/bin/env bash

# Publish a built component to an OCI registry, and sign it with cosign.
#
# VERSION=<version> REPOSITORY=<repository> scripts/publish.sh <file>
#
# The file is one of the files built into the components directory, components are in a directory
# of their own, the interface is not, e.g. gate.wasm from target/components/gate/gate.wasm and
# interface.wasm from target/components/interface.wasm. The interface is published to the
# repository, each component to a repository of its own under it, a debug build is tagged with a
# `_debug` suffix.
#
# interface.wasm -> ${REPOSITORY}:0.1.0
# gate.wasm -> ${REPOSITORY}/gate:0.1.0
# gate.debug.wasm -> ${REPOSITORY}/gate:0.1.0_debug
#
# VERSION the version to publish, a leading `v` is dropped from the tag, e.g. v0.1.0
# REPOSITORY the repository to publish to, e.g. ghcr.io/componentized/http
# GITHUB_REPOSITORY the GitHub repository the components are built from, e.g. componentized/http
# COMPONENTS_DIR the directory the components are built into, defaults to target/components
# SIGN sign the published components with cosign, `false` to push without signing,
# e.g. to a local registry
# PUBLISH_LOG append the published file and its image to this file, e.g.
# `gate.wasm ghcr.io/componentized/http/gate:0.1.0@sha256:...`

set -euo pipefail

cd "$(dirname "$0")/.."

file="${1:-}"
if [[ -z "$file" ]]; then
echo "usage: $0 <file>, e.g. interface.wasm or gate.wasm" >&2
exit 1
fi
: "${VERSION:?VERSION is undefined}"
: "${REPOSITORY:?REPOSITORY is undefined}"
GITHUB_REPOSITORY="${GITHUB_REPOSITORY:-componentized/$(basename "$(git rev-parse --show-toplevel)")}"
COMPONENTS_DIR="${COMPONENTS_DIR:-target/components}"
SIGN="${SIGN:-true}"
PUBLISH_LOG="${PUBLISH_LOG:-}"

component="${file%.wasm}"
component="${component%.debug}"
debug=""
[[ "$file" == *.debug.wasm ]] && debug=true

if [[ "$file" == interface.wasm ]]; then
component_file="$file"
title="${GITHUB_REPOSITORY/\//:}"
else
component_file="${component}/${file}"
title="${GITHUB_REPOSITORY/\//:}-${component}"
fi
[[ -n "$debug" ]] && title="${title} (debug)"

# the description is the line following the title in the readme
readme="${COMPONENTS_DIR}/$(dirname "$component_file")/README.md"
description=$(sed -n 3p "$readme")

commit=$(git rev-parse HEAD)
revision="$commit"
git diff --quiet HEAD || revision="${commit}+dirty"
url="https://github.com/${GITHUB_REPOSITORY}/tree/${commit}"
[[ -f "components/${component}/README.md" ]] && url="${url}/components/${component}"

component_version="$VERSION"
[[ -n "$debug" ]] && component_version="${VERSION}+debug"
tag="${component_version#v}"
tag="${tag//+/_}"

if [[ "$file" == interface.wasm ]]; then
image="${REPOSITORY}:${tag}"
else
image="${REPOSITORY}/${component}:${tag}"
fi

echo "::group::${file} -> ${image}"

digest=$(
wkg oci push \
--annotation "org.opencontainers.image.title=${title}" \
--annotation "org.opencontainers.image.description=${description}" \
--annotation "org.opencontainers.image.version=${component_version}" \
--annotation "org.opencontainers.image.url=${url}" \
--annotation "org.opencontainers.image.source=https://github.com/${GITHUB_REPOSITORY}.git" \
--annotation "org.opencontainers.image.revision=${revision}" \
--annotation "org.opencontainers.image.licenses=Apache-2.0" \
"$image" \
"${COMPONENTS_DIR}/${component_file}" \
2>&1 \
| tee /dev/stderr \
| grep -o 'sha256:[a-f0-9]\{64\}'
)

if [[ -n "$PUBLISH_LOG" ]]; then
echo "${file} ${image}@${digest}" >> "$PUBLISH_LOG"
fi

if [[ "$SIGN" == true ]]; then
cosign sign --yes "${image}@${digest}"
else
echo "Not signing ${image}@${digest}, SIGN=${SIGN}"
fi

echo "::endgroup::"
Loading