Jaypore CI

> Jaypore CI: Minimal, Offline, Local CI system.
Log | Files | Refs | README

cron_types.go (1992B)


      1 package jci
      2 
      3 import (
      4 	"crypto/sha1"
      5 	"encoding/hex"
      6 	"fmt"
      7 	"path/filepath"
      8 	"strings"
      9 )
     10 
     11 type CronJobType string
     12 
     13 const (
     14 	CronJobGitJCI CronJobType = "git-jci"
     15 	CronJobBinary CronJobType = "binary"
     16 	CronJobShell  CronJobType = "shell"
     17 )
     18 
     19 type CronJob struct {
     20 	ID         string
     21 	Schedule   string
     22 	Command    string
     23 	Type       CronJobType
     24 	BinaryPath string
     25 	BinaryArgs string
     26 	Line       int
     27 	CronLog    string
     28 }
     29 
     30 func classifyCronCommand(command string, repoRoot string) (CronJobType, string, string) {
     31 	trimmed := strings.TrimSpace(command)
     32 	if trimmed == "" {
     33 		return CronJobShell, "", ""
     34 	}
     35 
     36 	if strings.HasPrefix(trimmed, "git jci") {
     37 		return CronJobGitJCI, "", ""
     38 	}
     39 
     40 	head, tail := splitCommandHeadTail(trimmed)
     41 	cleaned := strings.TrimPrefix(head, "./")
     42 	if strings.HasPrefix(cleaned, ".jci/") {
     43 		abs := filepath.Join(repoRoot, cleaned)
     44 		return CronJobBinary, abs, tail
     45 	}
     46 
     47 	if !strings.Contains(head, "/") {
     48 		candidate := filepath.Join(repoRoot, ".jci", head)
     49 		return CronJobBinary, candidate, tail
     50 	}
     51 
     52 	return CronJobShell, trimmed, tail
     53 }
     54 
     55 func cronJobID(schedule, command string) string {
     56 	sum := sha1.Sum([]byte(schedule + "\x00" + command))
     57 	return hex.EncodeToString(sum[:])
     58 }
     59 
     60 func (job CronJob) shellCommand(repoRoot string) string {
     61 	var command string
     62 	switch job.Type {
     63 	case CronJobBinary:
     64 		command = shellEscape(job.BinaryPath)
     65 		if job.BinaryArgs != "" {
     66 			command += " " + job.BinaryArgs
     67 		}
     68 	default:
     69 		command = job.Command
     70 	}
     71 
     72 	full := fmt.Sprintf("cd %s && %s", shellEscape(repoRoot), command)
     73 	if job.CronLog != "" {
     74 		full = fmt.Sprintf("%s >> %s 2>&1", full, shellEscape(job.CronLog))
     75 	}
     76 	return full
     77 }
     78 
     79 func shellEscape(value string) string {
     80 	if value == "" {
     81 		return "''"
     82 	}
     83 	return "'" + strings.ReplaceAll(value, "'", "'\\''") + "'"
     84 }
     85 
     86 func splitCommandHeadTail(cmd string) (string, string) {
     87 	parts := strings.Fields(cmd)
     88 	if len(parts) == 0 {
     89 		return "", ""
     90 	}
     91 	head := parts[0]
     92 	tail := strings.Join(parts[1:], " ")
     93 	return head, tail
     94 }