Skip to content

Commit 34c35b6

Browse files
committed
reafctor workflow to trigger cli tests
1 parent 0310fe5 commit 34c35b6

File tree

3 files changed

+772
-485
lines changed

3 files changed

+772
-485
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: 'Checkout JFrog Repository'
2+
description: 'Checkout a JFrog repository with conditional logic based on whether repo/ref are provided'
3+
4+
inputs:
5+
repository:
6+
description: 'Repository to checkout (e.g., jfrog/jfrog-cli). If empty, step is skipped.'
7+
required: false
8+
default: ''
9+
ref:
10+
description: 'Branch/tag/SHA to checkout'
11+
required: false
12+
default: 'master'
13+
path:
14+
description: 'Relative path to checkout to'
15+
required: true
16+
default-repository:
17+
description: 'Default repository to use if repository input is empty but checkout is still needed'
18+
required: false
19+
default: ''
20+
default-ref:
21+
description: 'Default ref to use with default-repository'
22+
required: false
23+
default: 'master'
24+
25+
runs:
26+
using: 'composite'
27+
steps:
28+
# Checkout from specified repository if provided
29+
- name: Checkout from specified repo
30+
if: inputs.repository != ''
31+
uses: actions/checkout@v5
32+
with:
33+
repository: ${{ inputs.repository }}
34+
ref: ${{ inputs.ref }}
35+
path: ${{ inputs.path }}
36+
37+
# Checkout from default repository if no specific repo but default is provided
38+
- name: Checkout from default repo
39+
if: inputs.repository == '' && inputs.default-repository != ''
40+
uses: actions/checkout@v5
41+
with:
42+
repository: ${{ inputs.default-repository }}
43+
ref: ${{ inputs.default-ref }}
44+
path: ${{ inputs.path }}

