#!/usr/bin/env bash

# Remote task-cache uploads must not carry env or var values in plaintext.

UPLOAD_DIR="$(mktemp -d "${TMPDIR:-/tmp}/remote-cache-uploads.XXXXXX")"

start_http_server --handler - "$UPLOAD_DIR" <<'PY'
import http.server
import itertools
import os
import sys

upload_dir = sys.argv[1]
counter = itertools.count()


class Handler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_error(404)

    def do_PUT(self):
        length = int(self.headers.get("Content-Length", "0"))
        body = self.rfile.read(length)
        path = os.path.join(upload_dir, f"upload-{next(counter):04d}")
        with open(path, "wb") as file:
            file.write(body)
        self.send_response(201)
        self.send_header("Content-Length", "0")
        self.end_headers()
PY

cat <<EOF >mise.toml
[settings]
experimental = true
task.cache.remote_url = "http://127.0.0.1:$HTTP_PORT/cache"
task.cache.remote_namespace = "test"

[env]
REDACTED_TOKEN = { value = "redacted-env-value-e2e", redact = true }

[vars]
deploy_key = "plain-var-value-e2e"

[tasks.build]
run = "echo ran >> runs.txt"
env = { TASK_TOKEN = "task-env-value-e2e" }
sources = ["input.txt"]
outputs = []
cache = { enabled = true, env = ["REDACTED_TOKEN", "CACHE_TOKEN"] }

[tasks.publish]
run = "echo published >> publishes.txt"
sources = ["input.txt"]
outputs = []
cache = { enabled = true }

[tasks.release]
depends = [{ task = "publish", args = ["{{env.REDACTED_TOKEN}}", "{{vars.deploy_key}}"] }]
run = "true"
EOF

printf 'input\n' >input.txt

# Remote writes are only enabled for trusted CI writers.
export GITHUB_ACTIONS=true GITHUB_EVENT_NAME=push GITHUB_REF_TYPE=branch GITHUB_REF_PROTECTED=true
CACHE_TOKEN=cache-env-value-e2e mise run build
assert "wc -l < runs.txt | tr -d ' '" "1"

# The action blob was uploaded, but none of the values it was built from.
assert_contains "cat $UPLOAD_DIR/*" '"task":"build"'
assert_contains "cat $UPLOAD_DIR/*" '"REDACTED_TOKEN"'
assert_not_contains "cat $UPLOAD_DIR/*" "redacted-env-value-e2e"
assert_not_contains "cat $UPLOAD_DIR/*" "cache-env-value-e2e"
assert_not_contains "cat $UPLOAD_DIR/*" "task-env-value-e2e"
assert_not_contains "cat $UPLOAD_DIR/*" "plain-var-value-e2e"

# The digests still key the cache: same values hit, a changed value misses.
CACHE_TOKEN=cache-env-value-e2e mise run build
assert "wc -l < runs.txt | tr -d ' '" "1"
CACHE_TOKEN=rotated-value-e2e mise run build
assert "wc -l < runs.txt | tr -d ' '" "2"

# Dependency args rendered from env and vars, and CLI args, are digested too.
rm -f "$UPLOAD_DIR"/*
mise run release
assert "wc -l < publishes.txt | tr -d ' '" "1"
# Different args still change the key, so this runs again.
mise run publish -- cli-arg-value-e2e
assert "wc -l < publishes.txt | tr -d ' '" "2"
assert_contains "cat $UPLOAD_DIR/*" '"task":"publish"'
assert_not_contains "cat $UPLOAD_DIR/*" "redacted-env-value-e2e"
assert_not_contains "cat $UPLOAD_DIR/*" "plain-var-value-e2e"
assert_not_contains "cat $UPLOAD_DIR/*" "cli-arg-value-e2e"
