Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cmd/llpkgstore/internal/verification.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

"github.com/goplus/llpkgstore/config"
"github.com/goplus/llpkgstore/internal/actions"
"github.com/goplus/llpkgstore/internal/actions/env"
"github.com/goplus/llpkgstore/internal/actions/generator/llcppg"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -61,7 +62,7 @@
}
// output parsed path to Github Env for demotest
b, _ := json.Marshal(&paths)
actions.Setenv(map[string]string{
env.Setenv(env.Env{

Check warning on line 65 in cmd/llpkgstore/internal/verification.go

View check run for this annotation

Codecov / codecov/patch

cmd/llpkgstore/internal/verification.go#L65

Added line #L65 was not covered by tests
"LLPKG_PATH": string(b),
})
}
Expand Down
186 changes: 42 additions & 144 deletions internal/actions/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"slices"
Expand All @@ -14,33 +13,20 @@
"sync"

"github.com/goplus/llpkgstore/config"
"github.com/goplus/llpkgstore/internal/actions/versions"
"github.com/goplus/llpkgstore/internal/actions/mappingtable"
"github.com/goplus/llpkgstore/internal/actions/parser/prefix"
"github.com/goplus/llpkgstore/internal/actions/version"
"golang.org/x/mod/semver"
)

// GitHubEvent caches parsed GitHub event data from GITHUB_EVENT_PATH
var GitHubEvent = sync.OnceValue(parseGitHubEvent)
var (
// GitHubEvent caches parsed GitHub event data from GITHUB_EVENT_PATH
GitHubEvent = sync.OnceValue(parseGitHubEvent)

// In our previous design, each platform should generate *_{OS}_{Arch}.go file
// Feb 12th, this design revoked, still keep the code.
var currentSuffix = runtime.GOOS + "_" + runtime.GOARCH

// must panics if the error is non-nil, halting execution
func must(err error) {
if err != nil {
panic(err)
}
}

// envToString converts environment variables map to newline-separated key=value pairs for GitHub Actions
func envToString(envm map[string]string) string {
var env []string

for name, value := range envm {
env = append(env, fmt.Sprintf("%s=%s", name, value))
}
return strings.Join(env, "\n")
}
// In our previous design, each platform should generate *_{OS}_{Arch}.go file
// Feb 12th, this design revoked, still keep the code.
_currentSuffix = runtime.GOOS + "_" + runtime.GOARCH
)

// parseGitHubEvent parses the GitHub event payload from GITHUB_EVENT_PATH into a map
func parseGitHubEvent() map[string]any {
Expand All @@ -49,9 +35,8 @@
panic("cannot get GITHUB_EVENT_PATH")
}
event, err := os.ReadFile(eventFileName)
if err != nil {
panic(err)
}
must(err)

Check warning on line 39 in internal/actions/actions.go

View check run for this annotation

Codecov / codecov/patch

internal/actions/actions.go#L38-L39

Added lines #L38 - L39 were not covered by tests
var m map[string]any
json.Unmarshal([]byte(event), &m)

Expand All @@ -61,64 +46,24 @@
return m
}

// PullRequestEvent extracts pull request details from the parsed GitHub event data
func PullRequestEvent() map[string]any {
pullRequest, ok := GitHubEvent()["pull_request"].(map[string]any)
if !ok {
panic("cannot parse GITHUB_EVENT_PATH pull_request")
}
return pullRequest
}

