Skip to content

Instantly share code, notes, and snippets.

@cjavdev
Created April 17, 2026 17:54
Show Gist options
  • Select an option

  • Save cjavdev/96808d73b1188d77089d128a0d6de225 to your computer and use it in GitHub Desktop.

Select an option

Save cjavdev/96808d73b1188d77089d128a0d6de225 to your computer and use it in GitHub Desktop.
Stainless bundle from config repo
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<EOF
Usage: $0 <github-repo-url> [output-zip]
Downloads a Stainless config repo from GitHub and packages it into a zip
containing a top-level 'stainless/' directory with:
- openapi.json (any *.json / *.yaml / *.yml OpenAPI spec in the repo)
- stainless.yml
- workspace.json (renamed from stainless-workspace.json)
Examples:
$0 https://github.com/stainless-sdks/believe-config
$0 git@github.com:stainless-sdks/believe-config.git believe-config.zip
$0 stainless-sdks/believe-config
EOF
exit 1
}
[[ $# -ge 1 ]] || usage
REPO_INPUT="$1"
OUTPUT_ZIP="${2:-}"
# Normalize input into a cloneable URL and a repo name.
# Strip trailing slash and optional .git suffix first, then parse.
trimmed="${REPO_INPUT%/}"
trimmed="${trimmed%.git}"
if [[ "$trimmed" =~ ^https?://github\.com/([^/]+)/([^/]+)$ ]]; then
OWNER="${BASH_REMATCH[1]}"
NAME="${BASH_REMATCH[2]}"
CLONE_URL="https://github.com/${OWNER}/${NAME}.git"
elif [[ "$trimmed" =~ ^git@github\.com:([^/]+)/([^/]+)$ ]]; then
OWNER="${BASH_REMATCH[1]}"
NAME="${BASH_REMATCH[2]}"
CLONE_URL="git@github.com:${OWNER}/${NAME}.git"
elif [[ "$trimmed" =~ ^([^/[:space:]]+)/([^/[:space:]]+)$ ]]; then
OWNER="${BASH_REMATCH[1]}"
NAME="${BASH_REMATCH[2]}"
CLONE_URL="https://github.com/${OWNER}/${NAME}.git"
else
echo "Error: could not parse '$REPO_INPUT' as a GitHub repo." >&2
usage
fi
: "${OUTPUT_ZIP:=${NAME}.zip}"
OUTPUT_ZIP_ABS="$(cd "$(dirname "$OUTPUT_ZIP")" && pwd)/$(basename "$OUTPUT_ZIP")"
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT
echo "Cloning $CLONE_URL ..."
git clone --depth 1 "$CLONE_URL" "$TMP_DIR/repo" >/dev/null 2>&1 || {
echo "git clone failed. If this is a private repo, check your SSH/HTTPS auth." >&2
exit 1
}
SRC="$TMP_DIR/repo"
# Locate the three required files.
STAINLESS_YML="$(find "$SRC" -maxdepth 2 -type f -iname 'stainless.yml' | head -n1 || true)"
WORKSPACE_JSON="$(find "$SRC" -maxdepth 2 -type f -iname 'stainless-workspace.json' | head -n1 || true)"
# OpenAPI spec: prefer openapi.json, fall back to openapi.yml / openapi.yaml.
OPENAPI_SPEC=""
for candidate in openapi.json openapi.yaml openapi.yml; do
found="$(find "$SRC" -maxdepth 2 -type f -iname "$candidate" | head -n1 || true)"
if [[ -n "$found" ]]; then
OPENAPI_SPEC="$found"
break
fi
done
missing=()
[[ -n "$STAINLESS_YML" ]] || missing+=("stainless.yml")
[[ -n "$WORKSPACE_JSON" ]] || missing+=("stainless-workspace.json")
[[ -n "$OPENAPI_SPEC" ]] || missing+=("openapi.json (or openapi.yaml/.yml)")
if (( ${#missing[@]} > 0 )); then
echo "Error: repo is missing required files: ${missing[*]}" >&2
exit 1
fi
STAGING="$TMP_DIR/stage/stainless"
mkdir -p "$STAGING"
cp "$STAINLESS_YML" "$STAGING/stainless.yml"
cp "$WORKSPACE_JSON" "$STAGING/workspace.json"
cp "$OPENAPI_SPEC" "$STAGING/$(basename "$OPENAPI_SPEC")"
rm -f "$OUTPUT_ZIP_ABS"
( cd "$TMP_DIR/stage" && zip -r "$OUTPUT_ZIP_ABS" stainless >/dev/null )
echo "Created $OUTPUT_ZIP_ABS"
echo "Contents:"
unzip -l "$OUTPUT_ZIP_ABS"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment