Merge pull request #10769 from cli/babakks/fix-job-log-resolution

Fix job log resolution to skip legacy logs in favour of normal/new ones
This commit is contained in:
William Martin 2025-04-11 16:16:39 +02:00 committed by GitHub
commit 408e21ebdd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 42 additions and 17 deletions

View file

@ -555,15 +555,25 @@ func getJobNameForLogFilename(name string) string {
return sanitizedJobName
}
// A job run log file is a top-level .txt file whose name starts with an ordinal
// number; e.g., "0_jobname.txt".
func jobLogFilenameRegexp(job shared.Job) *regexp.Regexp {
sanitizedJobName := getJobNameForLogFilename(job.Name)
re := fmt.Sprintf(`^-?\d+_%s\.txt`, regexp.QuoteMeta(sanitizedJobName))
re := fmt.Sprintf(`^\d+_%s\.txt$`, regexp.QuoteMeta(sanitizedJobName))
return regexp.MustCompile(re)
}
// A legacy job run log file is a top-level .txt file whose name starts with a
// negative number which is the ID of the run; e.g., "-2147483648_jobname.txt".
func legacyJobLogFilenameRegexp(job shared.Job) *regexp.Regexp {
sanitizedJobName := getJobNameForLogFilename(job.Name)
re := fmt.Sprintf(`^-\d+_%s\.txt$`, regexp.QuoteMeta(sanitizedJobName))
return regexp.MustCompile(re)
}
func stepLogFilenameRegexp(job shared.Job, step shared.Step) *regexp.Regexp {
sanitizedJobName := getJobNameForLogFilename(job.Name)
re := fmt.Sprintf(`^%s\/%d_.*\.txt`, regexp.QuoteMeta(sanitizedJobName), step.Number)
re := fmt.Sprintf(`^%s\/%d_.*\.txt$`, regexp.QuoteMeta(sanitizedJobName), step.Number)
return regexp.MustCompile(re)
}
@ -662,26 +672,31 @@ func truncateAsUTF16(str string, max int) string {
// where the ID can apparently be negative.
func attachRunLog(rlz *zip.Reader, jobs []shared.Job) {
for i, job := range jobs {
re := jobLogFilenameRegexp(job)
for _, file := range rlz.File {
if re.MatchString(file.Name) {
jobs[i].Log = file
break
}
// As a highest priority, we try to use the step logs first. We have seen zips that surprisingly contain
// step logs, normal job logs and legacy job logs. In this case, both job logs would be ignored. We have
// never seen a zip containing both job logs and no step logs, however, it may be possible. In that case
// let's prioritise the normal log over the legacy one.
jobLog := matchFileInZIPArchive(rlz, jobLogFilenameRegexp(job))
if jobLog == nil {
jobLog = matchFileInZIPArchive(rlz, legacyJobLogFilenameRegexp(job))
}
jobs[i].Log = jobLog
for j, step := range job.Steps {
re := stepLogFilenameRegexp(job, step)
for _, file := range rlz.File {
if re.MatchString(file.Name) {
jobs[i].Steps[j].Log = file
break
}
}
jobs[i].Steps[j].Log = matchFileInZIPArchive(rlz, stepLogFilenameRegexp(job, step))
}
}
}
func matchFileInZIPArchive(zr *zip.Reader, re *regexp.Regexp) *zip.File {
for _, file := range zr.File {
if re.MatchString(file.Name) {
return file
}
}
return nil
}
func displayRunLog(w io.Writer, jobs []shared.Job, failed bool) error {
for _, job := range jobs {
// To display a run log, we first try to compile it from individual step

View file

@ -2039,8 +2039,9 @@ func TestViewRun(t *testing.T) {
// ├── 2_cool job with no step logs.txt
// ├── 3_sad job with no step logs.txt
// ├── -9999999999_legacy cool job with no step logs.txt
// └── -9999999999_legacy sad job with no step logs.txt
// ├── -9999999999_legacy sad job with no step logs.txt
// ├── 4_cool job with both legacy and new logs.txt
// └── -9999999999_cool job with both legacy and new logs.txt
func Test_attachRunLog(t *testing.T) {
tests := []struct {
name string
@ -2149,6 +2150,15 @@ func Test_attachRunLog(t *testing.T) {
wantJobFilename: "-9999999999_legacy cool job with no step logs.txt",
wantStepMatch: false,
},
{
name: "matching job name with both normal and legacy filename",
job: shared.Job{
Name: "cool job with both legacy and new logs",
},
wantJobMatch: true,
wantJobFilename: "4_cool job with both legacy and new logs.txt",
wantStepMatch: false,
},
{
name: "one job name is a suffix of another",
job: shared.Job{