// IssueEvent retrieves issue-related information from the GitHub event payload
func IssueEvent() map[string]any {
issue, ok := GitHubEvent()["issue"].(map[string]any)
if !ok {
panic("cannot parse GITHUB_EVENT_PATH pull_request")
// must panics if the error is non-nil, halting execution
func must(err error) {
if err != nil {
panic(err)

Check warning on line 52 in internal/actions/actions.go

View check run for this annotation

Codecov / codecov/patch

internal/actions/actions.go#L50-L52

Added lines #L50 - L52 were not covered by tests
}
return issue
}

// tagRef constructs full Git tag reference string (e.g. "refs/tags/v1.0.0")
func tagRef(tag string) string {
return "refs/tags/" + strings.TrimSpace(tag)
func binaryZip(packageName string) string {
return fmt.Sprintf("%s_%s.zip", packageName, _currentSuffix)

Check warning on line 57 in internal/actions/actions.go

View check run for this annotation

Codecov / codecov/patch

internal/actions/actions.go#L56-L57

Added lines #L56 - L57 were not covered by tests
}

// branchRef generates full Git branch reference string (e.g. "refs/heads/main")
func branchRef(branchName string) string {
return "refs/heads/" + strings.TrimSpace(branchName)
}

// hasTag checks if specified Git tag exists in repository
func hasTag(tag string) bool {
_, err := exec.Command("git", "rev-parse", tagRef(tag)).CombinedOutput()
return err == nil
}

// shaFromTag retrieves commit SHA for given Git tag
// Panics if tag doesn't exist
func shaFromTag(tag string) string {
ret, err := exec.Command("git", "rev-list", "-n", "1", tag).CombinedOutput()
if err != nil {
log.Fatalf("cannot find a tag: %s %s", tag, string(ret))
}
return strings.TrimSpace(string(ret))
}

// parseMappedVersion splits the mapped version string into library name and version.
// Input format: "clib/semver" where semver starts with 'v'
// Panics if input format is invalid or version isn't valid semantic version
func parseMappedVersion(version string) (clib, mappedVersion string) {
arr := strings.Split(version, "/")
if len(arr) != 2 {
panic("invalid mapped version format")
}
clib, mappedVersion = arr[0], arr[1]

if !semver.IsValid(mappedVersion) {
panic("invalid mapped version format: mappedVersion is not a semver")
}
return
func isLegacyBranch(branchName string) bool {
return strings.HasPrefix(branchName, prefix.BranchPrefix)
}

// isValidLLPkg checks if directory contains both llpkg.cfg and llcppg.cfg
Expand All @@ -133,21 +78,39 @@
return hasLLCppg && hasLLPkg
}

// PullRequestEvent extracts pull request details from the parsed GitHub event data
func PullRequestEvent() map[string]any {
pullRequest, ok := GitHubEvent()["pull_request"].(map[string]any)
if !ok {
panic("cannot parse GITHUB_EVENT_PATH pull_request")

Check warning on line 85 in internal/actions/actions.go

View check run for this annotation

Codecov / codecov/patch

internal/actions/actions.go#L82-L85

Added lines #L82 - L85 were not covered by tests
}
return pullRequest

Check warning on line 87 in internal/actions/actions.go

View check run for this annotation

Codecov / codecov/patch

internal/actions/actions.go#L87

Added line #L87 was not covered by tests
}

// IssueEvent retrieves issue-related information from the GitHub event payload
func IssueEvent() map[string]any {
issue, ok := GitHubEvent()["issue"].(map[string]any)
if !ok {
panic("cannot parse GITHUB_EVENT_PATH pull_request")

Check warning on line 94 in internal/actions/actions.go

View check run for this annotation

Codecov / codecov/patch

internal/actions/actions.go#L91-L94

Added lines #L91 - L94 were not covered by tests
}
return issue

Check warning on line 96 in internal/actions/actions.go

View check run for this annotation

Codecov / codecov/patch

internal/actions/actions.go#L96

Added line #L96 was not covered by tests
}

// checkLegacyVersion validates versioning strategy for legacy package submissions
// Ensures semantic versioning compliance and proper branch maintenance strategy
func checkLegacyVersion(ver *versions.Versions, cfg config.LLPkgConfig, mappedVersion string, isLegacy bool) {
func checkLegacyVersion(ver *mappingtable.Versions, cfg config.LLPkgConfig, mappedVersion string, isLegacy bool) {
if slices.Contains(ver.GoVersions(cfg.Upstream.Package.Name), mappedVersion) {
panic("repeat semver")
log.Panicf("repeat semver: %s", mappedVersion)
}
vers := ver.CVersions(cfg.Upstream.Package.Name)
currentVersion := versions.ToSemVer(cfg.Upstream.Package.Version)
currentVersion := version.ToSemVer(cfg.Upstream.Package.Version)

// skip when we're the only latest version or C version doesn't follow semver.
if len(vers) == 0 || !semver.IsValid(currentVersion) {
return
}

sort.Sort(versions.ByVersionDescending(vers))
sort.Sort(version.ByVersionDescending(vers))

latestVersion := vers[0]

Expand Down Expand Up @@ -207,68 +170,3 @@
panic("mapped version should not less than the legacy one.")
}
}

// Setenv writes environment variables to GITHUB_ENV for GitHub Actions consumption
func Setenv(envm map[string]string) {
env, err := os.OpenFile(os.Getenv("GITHUB_ENV"), os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
// should never happen,
// it means current runtime is not Github actions if there's any errors
must(err)

env.WriteString(envToString(envm))

// make sure we write it to the GITHUB_ENV
env.Close()
}

// SetOutput writes workflow outputs to GITHUB_OUTPUT for GitHub Actions
func SetOutput(envm map[string]string) {
env, err := os.OpenFile(os.Getenv("GITHUB_OUTPUT"), os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
must(err)

env.WriteString(envToString(envm))

env.Close()
}

// Changes returns the changed files in current PR,
// which depends on ALL_CHANGED_FILES generated by tj-actions/changed-files action,
// if there's no content in ALL_CHANGED_FILES, it panic.
func Changes() []string {
changes := os.Getenv("ALL_CHANGED_FILES")
if changes == "" {
panic("cannot find changes file!")
}
return strings.Fields(changes)
}

// Repository returns owner and repository name for the current repository
//
// Example: goplus/llpkg, owner: goplus, repo: llpkg
// Repository extracts GitHub repository owner and name from GITHUB_REPOSITORY
func Repository() (owner, repo string) {
thisRepo := os.Getenv("GITHUB_REPOSITORY")
if thisRepo == "" {
panic("no github repo")
}
current := strings.Split(thisRepo, "/")
return current[0], current[1]
}

// Token returns Github Token for current runner
func Token() string {
token := os.Getenv("GITHUB_TOKEN")
if token == "" {
panic("no GITHUB_TOKEN")
}
return token
}

// LatestCommitSHA returns the current commit SHA from GITHUB_SHA environment variable
func LatestCommitSHA() string {
sha := os.Getenv("GITHUB_SHA")
if sha == "" {
panic("no GITHUB_SHA found")
}
return sha
}
Loading