Some checks failed
Deploy MineGeo to Dokploy / deploy (push) Failing after 4m2s
177 lines
8.1 KiB
YAML
177 lines
8.1 KiB
YAML
name: Deploy MineGeo to Dokploy
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- master
|
|
|
|
jobs:
|
|
deploy:
|
|
# This label must map to a Docker job image in the Gitea act_runner config.
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Check out the pushed commit
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Upload source and wait for Dokploy build
|
|
shell: bash
|
|
env:
|
|
DOKPLOY_API_KEY: ${{ secrets.DOKPLOY_API_KEY }}
|
|
DOKPLOY_APPLICATION_ID: ${{ secrets.DOKPLOY_APPLICATION_ID }}
|
|
run: |
|
|
set -eu
|
|
umask 077
|
|
|
|
# Pin the deployment origin; runner variables and .env cannot override it.
|
|
readonly DOKPLOY_URL='https://dokploy.minegeo.site'
|
|
: "${DOKPLOY_API_KEY:?Add the DOKPLOY_API_KEY Actions secret.}"
|
|
: "${DOKPLOY_APPLICATION_ID:?Add the DOKPLOY_APPLICATION_ID Actions secret.}"
|
|
|
|
temp_root="${RUNNER_TEMP:-/tmp}"
|
|
mkdir -p "$temp_root"
|
|
auth_file="$(mktemp "$temp_root/minegeo-dokploy-auth.XXXXXX")"
|
|
archive_file="$(mktemp "$temp_root/minegeo-dokploy-source.XXXXXX")"
|
|
response_file="$(mktemp "$temp_root/minegeo-dokploy-response.XXXXXX")"
|
|
deployment_file="$(mktemp "$temp_root/minegeo-dokploy-status.XXXXXX")"
|
|
metrics_file="$(mktemp "$temp_root/minegeo-dokploy-metrics.XXXXXX")"
|
|
error_file="$(mktemp "$temp_root/minegeo-dokploy-errors.XXXXXX")"
|
|
headers_file="$(mktemp "$temp_root/minegeo-dokploy-headers.XXXXXX")"
|
|
cleanup() {
|
|
rm -f "$auth_file" "$archive_file" "$response_file" "$deployment_file" "$metrics_file" "$error_file" "$headers_file"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
# Keep the API key out of curl's command-line arguments and workflow logs.
|
|
printf 'x-api-key: %s\n' "$DOKPLOY_API_KEY" > "$auth_file"
|
|
unset DOKPLOY_API_KEY
|
|
|
|
echo "[Dokploy] Workflow revision: $(git rev-parse HEAD)"
|
|
curl --version | head -n 2
|
|
node scripts/dokploy-diagnostics.mjs environment "$DOKPLOY_URL"
|
|
|
|
dokploy_request() {
|
|
label="$1"
|
|
body_file="$2"
|
|
shift 2
|
|
: > "$body_file"
|
|
: > "$headers_file"
|
|
: > "$metrics_file"
|
|
: > "$error_file"
|
|
echo "[Dokploy] Starting $label at $(date -u '+%Y-%m-%dT%H:%M:%SZ')" >&2
|
|
if curl --silent --show-error \
|
|
--header "@$auth_file" \
|
|
--dump-header "$headers_file" \
|
|
--output "$body_file" \
|
|
--write-out '%{http_code}\nremote_ip=%{remote_ip} remote_port=%{remote_port} local_ip=%{local_ip}\ndns=%{time_namelookup}s connect=%{time_connect}s tls=%{time_appconnect}s first_byte=%{time_starttransfer}s total=%{time_total}s\nssl_verify_result=%{ssl_verify_result} redirects=%{num_redirects} uploaded=%{size_upload}B downloaded=%{size_download}B\n' \
|
|
"$@" > "$metrics_file" 2> "$error_file"; then
|
|
curl_exit=0
|
|
else
|
|
curl_exit=$?
|
|
fi
|
|
node scripts/dokploy-diagnostics.mjs request "$label" "$curl_exit" \
|
|
"$metrics_file" "$error_file" "$headers_file" "$body_file" "$auth_file" >&2
|
|
http_code="$(head -n 1 "$metrics_file")"
|
|
if [ "$curl_exit" -ne 0 ]; then
|
|
echo "[Dokploy] $label failed: curl exit $curl_exit, HTTP ${http_code:-000}." >&2
|
|
return 1
|
|
fi
|
|
case "$http_code" in
|
|
2??) ;;
|
|
*) echo "[Dokploy] $label failed: HTTP ${http_code:-000}." >&2; return 1 ;;
|
|
esac
|
|
}
|
|
|
|
# Only committed files from this revision are uploaded. This excludes
|
|
# .git metadata, local .env files, caches, and untracked workspace data.
|
|
git archive --format=zip --output="$archive_file" HEAD
|
|
echo "[Dokploy] Source archive size: $(wc -c < "$archive_file") bytes"
|
|
|
|
dokploy_request "API preflight GET /api/deployment.all" "$deployment_file" --get \
|
|
--data-urlencode "applicationId=$DOKPLOY_APPLICATION_ID" \
|
|
--connect-timeout 10 --max-time 30 \
|
|
"$DOKPLOY_URL/api/deployment.all"
|
|
|
|
previous_id="$(DOKPLOY_STATUS_FILE="$deployment_file" node <<'NODE'
|
|
const fs = require("node:fs");
|
|
let payload;
|
|
try { payload = JSON.parse(fs.readFileSync(process.env.DOKPLOY_STATUS_FILE, "utf8")); }
|
|
catch { console.error("Dokploy deployment list was not valid JSON."); process.exit(2); }
|
|
const rows = Array.isArray(payload)
|
|
? payload
|
|
: [payload?.data, payload?.deployments, payload?.items].find(Array.isArray);
|
|
if (!rows) process.exit(2);
|
|
const latest = rows[0];
|
|
process.stdout.write(String(latest?.id ?? latest?.deploymentId ?? ""));
|
|
NODE
|
|
)" || {
|
|
node scripts/dokploy-diagnostics.mjs request "API preflight response parsing" parse-error \
|
|
"$metrics_file" "$error_file" "$headers_file" "$deployment_file" "$auth_file" >&2
|
|
echo "Dokploy returned an unexpected deployment list; source was not uploaded." >&2
|
|
exit 1
|
|
}
|
|
|
|
dokploy_request "Source upload POST /api/application.dropDeployment" "$response_file" \
|
|
--form-string "applicationId=$DOKPLOY_APPLICATION_ID" \
|
|
--form "zip=@$archive_file;type=application/zip" \
|
|
--connect-timeout 15 --max-time 1800 \
|
|
"$DOKPLOY_URL/api/application.dropDeployment"
|
|
echo "Dokploy accepted the source archive; waiting for the VPS build and deployment."
|
|
|
|
attempt=0
|
|
while [ "$attempt" -lt 360 ]; do
|
|
dokploy_request "Deployment status GET /api/deployment.all (attempt $((attempt + 1))/360)" "$deployment_file" --get \
|
|
--data-urlencode "applicationId=$DOKPLOY_APPLICATION_ID" \
|
|
--connect-timeout 10 --max-time 30 \
|
|
"$DOKPLOY_URL/api/deployment.all"
|
|
|
|
status="$(DOKPLOY_STATUS_FILE="$deployment_file" DOKPLOY_PREVIOUS_DEPLOYMENT_ID="$previous_id" node <<'NODE'
|
|
const fs = require("node:fs");
|
|
let payload;
|
|
try { payload = JSON.parse(fs.readFileSync(process.env.DOKPLOY_STATUS_FILE, "utf8")); }
|
|
catch { console.error("Dokploy deployment status was not valid JSON."); process.exit(2); }
|
|
const rows = Array.isArray(payload)
|
|
? payload
|
|
: [payload?.data, payload?.deployments, payload?.items].find(Array.isArray);
|
|
if (!rows) process.exit(2);
|
|
const previousId = process.env.DOKPLOY_PREVIOUS_DEPLOYMENT_ID;
|
|
const current = rows.find((row) => {
|
|
const id = String(row?.id ?? row?.deploymentId ?? "");
|
|
return id && id !== previousId;
|
|
});
|
|
if (!current) {
|
|
process.stdout.write("waiting");
|
|
} else {
|
|
const value = String(current.status ?? "unknown").toLowerCase();
|
|
process.stdout.write(["done", "error", "running", "queued", "building", "deploying", "pending", "cancelled", "canceled"].includes(value) ? value : "unknown");
|
|
}
|
|
NODE
|
|
)" || {
|
|
node scripts/dokploy-diagnostics.mjs request "Deployment status response parsing" parse-error \
|
|
"$metrics_file" "$error_file" "$headers_file" "$deployment_file" "$auth_file" >&2
|
|
echo "Dokploy returned an unexpected deployment status; inspect the response diagnostics above." >&2
|
|
exit 1
|
|
}
|
|
|
|
case "$status" in
|
|
done)
|
|
echo "Dokploy build and deployment completed successfully."
|
|
exit 0
|
|
;;
|
|
error|cancelled|canceled)
|
|
echo "Dokploy reported a failed deployment; inspect that deployment's logs in Dokploy." >&2
|
|
exit 1
|
|
;;
|
|
*)
|
|
if [ $((attempt % 3)) -eq 0 ]; then
|
|
echo "Dokploy build status: $status."
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
sleep 10
|
|
attempt=$((attempt + 1))
|
|
done
|
|
|
|
echo "Timed out waiting for Dokploy to finish; inspect the deployment in Dokploy." >&2
|
|
exit 1
|