Skip to content

Commit

Permalink
feat: only run tests for changed files
Browse files Browse the repository at this point in the history
  • Loading branch information
Gurkengewuerz committed Oct 25, 2024
1 parent 2269e96 commit 0261231
Showing 1 changed file with 61 additions and 27 deletions.
88 changes: 61 additions & 27 deletions internal/judge/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ package judge

import (
"context"
"errors"
"fmt"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/gurkengewuerz/GitCodeJudge/config"
"github.com/gurkengewuerz/GitCodeJudge/internal/models"
"github.com/gurkengewuerz/GitCodeJudge/internal/models/status"
log "github.com/sirupsen/logrus"
"io/fs"
"os"
"path/filepath"
"strings"
Expand Down Expand Up @@ -64,7 +65,7 @@ func (e *Executor) Execute(submission models.Submission) (*models.TestResult, er
Password: config.CFG.GiteaToken,
},
ReferenceName: plumbing.ReferenceName(submission.BranchName),
Depth: 1,
Depth: 2, // need to get the parent commit
RecurseSubmodules: git.DefaultSubmoduleRecursionDepth,
})
if err != nil {
Expand All @@ -91,41 +92,79 @@ func (e *Executor) Execute(submission models.Submission) (*models.TestResult, er
}
log.WithFields(field).Debug("Worker checked out repository")

testCases := make([]models.TestCase, 0)
ref, err := r.Head()
if err != nil {
return nil, fmt.Errorf("failed to get HEAD: %v", err)
}

err = filepath.WalkDir(repoTmpDir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
// Get the commit object
commit, err := r.CommitObject(ref.Hash())
if err != nil {
return nil, fmt.Errorf("failed to get commit: %v", err)
}

// Skip if it's not a directory
if !d.IsDir() {
return nil
// Get the parent commit to compare changes
parentCommit, err := commit.Parent(0)
if err != nil {
if errors.Is(err, object.ErrParentNotFound) {
// This is the first commit
return &models.TestResult{
Status: status.StatusNone,
}, nil
}
return nil, fmt.Errorf("failed to get parent commit: %v", err)
}

// Calculate relative path
relPath, err := filepath.Rel(repoTmpDir, path)
if err != nil {
return err
// Get changes between commits
patch, err := commit.Patch(parentCommit)
if err != nil {
return nil, fmt.Errorf("failed to get patch: %v", err)
}

changedFiles := make([]string, 0)
for _, filePatch := range patch.FilePatches() {
from, to := filePatch.Files()

// Handle added files
if from == nil && to != nil {
changedFiles = append(changedFiles, to.Path())
continue
}

if strings.Count(relPath, string(os.PathSeparator)) > 2 {
return fs.SkipDir
/*
// Handle deleted files
if from != nil && to == nil {
changedFiles = append(changedFiles, from.Path())
continue
}
*/

// Handle modified files
if from != nil && to != nil {
changedFiles = append(changedFiles, to.Path())
}
}

log.WithFields(field).WithField("ChangedFiles", changedFiles).Debug("files in latest commit")

testCases := make([]models.TestCase, 0)

for _, file := range changedFiles {
path := filepath.Dir(file)

// Get test cases for the task
newTestCases, err := LoadTestCases(filepath.Join(e.testCaseDir, relPath))
newTestCases, err := LoadTestCases(filepath.Join(e.testCaseDir, path))

if err == nil {
log.WithFields(field).WithFields(log.Fields{
"Path": relPath,
"Path": path,
"TestCases": len(newTestCases),
}).WithError(err).Debug("Loaded test cases")

for i := range newTestCases {
parts := strings.Split(relPath, string(os.PathSeparator))
parts := strings.Split(path, string(os.PathSeparator))
if len(parts) != 2 {
return nil
continue
}

newTestCases[i].Solution = &models.Solution{
Expand All @@ -142,14 +181,9 @@ func (e *Executor) Execute(submission models.Submission) (*models.TestResult, er
"Path": path,
}).WithError(err).Debug("Failed to load test cases")
}

return nil
})
if err != nil {
log.WithFields(field).WithError(err).Debug("WalkDir returned errors")
}

log.WithFields(field).Debugf("Found %d test cases", len(testCases))
log.WithFields(field).WithField("ChangedFiles", changedFiles).Debugf("Found %d test cases in %d changed files", len(testCases), len(changedFiles))

result := &models.TestResult{
TestCases: make([]models.TestCaseResult, len(testCases)),
Expand All @@ -161,7 +195,7 @@ func (e *Executor) Execute(submission models.Submission) (*models.TestResult, er
"Workshop": tc.Solution.Workshop,
"Task": tc.Solution.Task,
}
log.WithFields(field).Debug("Executing")
log.WithFields(field).Info("Executing test case")

execResult, err := e.docker.RunCode(context.Background(), tc)
if err != nil {
Expand Down

0 comments on commit 0261231

Please sign in to comment.