Some checks failed
Go / build (.exe, 386, windows, windows-386) (push) Has been cancelled
Go / build (.exe, amd64, windows, windows-amd64) (push) Has been cancelled
Go / build (.exe, arm64, windows, windows-arm64) (push) Has been cancelled
Go / build (386, freebsd, freebsd-386) (push) Has been cancelled
Go / build (386, linux, linux-386) (push) Has been cancelled
Go / build (386, netbsd, netbsd-386) (push) Has been cancelled
Go / build (386, openbsd, openbsd-386) (push) Has been cancelled
Go / build (386, plan9, plan9-386) (push) Has been cancelled
Go / build (amd64, darwin, darwin-amd64) (push) Has been cancelled
Go / build (amd64, dragonfly, dragonfly-amd64) (push) Has been cancelled
Go / build (amd64, freebsd, freebsd-amd64) (push) Has been cancelled
Go / build (amd64, illumos, illumos-amd64) (push) Has been cancelled
Go / build (amd64, linux, linux-amd64) (push) Has been cancelled
Go / build (amd64, netbsd, netbsd-amd64) (push) Has been cancelled
Go / build (amd64, openbsd, openbsd-amd64) (push) Has been cancelled
Go / build (amd64, plan9, plan9-amd64) (push) Has been cancelled
Go / build (amd64, solaris, solaris-amd64) (push) Has been cancelled
Go / build (arm, 6, linux, linux-armv6) (push) Has been cancelled
Go / build (arm, 7, linux, linux-armv7) (push) Has been cancelled
Go / build (arm, freebsd, freebsd-arm) (push) Has been cancelled
Go / build (arm, netbsd, netbsd-arm) (push) Has been cancelled
Go / build (arm, openbsd, openbsd-arm) (push) Has been cancelled
Go / build (arm, plan9, plan9-arm) (push) Has been cancelled
Go / build (arm64, darwin, darwin-arm64) (push) Has been cancelled
Go / build (arm64, freebsd, freebsd-arm64) (push) Has been cancelled
Go / build (arm64, linux, linux-arm64) (push) Has been cancelled
Go / build (arm64, netbsd, netbsd-arm64) (push) Has been cancelled
Go / build (arm64, openbsd, openbsd-arm64) (push) Has been cancelled
Go / build (loong64, linux, linux-loong64) (push) Has been cancelled
Go / build (mips, linux, linux-mips) (push) Has been cancelled
Go / build (mips64, linux, linux-mips64) (push) Has been cancelled
Go / build (mips64le, linux, linux-mips64le) (push) Has been cancelled
Go / build (mipsle, linux, linux-mipsle) (push) Has been cancelled
Go / build (ppc64, aix, aix-ppc64) (push) Has been cancelled
Go / build (ppc64, linux, linux-ppc64) (push) Has been cancelled
Go / build (ppc64, openbsd, openbsd-ppc64) (push) Has been cancelled
Go / build (ppc64le, linux, linux-ppc64le) (push) Has been cancelled
Go / build (riscv64, freebsd, freebsd-riscv64) (push) Has been cancelled
Go / build (riscv64, linux, linux-riscv64) (push) Has been cancelled
Go / build (riscv64, openbsd, openbsd-riscv64) (push) Has been cancelled
Go / build (s390x, linux, linux-s390x) (push) Has been cancelled
Go / merge-artifacts (push) Has been cancelled
Docker Image / docker (push) Has been cancelled
130 lines
3.6 KiB
Go
130 lines
3.6 KiB
Go
package pluginmanager
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
)
|
|
|
|
func (m *Manager) GCCandidates(ctx context.Context) ([]GCCandidate, error) {
|
|
refs, err := m.repo.ReferencedArtifactIDs(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
artifacts, err := m.repo.ListArtifacts(ctx, "")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var candidates []GCCandidate
|
|
for _, artifact := range artifacts {
|
|
referenced := refs[artifact.ID]
|
|
artifactPath := artifactGCPath(artifact)
|
|
size := artifact.SizeBytes
|
|
if info, err := os.Stat(artifactPath); err == nil && info.IsDir() {
|
|
size = dirSize(artifactPath)
|
|
} else if err == nil {
|
|
size = info.Size()
|
|
}
|
|
candidate := GCCandidate{
|
|
Kind: "artifact",
|
|
ID: artifact.ID,
|
|
PluginID: artifact.PluginID,
|
|
Path: artifactPath,
|
|
Protected: referenced,
|
|
SizeBytes: size,
|
|
CreatedAt: artifact.CreatedAt,
|
|
Referenced: referenced,
|
|
}
|
|
switch {
|
|
case referenced:
|
|
candidate.Reason = "referenced by active/desired/snapshot/build"
|
|
case artifact.ArtifactType == ArtifactTypeSource:
|
|
candidate.Reason = "unreferenced source package"
|
|
case artifact.Status == ArtifactStatusRejected || artifact.Status == ArtifactStatusDeleted:
|
|
candidate.Reason = "unreferenced rejected/deleted artifact"
|
|
default:
|
|
candidate.Reason = "unreferenced artifact"
|
|
}
|
|
if !referenced && (artifact.ArtifactType == ArtifactTypeSource || artifact.Status == ArtifactStatusRejected || artifact.Status == ArtifactStatusDeleted) {
|
|
candidates = append(candidates, candidate)
|
|
}
|
|
}
|
|
builds, err := m.repo.ListBuilds(ctx, "")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, build := range builds {
|
|
protectedBuild := build.Status == BuildStatusRunning || build.Status == BuildStatusQueued
|
|
reason := "completed build log"
|
|
if protectedBuild {
|
|
reason = "in-flight build"
|
|
}
|
|
candidates = append(candidates, GCCandidate{
|
|
Kind: "build_log",
|
|
ID: buildIDString(build.ID),
|
|
PluginID: build.PluginID,
|
|
Protected: protectedBuild,
|
|
Reason: reason,
|
|
SizeBytes: int64(len(build.LogSummary)),
|
|
CreatedAt: build.CreatedAt,
|
|
})
|
|
}
|
|
return candidates, nil
|
|
}
|
|
|
|
func (m *Manager) RunGC(ctx context.Context, actor string, dryRun bool) ([]GCCandidate, error) {
|
|
candidates, err := m.GCCandidates(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if dryRun {
|
|
_ = m.repo.RecordOperation(ctx, "", "", "artifact_gc", "dry_run", actor, "artifact gc dry-run completed", map[string]any{
|
|
"candidates": len(candidates),
|
|
})
|
|
return candidates, nil
|
|
}
|
|
var removed []GCCandidate
|
|
for _, candidate := range candidates {
|
|
if candidate.Protected || candidate.Path == "" || candidate.Kind != "artifact" {
|
|
continue
|
|
}
|
|
if err := os.RemoveAll(candidate.Path); err != nil {
|
|
_ = m.repo.RecordOperation(ctx, candidate.PluginID, candidate.ID, "artifact_gc", "failed", actor, err.Error(), map[string]any{
|
|
"path": candidate.Path,
|
|
})
|
|
continue
|
|
}
|
|
removed = append(removed, candidate)
|
|
}
|
|
_ = m.repo.RecordOperation(ctx, "", "", "artifact_gc", "succeeded", actor, "artifact gc completed", map[string]any{
|
|
"removed": len(removed),
|
|
})
|
|
return removed, nil
|
|
}
|
|
|
|
func artifactGCPath(artifact ArtifactRecord) string {
|
|
if artifact.FilePath == "" {
|
|
return ""
|
|
}
|
|
return filepath.Dir(artifact.FilePath)
|
|
}
|
|
|
|
func dirSize(root string) int64 {
|
|
var total int64
|
|
_ = filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error {
|
|
if err != nil || d.IsDir() {
|
|
return nil
|
|
}
|
|
if info, err := d.Info(); err == nil {
|
|
total += info.Size()
|
|
}
|
|
return nil
|
|
})
|
|
return total
|
|
}
|
|
|
|
func buildIDString(id int64) string {
|
|
return strconv.FormatInt(id, 10)
|
|
}
|