package runner
import (
"context"
"encoding/json"
"net/http/httptest"
"strings"
"testing"
"time"
)
// A JOB STARTED BY A TAG KNOWS WHICH TAG (RFC 0020's `tag` event).
//
// The forge puts the tag in the run's input; the runner hands it to
// every step as QUARRY_TAG, so a release workflow on a check-in that
// carries two version tags knows which one fired it. A run no tag
// started has no QUARRY_TAG at all.
func TestAJobStartedByATagSeesItAsQuarryTag(t *testing.T) {
j, _ := json.Marshal(Job{Steps: []JobStep{{Run: `echo "tag=[${QUARRY_TAG-unset}]"`}}})
meta := map[string]string{JobKey: string(j)}
tagged := task("tagged", "c1")
tagged.Input, _ = json.Marshal(map[string]string{"repo": "alpha", "checkin": "c1", "tag": "version-0.2.0"})
tagged.Metadata = meta
plain := task("plain", "c1")
plain.Metadata = meta
b := &fakeBridge{queue: map[string][]polled{"t-job": {tagged, plain}}, resolved: map[string]map[string]any{}, logs: map[string]string{}}
srv := httptest.NewServer(b.handler())
defer srv.Close()
r, err := New(Config{
Bridge: srv.URL, Token: "WT", Tasks: []string{"t-job"}, MaxTasks: 1,
WorkDir: t.TempDir(), Checkout: appCheckout{}, Heartbeat: 50 * time.Millisecond, Logf: t.Logf,
})
if err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithCancel(context.Background())
done := make(chan struct{})
go func() { r.Run(ctx); close(done) }()
for deadline := time.Now().Add(10 * time.Second); time.Now().Before(deadline); time.Sleep(20 * time.Millisecond) {
b.mu.Lock()
n := len(b.resolved)
b.mu.Unlock()
if n == 2 {
break
}
}
cancel()
<-done
b.mu.Lock()
defer b.mu.Unlock()
if !strings.Contains(b.logs["tagged"], "tag=[version-0.2.0]") {
t.Errorf("FAIL: a tag run's step logged %q; want QUARRY_TAG=version-0.2.0", b.logs["tagged"])
}
if !strings.Contains(b.logs["plain"], "tag=[unset]") {
t.Errorf("FAIL: a push run's step logged %q; want no QUARRY_TAG", b.logs["plain"])
}
t.Log("ok: a tag run's steps see QUARRY_TAG; other runs have none")
}