Skip to content

Commit cab5521

Browse files
authored
Prevent adding workflows from current repository (#3443)
1 parent bc8fe77 commit cab5521

2 files changed

Lines changed: 245 additions & 0 deletions

File tree

pkg/cli/add_command.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,24 @@ func AddWorkflows(workflows []string, number int, verbose bool, engineOverride s
175175
processedWorkflows = append(processedWorkflows, spec)
176176
}
177177

178+
// Check if any workflow is from the current repository
179+
// Skip this check if we can't determine the current repository (e.g., not in a git repo)
180+
currentRepoSlug, repoErr := GetCurrentRepoSlug()
181+
if repoErr == nil {
182+
// We successfully determined the current repository, check all workflow specs
183+
for _, spec := range processedWorkflows {
184+
// Skip local workflow specs (starting with "./")
185+
if strings.HasPrefix(spec.WorkflowPath, "./") {
186+
continue
187+
}
188+
189+
if spec.RepoSlug == currentRepoSlug {
190+
return fmt.Errorf("cannot add workflows from the current repository (%s). The 'add' command is for installing workflows from other repositories", currentRepoSlug)
191+
}
192+
}
193+
}
194+
// If we can't determine the current repository, proceed without the check
195+
178196
// Install required repositories
179197
for repo, version := range repoVersions {
180198
repoWithVersion := repo

pkg/cli/add_current_repo_test.go

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
package cli
2+
3+
import (
4+
"os"
5+
"os/exec"
6+
"strings"
7+
"testing"
8+
)
9+
10+
// TestAddWorkflowsFromCurrentRepository tests that adding workflows from the current repository is prevented
11+
func TestAddWorkflowsFromCurrentRepository(t *testing.T) {
12+
// Create a temporary git repository to simulate being in a repository
13+
tempDir := t.TempDir()
14+
15+
// Initialize a proper git repository
16+
initCmd := exec.Command("git", "init")
17+
initCmd.Dir = tempDir
18+
if err := initCmd.Run(); err != nil {
19+
t.Fatalf("Failed to initialize git repository: %v", err)
20+
}
21+
22+
// Add a remote origin
23+
remoteCmd := exec.Command("git", "remote", "add", "origin", "https://github.com/test-owner/test-repo.git")
24+
remoteCmd.Dir = tempDir
25+
if err := remoteCmd.Run(); err != nil {
26+
t.Fatalf("Failed to add remote origin: %v", err)
27+
}
28+
29+
// Change to the temp directory
30+
oldDir, err := os.Getwd()
31+
if err != nil {
32+
t.Fatalf("Failed to get current directory: %v", err)
33+
}
34+
defer os.Chdir(oldDir)
35+
36+
if err := os.Chdir(tempDir); err != nil {
37+
t.Fatalf("Failed to change to temp directory: %v", err)
38+
}
39+
40+
// Clear the repository slug cache to ensure fresh lookup
41+
ClearCurrentRepoSlugCache()
42+
43+
tests := []struct {
44+
name string
45+
workflowSpecs []string
46+
expectError bool
47+
errorContains string
48+
}{
49+
{
50+
name: "prevent adding workflow from current repository",
51+
workflowSpecs: []string{"test-owner/test-repo/my-workflow"},
52+
expectError: true,
53+
errorContains: "cannot add workflows from the current repository",
54+
},
55+
{
56+
name: "prevent adding workflow from current repository with version",
57+
workflowSpecs: []string{"test-owner/test-repo/my-workflow@v1.0.0"},
58+
expectError: true,
59+
errorContains: "cannot add workflows from the current repository",
60+
},
61+
{
62+
name: "prevent adding workflow from current repository with wildcard",
63+
workflowSpecs: []string{"test-owner/test-repo/*"},
64+
expectError: true,
65+
errorContains: "cannot add workflows from the current repository",
66+
},
67+
{
68+
name: "allow adding workflow from different repository",
69+
workflowSpecs: []string{"different-owner/different-repo/workflow"},
70+
expectError: false, // This will still fail because package doesn't exist, but not due to current repo check
71+
},
72+
}
73+
74+
for _, tt := range tests {
75+
t.Run(tt.name, func(t *testing.T) {
76+
// Clear cache before each test
77+
ClearCurrentRepoSlugCache()
78+
79+
err := AddWorkflows(tt.workflowSpecs, 1, false, "", "", false, "", false, false)
80+
81+
if tt.expectError {
82+
if err == nil {
83+
t.Errorf("Expected error but got nil")
84+
return
85+
}
86+
if !strings.Contains(err.Error(), tt.errorContains) {
87+
t.Errorf("Expected error to contain %q, got: %v", tt.errorContains, err)
88+
}
89+
} else {
90+
// For "allow" case, we expect a different error (workflow not found, not current repo error)
91+
if err != nil && strings.Contains(err.Error(), "cannot add workflows from the current repository") {
92+
t.Errorf("Should not get current repository error for different repository, got: %v", err)
93+
}
94+
}
95+
})
96+
}
97+
}
98+
99+
// TestAddWorkflowsFromCurrentRepositoryMultiple tests prevention for multiple workflows
100+
func TestAddWorkflowsFromCurrentRepositoryMultiple(t *testing.T) {
101+
// Create a temporary git repository to simulate being in a repository
102+
tempDir := t.TempDir()
103+
104+
// Initialize a proper git repository
105+
initCmd := exec.Command("git", "init")
106+
initCmd.Dir = tempDir
107+
if err := initCmd.Run(); err != nil {
108+
t.Fatalf("Failed to initialize git repository: %v", err)
109+
}
110+
111+
// Add a remote origin with SSH format
112+
remoteCmd := exec.Command("git", "remote", "add", "origin", "git@github.com:myorg/myrepo.git")
113+
remoteCmd.Dir = tempDir
114+
if err := remoteCmd.Run(); err != nil {
115+
t.Fatalf("Failed to add remote origin: %v", err)
116+
}
117+
118+
// Change to the temp directory
119+
oldDir, err := os.Getwd()
120+
if err != nil {
121+
t.Fatalf("Failed to get current directory: %v", err)
122+
}
123+
defer os.Chdir(oldDir)
124+
125+
if err := os.Chdir(tempDir); err != nil {
126+
t.Fatalf("Failed to change to temp directory: %v", err)
127+
}
128+
129+
// Clear the repository slug cache
130+
ClearCurrentRepoSlugCache()
131+
132+
tests := []struct {
133+
name string
134+
workflowSpecs []string
135+
expectError bool
136+
errorContains string
137+
}{
138+
{
139+
name: "prevent when first workflow is from current repository",
140+
workflowSpecs: []string{
141+
"myorg/myrepo/workflow1",
142+
"otherorg/otherrepo/workflow2",
143+
},
144+
expectError: true,
145+
errorContains: "cannot add workflows from the current repository",
146+
},
147+
{
148+
name: "prevent when second workflow is from current repository",
149+
workflowSpecs: []string{
150+
"otherorg/otherrepo/workflow1",
151+
"myorg/myrepo/workflow2",
152+
},
153+
expectError: true,
154+
errorContains: "cannot add workflows from the current repository",
155+
},
156+
{
157+
name: "prevent when all workflows are from current repository",
158+
workflowSpecs: []string{
159+
"myorg/myrepo/workflow1",
160+
"myorg/myrepo/workflow2",
161+
},
162+
expectError: true,
163+
errorContains: "cannot add workflows from the current repository",
164+
},
165+
{
166+
name: "allow when all workflows are from different repositories",
167+
workflowSpecs: []string{
168+
"org1/repo1/workflow1",
169+
"org2/repo2/workflow2",
170+
},
171+
expectError: false,
172+
},
173+
}
174+
175+
for _, tt := range tests {
176+
t.Run(tt.name, func(t *testing.T) {
177+
// Clear cache before each test
178+
ClearCurrentRepoSlugCache()
179+
180+
err := AddWorkflows(tt.workflowSpecs, 1, false, "", "", false, "", false, false)
181+
182+
if tt.expectError {
183+
if err == nil {
184+
t.Errorf("Expected error but got nil")
185+
return
186+
}
187+
if !strings.Contains(err.Error(), tt.errorContains) {
188+
t.Errorf("Expected error to contain %q, got: %v", tt.errorContains, err)
189+
}
190+
} else {
191+
// For "allow" case, we expect a different error (workflow not found, not current repo error)
192+
if err != nil && strings.Contains(err.Error(), "cannot add workflows from the current repository") {
193+
t.Errorf("Should not get current repository error for different repository, got: %v", err)
194+
}
195+
}
196+
})
197+
}
198+
}
199+
200+
// TestAddWorkflowsFromCurrentRepositoryNotInGitRepo tests behavior when not in a git repository
201+
func TestAddWorkflowsFromCurrentRepositoryNotInGitRepo(t *testing.T) {
202+
// Create a temporary directory without .git
203+
tempDir := t.TempDir()
204+
205+
// Change to the temp directory
206+
oldDir, err := os.Getwd()
207+
if err != nil {
208+
t.Fatalf("Failed to get current directory: %v", err)
209+
}
210+
defer os.Chdir(oldDir)
211+
212+
if err := os.Chdir(tempDir); err != nil {
213+
t.Fatalf("Failed to change to temp directory: %v", err)
214+
}
215+
216+
// Clear the repository slug cache
217+
ClearCurrentRepoSlugCache()
218+
219+
// When not in a git repo, the check should be skipped (can't determine current repo)
220+
// The function should proceed and fail for other reasons (e.g., workflow not found)
221+
err = AddWorkflows([]string{"some-owner/some-repo/workflow"}, 1, false, "", "", false, "", false, false)
222+
223+
// Should NOT get the "cannot add workflows from the current repository" error
224+
if err != nil && strings.Contains(err.Error(), "cannot add workflows from the current repository") {
225+
t.Errorf("Should not check current repository when not in a git repo, got: %v", err)
226+
}
227+
}

0 commit comments

Comments
 (0)