detached 0e6522c

ci_workflow_test.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package kvstore_test
4
5import (
6	"context"
7	"testing"
8
9	"github.com/stretchr/testify/assert"
10	"github.com/stretchr/testify/require"
11
12	"bnema.dev/ermite/internal/domain"
13	"bnema.dev/ermite/internal/ports"
14)
15
16const wfRelease = ".github/workflows/release.yml"
17
18func TestCIWorkflowDisabledState(t *testing.T) {
19	ctx := context.Background()
20	s := openStore(t, t.TempDir())
21	ci := s.CI()
22	a, b := name(t, "a"), name(t, "b")
23	for _, n := range []domain.RepoName{a, b} {
24		require.NoError(t, s.Create(ctx, domain.Repo{Name: n, Visibility: domain.VisibilityPrivate, CreatedAt: created, Settings: domain.DefaultRepoSettings()}))
25	}
26
27	got, err := ci.DisabledWorkflows(ctx, a)
28	require.NoError(t, err)
29	assert.Empty(t, got)
30
31	require.NoError(t, ci.DisableWorkflow(ctx, a, wfRelease, created))
32	require.NoError(t, ci.DisableWorkflow(ctx, a, wfRelease, created), "idempotent")
33	require.NoError(t, ci.DisableWorkflow(ctx, a, ".github/workflows/aur.yml", created))
34	got, err = ci.DisabledWorkflows(ctx, a)
35	require.NoError(t, err)
36	assert.Equal(t, []string{".github/workflows/aur.yml", wfRelease}, got)
37	got, _ = ci.DisabledWorkflows(ctx, b)
38	assert.Empty(t, got, "per repository")
39
40	require.NoError(t, ci.EnableWorkflow(ctx, a, wfRelease))
41	require.NoError(t, ci.EnableWorkflow(ctx, a, wfRelease), "idempotent")
42	got, _ = ci.DisabledWorkflows(ctx, a)
43	assert.Equal(t, []string{".github/workflows/aur.yml"}, got)
44
45	assert.ErrorIs(t, ci.DisableWorkflow(ctx, name(t, "gone"), wfRelease, created), domain.ErrNotFound)
46
47	// The state goes with the repository: a new one under the same name starts enabled.
48	require.NoError(t, s.Delete(ctx, a))
49	require.NoError(t, s.Create(ctx, domain.Repo{Name: a, Visibility: domain.VisibilityPrivate, CreatedAt: created, Settings: domain.DefaultRepoSettings()}))
50	got, _ = ci.DisabledWorkflows(ctx, a)
51	assert.Empty(t, got)
52}
53
54// A run is refused for a disabled workflow in the very transaction that stores
55// it: a disable that lands between the read of the state and the write of the
56// run (here, from inside build) cannot be overtaken, and no run is left.
57func TestCreateRunRefusesAWorkflowDisabledMeanwhile(t *testing.T) {
58	ctx := context.Background()
59	s := openStore(t, t.TempDir())
60	ci := s.CI()
61	n := name(t, "a")
62	require.NoError(t, s.Create(ctx, domain.Repo{Name: n, Visibility: domain.VisibilityPrivate, CreatedAt: created, Settings: domain.DefaultRepoSettings()}))
63	draft := func(id, number int64) ports.CIRunDraft {
64		return ports.CIRunDraft{Run: domain.CIRun{Repo: n, ID: id, Number: number, Attempt: 1, WorkflowPath: wfRelease, Status: domain.CIQueued, CreatedAt: created}}
65	}
66
67	// Enabled: a run is created.
68	_, err := ci.CreateRun(ctx, n, wfRelease, draft)
69	require.NoError(t, err)
70
71	// Disabled from inside build, after the state was read.
72	calls := 0
73	_, err = ci.CreateRun(ctx, n, wfRelease, func(id, number int64) ports.CIRunDraft {
74		calls++
75		if calls == 1 {
76			require.NoError(t, ci.DisableWorkflow(ctx, n, wfRelease, created))
77		}
78		return draft(id, number)
79	})
80	assert.ErrorIs(t, err, domain.ErrWorkflowDisabled)
81	assert.Equal(t, 1, calls, "refused on the retry, before build")
82	runs, err := ci.ListRuns(ctx, n, 0, 10)
83	require.NoError(t, err)
84	assert.Len(t, runs, 1, "no run was stored by the refused call")
85
86	// Other workflows are not affected, and enabling restores it.
87	_, err = ci.CreateRun(ctx, n, ".github/workflows/other.yml", draft)
88	require.NoError(t, err)
89	require.NoError(t, ci.EnableWorkflow(ctx, n, wfRelease))
90	_, err = ci.CreateRun(ctx, n, wfRelease, draft)
91	require.NoError(t, err)
92}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 4

Tags 45

↑↓ moveenter openesc close