Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Merge branch 'claude/cool-newton-7nm8r9' (#36): real GitHub Actions on g1t, managed deploy workflows, g1t/deploy and the Sysbox runner 0.2.0. The merge keeps both sides' webhook events and API operations, says agent images need tar, guards the job engine's stop to Unix so the runner builds on Windows again, and keeps the moves tests' previews from going idle as the calendar passes their fixture's date. | 1 | #!/usr/bin/env bash |
| 2 | # The g1t/deploy action's work (see README.md): opens a g1t.page build for | |
| 3 | # this job with POST /repos/{owner}/{repo}/deployments/builds, masks its | |
| 4 | # token and the project's build secrets, and runs `g1t-runner deploy` in | |
| 5 | # the checkout with them. Reads the action's inputs as INPUT_* variables. | |
| 6 | set -euo pipefail | |
| 7 | ||
| 8 | api="${GITHUB_API_URL:-https://api.g1t.sh}" | |
| 9 | api="${api%/}" | |
| 10 | repo="${GITHUB_REPOSITORY:?GITHUB_REPOSITORY is not set: run this in a g1t Actions job.}" | |
| 11 | if [ -z "${INPUT_TOKEN:-}" ]; then | |
| 12 | echo "::error::The token input is empty: give the job's own token, \${{ github.token }}, with permissions: deployments: write." | |
| 13 | exit 1 | |
| 14 | fi | |
| 15 | ||
| 16 | # JSON, with jq where there is one, else Python. | |
| 17 | if command -v jq >/dev/null 2>&1; then | |
| 18 | field() { jq -r --arg key "$1" '.[$key] // empty | if type == "object" or type == "array" then tojson else tostring end'; } | |
| 19 | values() { jq -r --arg key "$1" '.[$key] // {} | .[] | tostring'; } | |
| 20 | message() { jq -r '.message // .error.message // empty' 2>/dev/null || true; } | |
| 21 | body() { jq -cn --arg project "$1" --arg sha "$2" '{project: $project, sha: $sha} | with_entries(select(.value != ""))'; } | |
| 22 | elif command -v python3 >/dev/null 2>&1; then | |
| 23 | field() { | |
| 24 | python3 -c 'import json, sys | |
| 25 | v = json.load(sys.stdin).get(sys.argv[1]) | |
| 26 | if v is None: sys.exit(0) | |
| 27 | print(json.dumps(v, separators=(",", ":")) if isinstance(v, (dict, list)) else str(v).lower() if isinstance(v, bool) else v)' "$1" | |
| 28 | } | |
| 29 | values() { python3 -c 'import json, sys | |
| 30 | for v in (json.load(sys.stdin).get(sys.argv[1]) or {}).values(): print(v)' "$1"; } | |
| 31 | message() { python3 -c 'import json, sys | |
| 32 | d = json.load(sys.stdin); print(d.get("message") or (d.get("error") or {}).get("message") or "")' 2>/dev/null || true; } | |
| 33 | body() { python3 -c 'import json, sys | |
| 34 | print(json.dumps({k: v for k, v in (("project", sys.argv[1]), ("sha", sys.argv[2])) if v}))' "$1" "$2"; } | |
| 35 | else | |
| 36 | echo "::error::g1t/deploy needs jq or python3 on the machine." | |
| 37 | exit 1 | |
| 38 | fi | |
| 39 | ||
| 40 | # The build, opened for this job. | |
| 41 | request="$(body "${INPUT_PROJECT:-}" "${INPUT_SHA:-}")" | |
| 42 | answer_file="$(mktemp)" | |
| 43 | trap 'rm -f "${answer_file}"' EXIT | |
| 44 | status="$(curl -sS -o "${answer_file}" -w '%{http_code}' -X POST \ | |
| 45 | -H "Authorization: Bearer ${INPUT_TOKEN}" \ | |
| 46 | -H "Content-Type: application/json" \ | |
| 47 | -H "Accept: application/json" \ | |
| 48 | --data "${request}" \ | |
| 49 | "${api}/repos/${repo}/deployments/builds")" || { | |
| 50 | echo "::error::Could not reach ${api} to open the build." | |
| 51 | exit 1 | |
| 52 | } | |
| 53 | answer="$(cat "${answer_file}")" | |
| 54 | if [ "${status}" != "200" ]; then | |
| 55 | why="$(message <<<"${answer}")" | |
| 56 | echo "::error::g1t did not open the build (${status}): ${why:-no reason given}" | |
| 57 | exit 1 | |
| 58 | fi | |
| 59 | ||
| 60 | # Nothing secret is printed before it is masked. | |
| 61 | build_token="$(field token <<<"${answer}")" | |
| 62 | echo "::add-mask::${build_token}" | |
| 63 | while IFS= read -r secret; do | |
| 64 | [ -n "${secret}" ] && echo "::add-mask::${secret}" | |
| 65 | done < <(values build_secrets <<<"${answer}") | |
| 66 | ||
| 67 | deployment_id="$(field deploy_id <<<"${answer}")" | |
| 68 | kind="$(field kind <<<"${answer}")" | |
| 69 | url="$(field url <<<"${answer}")" | |
| 70 | project="$(field project <<<"${answer}")" | |
| 71 | branch="$(field branch <<<"${answer}")" | |
| 72 | trusted="$(field trusted <<<"${answer}")" | |
| 73 | { | |
| 74 | echo "deployment-id=${deployment_id}" | |
| 75 | echo "kind=${kind}" | |
| 76 | echo "url=${url}" | |
| 77 | } >>"${GITHUB_OUTPUT:-/dev/null}" | |
| 78 | ||
| 79 | if [ "${kind}" = "production" ]; then | |
| 80 | echo "Building ${project} for production, at ${url}" | |
| 81 | else | |
| 82 | echo "Building the ${branch} preview of ${project}, at ${url}" | |
| 83 | fi | |
| 84 | if [ "${trusted}" != "true" ]; then | |
| 85 | echo "::notice::This run is not trusted with the project's build secrets (a pull request from outside, or a run that needed approval): it builds without them." | |
| 86 | fi | |
| 87 | ||
| 88 | # What the step gives wins over the project's own settings. | |
| 89 | pick() { if [ -n "$1" ]; then echo "$1"; else field "$2" <<<"${answer}"; fi; } | |
| 90 | export DEPLOY_ID="${deployment_id}" | |
| 91 | export DEPLOY_TOKEN="${build_token}" | |
| 92 | export G1T_API="${api}" | |
| 93 | export ROOT_DIR="$(pick "${INPUT_ROOT_DIR:-}" root_dir)" | |
| 94 | export BUILD_COMMAND="$(pick "${INPUT_BUILD_COMMAND:-}" build_command)" | |
| 95 | export OUTPUT_DIR="$(pick "${INPUT_OUTPUT_DIR:-}" output_dir)" | |
| 96 | export BUILD_ENV="$(field build_env <<<"${answer}")" | |
| 97 | export BUILD_SECRETS="$(field build_secrets <<<"${answer}")" | |
| 98 | unset GIT_REMOTE | |
| 99 | ||
| 100 | runner="$(bash "${GITHUB_ACTION_PATH:-$(dirname "$0")}/runner.sh")" | |
| 101 | if ! "${runner}" deploy --help 2>/dev/null | grep -q DEPLOY_ID; then | |
| 102 | echo "::error::${runner} is older than g1t/deploy needs: update it (g1t-runner update), or let the action download it by taking it off PATH." | |
| 103 | exit 1 | |
| 104 | fi | |
| 105 | "${runner}" deploy | |
| 106 | echo "Deployed: ${url}" | |
| 107 | if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then | |
| 108 | echo "Deployed ${project} (${kind}) to ${url}" >>"${GITHUB_STEP_SUMMARY}" | |
| 109 | fi |
This file's history is long; its oldest lines are credited to the oldest commit read.