#!/usr/bin/env bash set -euo pipefail # This script requires quicktype to be installed. # While you can install it using npm, we have it in our devDependencies # in ${PROJECT_ROOT}/package.json. PROJECT_ROOT="$(git rev-parse --show-toplevel)" if ! pnpm list | grep quicktype &>/dev/null; then echo "quicktype is required to run this script!" echo "Ensure that it is present in the devDependencies of ${PROJECT_ROOT}/package.json and then run pnpm install." exit 1 fi DEST_FILENAME="dcspec_gen.go" SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) DEST_PATH="${SCRIPT_DIR}/${DEST_FILENAME}" # Location of the JSON schema for the devcontainer specification. SCHEMA_SRC="https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.base.schema.json" SCHEMA_DEST="${SCRIPT_DIR}/devContainer.base.schema.json" UPDATE_SCHEMA="${UPDATE_SCHEMA:-false}" if [[ "${UPDATE_SCHEMA}" = true || ! -f "${SCHEMA_DEST}" ]]; then # Download the latest schema. echo "Updating schema..." curl --fail --silent --show-error --location --output "${SCHEMA_DEST}" "${SCHEMA_SRC}" else echo "Using existing schema..." fi TMPDIR=$(mktemp -d) trap 'rm -rfv "$TMPDIR"' EXIT show_stderr=1 exec 3>&2 if [[ " $* " == *" --quiet "* ]] || [[ ${DCSPEC_QUIET:-false} == "true" ]]; then # Redirect stderr to log because quicktype can't infer all types and # we don't care right now. show_stderr=0 exec 2>"${TMPDIR}/stderr.log" fi if ! pnpm exec quicktype \ --src-lang schema \ --lang go \ --top-level "DevContainer" \ --out "${TMPDIR}/${DEST_FILENAME}" \ --package "dcspec" \ "${SCHEMA_DEST}"; then echo "quicktype failed to generate Go code." >&3 if [[ "${show_stderr}" -eq 1 ]]; then cat "${TMPDIR}/stderr.log" >&3 fi exit 1 fi if [[ "${show_stderr}" -eq 0 ]]; then # Restore stderr. exec 2>&3 fi exec 3>&- # Format the generated code. "${PROJECT_ROOT}/scripts/format_go_file.sh" "${TMPDIR}/${DEST_FILENAME}" # Add a header so that Go recognizes this as a generated file. if grep -q -- "\[-i extension\]" < <(sed -h 2>&1); then # darwin sed sed -i '' '1s/^/\/\/ Code generated by dcspec\/gen.sh. DO NOT EDIT.\n\/\/\n/' "${TMPDIR}/${DEST_FILENAME}" else sed -i'' '1s/^/\/\/ Code generated by dcspec\/gen.sh. DO NOT EDIT.\n\/\/\n/' "${TMPDIR}/${DEST_FILENAME}" fi mv -v "${TMPDIR}/${DEST_FILENAME}" "${DEST_PATH}"