diff options
author | Roman Smrž <roman.smrz@seznam.cz> | 2025-05-18 10:35:24 +0200 |
---|---|---|
committer | Roman Smrž <roman.smrz@seznam.cz> | 2025-05-20 22:03:55 +0200 |
commit | aa9926074264d63aa6ceb2f3dd81e1fb9f9d0d29 (patch) | |
tree | e4d2b06e65fb11081fbc61787d05572cc904bc71 | |
parent | 4ac26772681d74be2cbbf9376a02ebc395257c86 (diff) |
Reflect dependencies in job id
-rw-r--r-- | src/Eval.hs | 25 | ||||
-rw-r--r-- | test/asset/run/external.yaml | 42 | ||||
-rw-r--r-- | test/script/run.et | 64 |
3 files changed, 123 insertions, 8 deletions
diff --git a/src/Eval.hs b/src/Eval.hs index 013c074..05381dd 100644 --- a/src/Eval.hs +++ b/src/Eval.hs @@ -58,22 +58,30 @@ isDefaultRepoMissingInId djob matches (JobIdCommit rname _) = isNothing rname matches (JobIdTree rname _ _) = isNothing rname -collectOtherRepos :: DeclaredJob -> Eval [ (( Maybe RepoName, Maybe Text ), FilePath ) ] -collectOtherRepos decl = do +collectOtherRepos :: DeclaredJobSet -> DeclaredJob -> Eval [ (( Maybe RepoName, Maybe Text ), FilePath ) ] +collectOtherRepos dset decl = do + let dependencies = map fst $ jobUses decl + dependencyRepos <- forM dependencies $ \name -> do + jobs <- either (throwError . OtherEvalError . T.pack) return $ jobsetJobsEither dset + job <- maybe (throwError $ OtherEvalError $ "job ‘" <> textJobName name <> "’ not found") return . find ((name ==) . jobName) $ jobs + return $ jobOtherCheckout job + missingDefault <- isDefaultRepoMissingInId decl + let checkouts = concat [ if missingDefault then map (( Nothing, Nothing ), ) $ jobContainingCheckout decl else [] , map (first (first Just)) $ jobOtherCheckout decl + , map (first (first Just)) $ concat dependencyRepos ] let commonSubdir reporev = joinPath $ foldr1 commonPrefix $ map (maybe [] splitDirectories . jcSubtree . snd) . filter ((reporev ==) . fst) $ checkouts return $ map (\r -> ( r, commonSubdir r )) . nub . map fst $ checkouts -evalJob :: [ ( Maybe RepoName, Tree ) ] -> DeclaredJob -> Eval Job -evalJob revisionOverrides decl = do +evalJob :: [ ( Maybe RepoName, Tree ) ] -> DeclaredJobSet -> DeclaredJob -> Eval Job +evalJob revisionOverrides dset decl = do EvalInput {..} <- ask - otherRepos <- collectOtherRepos decl + otherRepos <- collectOtherRepos dset decl otherRepoTrees <- forM otherRepos $ \(( mbname, mbrev ), commonPath ) -> do ( mbname, ) . ( commonPath, ) <$> case lookup mbname revisionOverrides of Just tree -> return tree @@ -101,7 +109,7 @@ evalJob revisionOverrides decl = do evalJobSet :: [ ( Maybe RepoName, Tree ) ] -> DeclaredJobSet -> Eval JobSet evalJobSet revisionOverrides decl = do - jobs <- either (return . Left) (handleToEither . mapM (evalJob revisionOverrides)) $ jobsetJobsEither decl + jobs <- either (return . Left) (handleToEither . mapM (evalJob revisionOverrides decl)) $ jobsetJobsEither decl return JobSet { jobsetCommit = jobsetCommit decl , jobsetJobsEither = jobs @@ -121,9 +129,10 @@ evalRepo (Just name) = asks (lookup name . eiOtherRepos) >>= \case canonicalJobName :: [ Text ] -> Config -> Eval JobId canonicalJobName (r : rs) config = do let name = JobName r + dset = JobSet Nothing $ Right $ configJobs config case find ((name ==) . jobName) (configJobs config) of Just djob -> do - otherRepos <- collectOtherRepos djob + otherRepos <- collectOtherRepos dset djob ( overrides, rs' ) <- (\f -> foldM f ( [], rs ) otherRepos) $ \( overrides, crs ) (( mbname, _ ), path ) -> do ( tree, crs' ) <- readTreeFromIdRef crs path =<< evalRepo mbname @@ -131,7 +140,7 @@ canonicalJobName (r : rs) config = do case rs' of (r' : _) -> throwError $ OtherEvalError $ "unexpected job ref part ‘" <> r' <> "’" _ -> return () - jobId <$> evalJob overrides djob + jobId <$> evalJob overrides dset djob Nothing -> throwError $ OtherEvalError $ "job ‘" <> r <> "’ not found" canonicalJobName [] _ = throwError $ OtherEvalError "expected job name" diff --git a/test/asset/run/external.yaml b/test/asset/run/external.yaml new file mode 100644 index 0000000..f1d2b2c --- /dev/null +++ b/test/asset/run/external.yaml @@ -0,0 +1,42 @@ +repo first: + path: ../first + +repo second: + path: ../second + + +job single: + checkout: + repo: first + dest: first + + shell: + - tar czf first.tar.gz first + + artifact tarball: + path: ./first.tar.gz + +job multiple: + checkout: + - repo: first + dest: first-subdir + subtree: subdir + - repo: second + dest: second-subdir + subtree: sub + + shell: + - tar czf pack.tar.gz first-subdir second-subdir + + artifact tarball: + path: ./pack.tar.gz + +job combine: + checkout: null + + shell: + - ls + + uses: + - single.tarball + - multiple.tarball diff --git a/test/script/run.et b/test/script/run.et index 4f4e016..9efc0e7 100644 --- a/test/script/run.et +++ b/test/script/run.et @@ -10,6 +10,9 @@ def expect_result from p of job result result: /job-finish $job ([a-z]+)/ capture done guard (done == result) +def expect_success from p of job: + expect_result from p of job result "done" + test RunWithouRepo: node n @@ -71,3 +74,64 @@ test RunWithRepo: expect /(.*)/ from p capture done guard (done == "run-finish") + + +test RunExternalRepo: + node n + shell on n as git_init: + mkdir -p first/subdir + git -C first -c init.defaultBranch=master init -q + git -C first -c user.name=test -c user.email=test commit -q --allow-empty -m 'initial commit' + touch first/subdir/file + git -C first add subdir + git -C first -c user.name=test -c user.email=test commit -q -m 'commit' + git -C first rev-parse HEAD^{tree} + git -C first rev-parse HEAD:subdir + + mkdir -p second/sub + git -C second -c init.defaultBranch=master init -q + git -C second -c user.name=test -c user.email=test commit -q --allow-empty -m 'initial commit' + touch second/sub/other + git -C second add sub + git -C second -c user.name=test -c user.email=test commit -q -m 'commit' + git -C second rev-parse HEAD^{tree} + git -C second rev-parse HEAD:sub + + mkdir -p main + git -C main -c init.defaultBranch=master init -q + git -C main -c user.name=test -c user.email=test commit -q --allow-empty -m 'initial commit' + cp "${scripts.path}/external.yaml" main/minici.yaml + git -C main add minici.yaml + git -C main -c user.name=test -c user.email=test commit -q -m 'commit' + git -C main rev-parse HEAD^{tree} + + expect /([0-9a-f]+)/ from git_init capture first_root + expect /([0-9a-f]+)/ from git_init capture first_subtree + expect /([0-9a-f]+)/ from git_init capture second_root + expect /([0-9a-f]+)/ from git_init capture second_subtree + expect /([0-9a-f]+)/ from git_init capture main_root + + # Explicit jobfile outside of any git repo + local: + spawn on n as p args [ "--repo=first:./first", "--repo=second:./second", "${scripts.path}/external.yaml", "run", "single", "multiple", "combine" ] + for job in [ "single.$first_root", "multiple.$first_subtree.$second_subtree", "combine.$first_root.$second_subtree" ]: + expect_success from p of job + + expect /(.*)/ from p capture done + guard (done == "run-finish") + + # Explicit jobfile within a git repo + local: + spawn on n as p args [ "--repo=first:./first", "--repo=second:./second", "${scripts.path}/external.yaml", "run", "single" ] + expect_success from p of "single.$first_root" + expect /(.*)/ from p capture done + guard (done == "run-finish") + + # Implicit jobfile within a git repo + local: + spawn on n as p args [ "--repo=first:./first", "--repo=second:./second", "./main", "run", "HEAD^..HEAD" ] + for job in [ "single.$first_root", "multiple.$first_subtree.$second_subtree", "combine.$first_root.$second_subtree" ]: + expect_success from p of "$main_root.$job" + + expect /(.*)/ from p capture done + guard (done == "run-finish") |