mirror of
https://github.com/go-gitea/gitea.git
synced 2026-07-17 21:15:21 +02:00
1. Storing "ctx" in a long-living object is wrong 2. Make the commit & tree cacheable (for the future performance optimization) 3. Also fix some bad designs like `// FIXME: bad design, this field can be nil if the commit is from "last commit cache"` ref: * #33893
85 lines
2.9 KiB
Go
85 lines
2.9 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package actions
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
git_model "gitea.dev/models/git"
|
|
repo_model "gitea.dev/models/repo"
|
|
actions_module "gitea.dev/modules/actions"
|
|
"gitea.dev/modules/gitrepo"
|
|
"gitea.dev/modules/log"
|
|
|
|
lru "github.com/hashicorp/golang-lru/v2"
|
|
)
|
|
|
|
// cachedScopedWorkflows is one source repo's parsed scoped workflows together with the default-branch SHA they were parsed at.
|
|
type cachedScopedWorkflows struct {
|
|
sha string
|
|
parsed []*actions_module.ParsedScopedWorkflow
|
|
}
|
|
|
|
// scopedWorkflowCache caches each scoped-workflow source repo's parsed workflows, keyed by source repo ID.
|
|
// There is exactly one entry per source: a default-branch update is detected by SHA mismatch and overwrites the entry, so stale parses never accumulate.
|
|
var scopedWorkflowCache *lru.Cache[int64, *cachedScopedWorkflows]
|
|
|
|
const defaultScopedWorkflowCacheSize = 1024
|
|
|
|
func init() {
|
|
c, err := lru.New[int64, *cachedScopedWorkflows](defaultScopedWorkflowCacheSize)
|
|
if err != nil {
|
|
log.Fatal("failed to new scopedWorkflowCache, err: %v", err)
|
|
}
|
|
scopedWorkflowCache = c
|
|
}
|
|
|
|
// LoadParsedScopedWorkflows returns the source repo's parsed scoped workflows at its current default-branch HEAD.
|
|
func LoadParsedScopedWorkflows(ctx context.Context, sourceRepo *repo_model.Repository) (sha string, parsed []*actions_module.ParsedScopedWorkflow, err error) {
|
|
branch, err := git_model.GetBranch(ctx, sourceRepo.ID, sourceRepo.DefaultBranch)
|
|
if err != nil {
|
|
return "", nil, fmt.Errorf("get source default branch: %w", err)
|
|
}
|
|
sha = branch.CommitID
|
|
|
|
if v, ok := scopedWorkflowCache.Get(sourceRepo.ID); ok && v.sha == sha {
|
|
// cache hit at the current default-branch HEAD
|
|
return sha, v.parsed, nil
|
|
}
|
|
|
|
// cache miss: open the source repo at the exact SHA we keyed on
|
|
sourceGitRepo, err := gitrepo.OpenRepository(ctx, sourceRepo)
|
|
if err != nil {
|
|
return "", nil, fmt.Errorf("open source repo: %w", err)
|
|
}
|
|
defer sourceGitRepo.Close()
|
|
|
|
sourceCommit, err := sourceGitRepo.GetCommit(sha)
|
|
if err != nil {
|
|
return "", nil, fmt.Errorf("get source commit %s: %w", sha, err)
|
|
}
|
|
parsed, err = actions_module.ParseScopedWorkflows(ctx, sourceGitRepo, sourceCommit)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
// overwrite this source's single entry (a stale entry from a previous HEAD is replaced, not accumulated)
|
|
scopedWorkflowCache.Add(sourceRepo.ID, &cachedScopedWorkflows{sha: sha, parsed: parsed})
|
|
return sha, parsed, nil
|
|
}
|
|
|
|
// ScopedWorkflowContent returns one scoped workflow's raw content (by entry name) at the source repo's current default-branch HEAD, or nil if no such workflow exists there.
|
|
func ScopedWorkflowContent(ctx context.Context, sourceRepo *repo_model.Repository, entryName string) ([]byte, error) {
|
|
_, parsed, err := LoadParsedScopedWorkflows(ctx, sourceRepo)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, p := range parsed {
|
|
if p.EntryName == entryName {
|
|
return p.Content, nil
|
|
}
|
|
}
|
|
return nil, nil
|
|
}
|