.github/tools/detect-deps/main.go

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"os"
7+
"os/exec"
8+
"strings"
9+
)
10+
11+
// GoMod represents the JSON structure from `go mod edit -json`
12+
type GoMod struct {
13+
Module Module `json:"Module"`
14+
Go string `json:"Go"`
15+
Require []Require `json:"Require"`
16+
Replace []Replace `json:"Replace"`
17+
}
18+
19+
// Module represents the module path
20+
type Module struct {
21+
Path string `json:"Path"`
22+
}
23+
24+
// Require represents a required module
25+
type Require struct {
26+
Path string `json:"Path"`
27+
Version string `json:"Version"`
28+
Indirect bool `json:"Indirect"`
29+
}
30+
31+
// Replace represents a replace directive
32+
type Replace struct {
33+
Old ModuleVersion `json:"Old"`
34+
New ModuleVersion `json:"New"`
35+
}
36+
37+
// ModuleVersion represents a module with optional version
38+
type ModuleVersion struct {
39+
Path string `json:"Path"`
40+
Version string `json:"Version,omitempty"`
41+
}
42+
43+
// DependencyInfo holds information about a detected dependency
44+
type DependencyInfo struct {
45+
Name string
46+
ModulePath string
47+
Repo string
48+
Ref string
49+
}
50+
51+
// jfrogDependencies maps short names to their module paths
52+
var jfrogDependencies = map[string]string{
53+
"build-info-go": "github.com/jfrog/build-info-go",
54+
"jfrog-client-go": "github.com/jfrog/jfrog-client-go",
55+
"jfrog-cli-core": "github.com/jfrog/jfrog-cli-core/v2",
56+
}
57+
58+
func main() {
59+
// Get current branch from environment
60+
currentBranch := os.Getenv("CURRENT_BRANCH")
61+
if currentBranch == "" {
62+
currentBranch = "main"
63+
}
64+
65+
// Parse go.mod
66+
goMod, err := parseGoMod()
67+
if err != nil {
68+
fmt.Fprintf(os.Stderr, "Error parsing go.mod: %v\n", err)
69+
os.Exit(1)
70+
}
71+
72+
// Build a map of replace directives
73+
replaces := make(map[string]Replace)
74+
for _, r := range goMod.Replace {
75+
replaces[r.Old.Path] = r
76+
}
77+
78+
// Open GITHUB_OUTPUT file for writing outputs
79+
outputFile := os.Getenv("GITHUB_OUTPUT")
80+
var output *os.File
81+
if outputFile != "" {
82+
var err error
83+
output, err = os.OpenFile(outputFile, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
84+
if err != nil {
85+
fmt.Fprintf(os.Stderr, "Error opening GITHUB_OUTPUT: %v\n", err)
86+
os.Exit(1)
87+
}
88+
defer output.Close()
89+
}
90+
91+
// Process each dependency
92+
for name, modulePath := range jfrogDependencies {
93+
info := detectDependency(name, modulePath, replaces, currentBranch)
94+
writeOutput(output, name, info)
95+
}
96+
}
97+
98+
// parseGoMod runs `go mod edit -json` and parses the output
99+
func parseGoMod() (*GoMod, error) {
100+
cmd := exec.Command("go", "mod", "edit", "-json")
101+
out, err := cmd.Output()
102+
if err != nil {
103+
return nil, fmt.Errorf("failed to run go mod edit -json: %w", err)
104+
}
105+
106+
var goMod GoMod
107+
if err := json.Unmarshal(out, &goMod); err != nil {
108+
return nil, fmt.Errorf("failed to parse go.mod JSON: %w", err)
109+
}
110+
111+
return &goMod, nil
112+
}
113+
114+
// detectDependency determines the repository and ref for a dependency
115+
func detectDependency(name, modulePath string, replaces map[string]Replace, currentBranch string) *DependencyInfo {
116+
// Check if there's a replace directive for this module
117+
if replace, ok := replaces[modulePath]; ok {
118+
// Parse the replace target
119+
newPath := replace.New.Path
120+
if strings.HasPrefix(newPath, "github.com/") {
121+
// Extract repo and version/ref
122+
parts := strings.TrimPrefix(newPath, "github.com/")
123+
repo := parts
124+
ref := replace.New.Version
125+
126+
// Handle version format like "v1.2.3-0.20240101-abc123"
127+
// The ref might be a pseudo-version containing a commit hash
128+
if ref != "" {
129+
fmt.Printf("Found replace directive: %s => %s @ %s\n", name, repo, ref)
130+
return &DependencyInfo{
131+
Name: name,
132+
ModulePath: modulePath,
133+
Repo: repo,
134+
Ref: ref,
135+
}
136+
}
137+
}
138+
}
139+
140+
// No replace directive found, check if current branch exists in the dependency repo
141+
repo := fmt.Sprintf("jfrog/%s", name)
142+
if name == "jfrog-cli-core" {
143+
repo = "jfrog/jfrog-cli-core"
144+
}
145+
146+
// Check if the current branch exists in the repo
147+
if branchExists(repo, currentBranch) {
148+
fmt.Printf("Branch '%s' exists in %s, using it\n", currentBranch, repo)
149+
return &DependencyInfo{
150+
Name: name,
151+
ModulePath: modulePath,
152+
Repo: repo,
153+
Ref: currentBranch,
154+
}
155+
}
156+
157+
fmt.Printf("No matching branch for %s, will use default (master)\n", name)
158+
return nil
159+
}
160+
161+
// branchExists checks if a branch exists in a GitHub repository
162+
func branchExists(repo, branch string) bool {
163+
if branch == "" || branch == "main" || branch == "master" {
164+
return false
165+
}
166+
167+
url := fmt.Sprintf("https://github.com/%s.git", repo)
168+
cmd := exec.Command("git", "ls-remote", "--heads", url, branch)
169+
out, err := cmd.Output()
170+
if err != nil {
171+
return false
172+
}
173+
174+
return strings.Contains(string(out), fmt.Sprintf("refs/heads/%s", branch))
175+
}
176+
177+
// writeOutput writes the dependency info to GITHUB_OUTPUT
178+
func writeOutput(output *os.File, name string, info *DependencyInfo) {
179+
// Convert name to output key format (e.g., "build-info-go" -> "build_info_go")
180+
keyName := strings.ReplaceAll(name, "-", "_")
181+
182+
var repo, ref string
183+
if info != nil {
184+
repo = info.Repo
185+
ref = info.Ref
186+
}
187+
188+
// Write to GITHUB_OUTPUT if available
189+
if output != nil {
190+
fmt.Fprintf(output, "%s_repo=%s\n", keyName, repo)
191+
fmt.Fprintf(output, "%s_ref=%s\n", keyName, ref)
192+
}
193+
194+
if info != nil {
195+
fmt.Printf(" %s_repo=%s\n", keyName, repo)
196+
fmt.Printf(" %s_ref=%s\n", keyName, ref)
197+
} else {
198+
fmt.Printf(" %s: using default\n", keyName)
199+
}
200+
}

0 commit comments

Comments
 (0)