packages feed

hercules-ci-agent 0.10.7 → 0.10.8

raw patch · 20 files changed

+509/−230 lines, 20 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Hercules.Agent.NixFile.CiNixArgs: instance GHC.Generics.Generic Hercules.Agent.NixFile.CiNixArgs.CiNixArgs
- Hercules.Agent.NixFile.GitSource: instance GHC.Generics.Generic Hercules.Agent.NixFile.GitSource.GitSource
- Hercules.Agent.NixFile.GitSource: instance GHC.Show.Show Hercules.Agent.NixFile.GitSource.GitSource
- Hercules.Agent.NixFile.HerculesCIArgs: instance GHC.Generics.Generic Hercules.Agent.NixFile.HerculesCIArgs.CISystems
- Hercules.Agent.NixFile.HerculesCIArgs: instance GHC.Generics.Generic Hercules.Agent.NixFile.HerculesCIArgs.HerculesCIArgs
- Hercules.Agent.NixFile.HerculesCIArgs: instance GHC.Generics.Generic Hercules.Agent.NixFile.HerculesCIArgs.HerculesCIMeta
- Hercules.Agent.Producer: instance GHC.Base.Functor (Hercules.Agent.Producer.Msg p)
- Hercules.Agent.Producer: instance GHC.Base.Functor (Hercules.Agent.Producer.Producer p)
- Hercules.Agent.Producer: instance GHC.Exception.Type.Exception Hercules.Agent.Producer.ProducerCancelled
- Hercules.Agent.Producer: instance GHC.Show.Show Hercules.Agent.Producer.ProducerCancelled
- Hercules.Agent.Socket: instance GHC.Exception.Type.Exception Hercules.Agent.Socket.HandshakeTimeout
- Hercules.Agent.Socket: instance GHC.Show.Show Hercules.Agent.Socket.HandshakeTimeout
- Hercules.Agent.WorkerProcess: instance GHC.Exception.Type.Exception Hercules.Agent.WorkerProcess.WorkerException
- Hercules.Agent.WorkerProcess: instance GHC.Show.Show Hercules.Agent.WorkerProcess.WorkerException
- Hercules.Agent.WorkerProtocol.Command: instance GHC.Generics.Generic Hercules.Agent.WorkerProtocol.Command.Command
- Hercules.Agent.WorkerProtocol.Command: instance GHC.Show.Show Hercules.Agent.WorkerProtocol.Command.Command
- Hercules.Agent.WorkerProtocol.Command.Build: instance GHC.Generics.Generic Hercules.Agent.WorkerProtocol.Command.Build.Build
- Hercules.Agent.WorkerProtocol.Command.Build: instance GHC.Show.Show Hercules.Agent.WorkerProtocol.Command.Build.Build
- Hercules.Agent.WorkerProtocol.Command.BuildResult: instance GHC.Generics.Generic Hercules.Agent.WorkerProtocol.Command.BuildResult.BuildResult
- Hercules.Agent.WorkerProtocol.Command.BuildResult: instance GHC.Generics.Generic Hercules.Agent.WorkerProtocol.Command.BuildResult.BuildStatus
- Hercules.Agent.WorkerProtocol.Command.BuildResult: instance GHC.Show.Show Hercules.Agent.WorkerProtocol.Command.BuildResult.BuildResult
- Hercules.Agent.WorkerProtocol.Command.BuildResult: instance GHC.Show.Show Hercules.Agent.WorkerProtocol.Command.BuildResult.BuildStatus
- Hercules.Agent.WorkerProtocol.Command.Effect: instance GHC.Generics.Generic Hercules.Agent.WorkerProtocol.Command.Effect.Effect
- Hercules.Agent.WorkerProtocol.Command.Effect: instance GHC.Show.Show Hercules.Agent.WorkerProtocol.Command.Effect.Effect
- Hercules.Agent.WorkerProtocol.Command.Eval: instance GHC.Generics.Generic Hercules.Agent.WorkerProtocol.Command.Eval.Eval
- Hercules.Agent.WorkerProtocol.Command.Eval: instance GHC.Show.Show Hercules.Agent.WorkerProtocol.Command.Eval.Eval
- Hercules.Agent.WorkerProtocol.Event: instance GHC.Generics.Generic Hercules.Agent.WorkerProtocol.Event.Event
- Hercules.Agent.WorkerProtocol.Event: instance GHC.Show.Show Hercules.Agent.WorkerProtocol.Event.Event
- Hercules.Agent.WorkerProtocol.Event.Attribute: instance GHC.Generics.Generic Hercules.Agent.WorkerProtocol.Event.Attribute.Attribute
- Hercules.Agent.WorkerProtocol.Event.Attribute: instance GHC.Generics.Generic Hercules.Agent.WorkerProtocol.Event.Attribute.AttributeType
- Hercules.Agent.WorkerProtocol.Event.Attribute: instance GHC.Show.Show Hercules.Agent.WorkerProtocol.Event.Attribute.Attribute
- Hercules.Agent.WorkerProtocol.Event.Attribute: instance GHC.Show.Show Hercules.Agent.WorkerProtocol.Event.Attribute.AttributeType
- Hercules.Agent.WorkerProtocol.Event.AttributeError: instance GHC.Generics.Generic Hercules.Agent.WorkerProtocol.Event.AttributeError.AttributeError
- Hercules.Agent.WorkerProtocol.Event.AttributeError: instance GHC.Show.Show Hercules.Agent.WorkerProtocol.Event.AttributeError.AttributeError
- Hercules.Agent.WorkerProtocol.Event.AttributeIFD: instance GHC.Generics.Generic Hercules.Agent.WorkerProtocol.Event.AttributeIFD.AttributeIFD
- Hercules.Agent.WorkerProtocol.Event.AttributeIFD: instance GHC.Show.Show Hercules.Agent.WorkerProtocol.Event.AttributeIFD.AttributeIFD
- Hercules.Agent.WorkerProtocol.Event.BuildResult: instance GHC.Generics.Generic Hercules.Agent.WorkerProtocol.Event.BuildResult.BuildResult
- Hercules.Agent.WorkerProtocol.Event.BuildResult: instance GHC.Show.Show Hercules.Agent.WorkerProtocol.Event.BuildResult.BuildResult
- Hercules.Agent.WorkerProtocol.OutputInfo: instance GHC.Generics.Generic Hercules.Agent.WorkerProtocol.OutputInfo.OutputInfo
- Hercules.Agent.WorkerProtocol.OutputInfo: instance GHC.Show.Show Hercules.Agent.WorkerProtocol.OutputInfo.OutputInfo
- Hercules.Agent.WorkerProtocol.ViaJSON: instance GHC.Read.Read a => GHC.Read.Read (Hercules.Agent.WorkerProtocol.ViaJSON.ViaJSON a)
- Hercules.Agent.WorkerProtocol.ViaJSON: instance GHC.Show.Show a => GHC.Show.Show (Hercules.Agent.WorkerProtocol.ViaJSON.ViaJSON a)
- Hercules.Agent.WorkerProtocol.WorkerConfig: instance GHC.Generics.Generic Hercules.Agent.WorkerProtocol.WorkerConfig.WorkerConfig
- Hercules.Agent.WorkerProtocol.WorkerConfig: instance GHC.Generics.Generic a => GHC.Generics.Generic (Hercules.Agent.WorkerProtocol.WorkerConfig.ViaShowRead a)
- Hercules.Agent.WorkerProtocol.WorkerConfig: instance GHC.Read.Read a => Data.Aeson.Types.FromJSON.FromJSON (Hercules.Agent.WorkerProtocol.WorkerConfig.ViaShowRead a)
- Hercules.Agent.WorkerProtocol.WorkerConfig: instance GHC.Read.Read a => GHC.Read.Read (Hercules.Agent.WorkerProtocol.WorkerConfig.ViaShowRead a)
- Hercules.Agent.WorkerProtocol.WorkerConfig: instance GHC.Show.Show Hercules.Agent.WorkerProtocol.WorkerConfig.WorkerConfig
- Hercules.Agent.WorkerProtocol.WorkerConfig: instance GHC.Show.Show a => Data.Aeson.Types.ToJSON.ToJSON (Hercules.Agent.WorkerProtocol.WorkerConfig.ViaShowRead a)
- Hercules.Agent.WorkerProtocol.WorkerConfig: instance GHC.Show.Show a => GHC.Show.Show (Hercules.Agent.WorkerProtocol.WorkerConfig.ViaShowRead a)
- Hercules.Secrets: instance GHC.Base.Monoid w => Hercules.Secrets.MonadMiniWriter w ((,) w)
- Hercules.Secrets: instance GHC.Generics.Generic Hercules.Secrets.SecretContext
- Hercules.Secrets: instance GHC.Show.Show Hercules.Secrets.SecretContext
- Hercules.UserException: instance GHC.Exception.Type.Exception Hercules.UserException.UserException
- Hercules.UserException: instance GHC.Show.Show Hercules.UserException.UserException
+ Hercules.Agent.NixFile: resolveAndInvokeOutputs :: forall m (a :: [Attr]). (MonadEval m, (a . "outputs") ~ OutputsFunction, (a ? "extraInputs") ~ ExtraInputsSchema) => PSObject (Attrs a) -> (Map ByteString InputDeclaration -> m (Value NixAttrs)) -> m (PSObject OutputsSchema)
+ Hercules.Agent.NixFile.CiNixArgs: instance GHC.Internal.Generics.Generic Hercules.Agent.NixFile.CiNixArgs.CiNixArgs
+ Hercules.Agent.NixFile.GitSource: instance GHC.Internal.Generics.Generic Hercules.Agent.NixFile.GitSource.GitSource
+ Hercules.Agent.NixFile.GitSource: instance GHC.Internal.Show.Show Hercules.Agent.NixFile.GitSource.GitSource
+ Hercules.Agent.NixFile.HerculesCIArgs: instance GHC.Internal.Generics.Generic Hercules.Agent.NixFile.HerculesCIArgs.CISystems
+ Hercules.Agent.NixFile.HerculesCIArgs: instance GHC.Internal.Generics.Generic Hercules.Agent.NixFile.HerculesCIArgs.HerculesCIArgs
+ Hercules.Agent.NixFile.HerculesCIArgs: instance GHC.Internal.Generics.Generic Hercules.Agent.NixFile.HerculesCIArgs.HerculesCIMeta
+ Hercules.Agent.Producer: instance GHC.Internal.Base.Functor (Hercules.Agent.Producer.Msg p)
+ Hercules.Agent.Producer: instance GHC.Internal.Base.Functor (Hercules.Agent.Producer.Producer p)
+ Hercules.Agent.Producer: instance GHC.Internal.Exception.Type.Exception Hercules.Agent.Producer.ProducerCancelled
+ Hercules.Agent.Producer: instance GHC.Internal.Show.Show Hercules.Agent.Producer.ProducerCancelled
+ Hercules.Agent.Socket: instance GHC.Internal.Exception.Type.Exception Hercules.Agent.Socket.HandshakeTimeout
+ Hercules.Agent.Socket: instance GHC.Internal.Show.Show Hercules.Agent.Socket.HandshakeTimeout
+ Hercules.Agent.WorkerProcess: instance GHC.Internal.Exception.Type.Exception Hercules.Agent.WorkerProcess.WorkerException
+ Hercules.Agent.WorkerProcess: instance GHC.Internal.Show.Show Hercules.Agent.WorkerProcess.WorkerException
+ Hercules.Agent.WorkerProtocol.Command: instance GHC.Internal.Generics.Generic Hercules.Agent.WorkerProtocol.Command.Command
+ Hercules.Agent.WorkerProtocol.Command: instance GHC.Internal.Show.Show Hercules.Agent.WorkerProtocol.Command.Command
+ Hercules.Agent.WorkerProtocol.Command.Build: instance GHC.Internal.Generics.Generic Hercules.Agent.WorkerProtocol.Command.Build.Build
+ Hercules.Agent.WorkerProtocol.Command.Build: instance GHC.Internal.Show.Show Hercules.Agent.WorkerProtocol.Command.Build.Build
+ Hercules.Agent.WorkerProtocol.Command.BuildResult: instance GHC.Internal.Generics.Generic Hercules.Agent.WorkerProtocol.Command.BuildResult.BuildResult
+ Hercules.Agent.WorkerProtocol.Command.BuildResult: instance GHC.Internal.Generics.Generic Hercules.Agent.WorkerProtocol.Command.BuildResult.BuildStatus
+ Hercules.Agent.WorkerProtocol.Command.BuildResult: instance GHC.Internal.Show.Show Hercules.Agent.WorkerProtocol.Command.BuildResult.BuildResult
+ Hercules.Agent.WorkerProtocol.Command.BuildResult: instance GHC.Internal.Show.Show Hercules.Agent.WorkerProtocol.Command.BuildResult.BuildStatus
+ Hercules.Agent.WorkerProtocol.Command.Effect: instance GHC.Internal.Generics.Generic Hercules.Agent.WorkerProtocol.Command.Effect.Effect
+ Hercules.Agent.WorkerProtocol.Command.Effect: instance GHC.Internal.Show.Show Hercules.Agent.WorkerProtocol.Command.Effect.Effect
+ Hercules.Agent.WorkerProtocol.Command.Eval: instance GHC.Internal.Generics.Generic Hercules.Agent.WorkerProtocol.Command.Eval.Eval
+ Hercules.Agent.WorkerProtocol.Command.Eval: instance GHC.Internal.Show.Show Hercules.Agent.WorkerProtocol.Command.Eval.Eval
+ Hercules.Agent.WorkerProtocol.Event: instance GHC.Internal.Generics.Generic Hercules.Agent.WorkerProtocol.Event.Event
+ Hercules.Agent.WorkerProtocol.Event: instance GHC.Internal.Show.Show Hercules.Agent.WorkerProtocol.Event.Event
+ Hercules.Agent.WorkerProtocol.Event.Attribute: instance GHC.Internal.Generics.Generic Hercules.Agent.WorkerProtocol.Event.Attribute.Attribute
+ Hercules.Agent.WorkerProtocol.Event.Attribute: instance GHC.Internal.Generics.Generic Hercules.Agent.WorkerProtocol.Event.Attribute.AttributeType
+ Hercules.Agent.WorkerProtocol.Event.Attribute: instance GHC.Internal.Show.Show Hercules.Agent.WorkerProtocol.Event.Attribute.Attribute
+ Hercules.Agent.WorkerProtocol.Event.Attribute: instance GHC.Internal.Show.Show Hercules.Agent.WorkerProtocol.Event.Attribute.AttributeType
+ Hercules.Agent.WorkerProtocol.Event.AttributeError: instance GHC.Internal.Generics.Generic Hercules.Agent.WorkerProtocol.Event.AttributeError.AttributeError
+ Hercules.Agent.WorkerProtocol.Event.AttributeError: instance GHC.Internal.Show.Show Hercules.Agent.WorkerProtocol.Event.AttributeError.AttributeError
+ Hercules.Agent.WorkerProtocol.Event.AttributeIFD: instance GHC.Internal.Generics.Generic Hercules.Agent.WorkerProtocol.Event.AttributeIFD.AttributeIFD
+ Hercules.Agent.WorkerProtocol.Event.AttributeIFD: instance GHC.Internal.Show.Show Hercules.Agent.WorkerProtocol.Event.AttributeIFD.AttributeIFD
+ Hercules.Agent.WorkerProtocol.Event.BuildResult: instance GHC.Internal.Generics.Generic Hercules.Agent.WorkerProtocol.Event.BuildResult.BuildResult
+ Hercules.Agent.WorkerProtocol.Event.BuildResult: instance GHC.Internal.Show.Show Hercules.Agent.WorkerProtocol.Event.BuildResult.BuildResult
+ Hercules.Agent.WorkerProtocol.OutputInfo: instance GHC.Internal.Generics.Generic Hercules.Agent.WorkerProtocol.OutputInfo.OutputInfo
+ Hercules.Agent.WorkerProtocol.OutputInfo: instance GHC.Internal.Show.Show Hercules.Agent.WorkerProtocol.OutputInfo.OutputInfo
+ Hercules.Agent.WorkerProtocol.ViaJSON: instance GHC.Internal.Read.Read a => GHC.Internal.Read.Read (Hercules.Agent.WorkerProtocol.ViaJSON.ViaJSON a)
+ Hercules.Agent.WorkerProtocol.ViaJSON: instance GHC.Internal.Show.Show a => GHC.Internal.Show.Show (Hercules.Agent.WorkerProtocol.ViaJSON.ViaJSON a)
+ Hercules.Agent.WorkerProtocol.WorkerConfig: instance GHC.Internal.Generics.Generic Hercules.Agent.WorkerProtocol.WorkerConfig.WorkerConfig
+ Hercules.Agent.WorkerProtocol.WorkerConfig: instance GHC.Internal.Generics.Generic a => GHC.Internal.Generics.Generic (Hercules.Agent.WorkerProtocol.WorkerConfig.ViaShowRead a)
+ Hercules.Agent.WorkerProtocol.WorkerConfig: instance GHC.Internal.Read.Read a => Data.Aeson.Types.FromJSON.FromJSON (Hercules.Agent.WorkerProtocol.WorkerConfig.ViaShowRead a)
+ Hercules.Agent.WorkerProtocol.WorkerConfig: instance GHC.Internal.Read.Read a => GHC.Internal.Read.Read (Hercules.Agent.WorkerProtocol.WorkerConfig.ViaShowRead a)
+ Hercules.Agent.WorkerProtocol.WorkerConfig: instance GHC.Internal.Show.Show Hercules.Agent.WorkerProtocol.WorkerConfig.WorkerConfig
+ Hercules.Agent.WorkerProtocol.WorkerConfig: instance GHC.Internal.Show.Show a => Data.Aeson.Types.ToJSON.ToJSON (Hercules.Agent.WorkerProtocol.WorkerConfig.ViaShowRead a)
+ Hercules.Agent.WorkerProtocol.WorkerConfig: instance GHC.Internal.Show.Show a => GHC.Internal.Show.Show (Hercules.Agent.WorkerProtocol.WorkerConfig.ViaShowRead a)
+ Hercules.Secrets: instance GHC.Internal.Base.Monoid w => Hercules.Secrets.MonadMiniWriter w ((,) w)
+ Hercules.Secrets: instance GHC.Internal.Generics.Generic Hercules.Secrets.SecretContext
+ Hercules.Secrets: instance GHC.Internal.Show.Show Hercules.Secrets.SecretContext
+ Hercules.UserException: instance GHC.Internal.Exception.Type.Exception Hercules.UserException.UserException
+ Hercules.UserException: instance GHC.Internal.Show.Show Hercules.UserException.UserException

Files

CHANGELOG.md view
@@ -5,6 +5,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.10.8] - 2026-01-06++### Added++- Nix 2.29, 2.30, 2.31, 2.32, 2.33 support+ ## [0.10.7] - 2025-07-18  ### Fixed@@ -804,6 +810,11 @@  - Initial release +[0.10.8]: https://github.com/hercules-ci/hercules-ci-agent/compare/hercules-ci-agent-0.10.7...hercules-ci-agent-0.10.8+[0.10.7]: https://github.com/hercules-ci/hercules-ci-agent/compare/hercules-ci-agent-0.10.6...hercules-ci-agent-0.10.7+[0.10.6]: https://github.com/hercules-ci/hercules-ci-agent/compare/hercules-ci-agent-0.10.5...hercules-ci-agent-0.10.6+[0.10.5]: https://github.com/hercules-ci/hercules-ci-agent/compare/hercules-ci-agent-0.10.4...hercules-ci-agent-0.10.5+[0.10.4]: https://github.com/hercules-ci/hercules-ci-agent/compare/hercules-ci-agent-0.10.3...hercules-ci-agent-0.10.4 [0.10.3]: https://github.com/hercules-ci/hercules-ci-agent/compare/hercules-ci-agent-0.10.2...hercules-ci-agent-0.10.3 [0.10.2]: https://github.com/hercules-ci/hercules-ci-agent/compare/hercules-ci-agent-0.10.1...hercules-ci-agent-0.10.2 [0.10.1]: https://github.com/hercules-ci/hercules-ci-agent/compare/hercules-ci-agent-0.9.12...hercules-ci-agent-0.10.1
cbits/hercules-error.hh view
@@ -1,4 +1,7 @@ #include <nix/store/store-api.hh>+#if NIX_IS_AT_LEAST(2, 32, 0)+#include <nix/store/build-result.hh>+#endif #include <string>  namespace hercules {@@ -6,7 +9,12 @@ class HerculesBuildError : public nix::BuildError { public:     nix::StorePath drv;+#if NIX_IS_AT_LEAST(2, 32, 0)+    HerculesBuildError(const std::string msg, nix::StorePath drv)+        : BuildError(nix::BuildResult::Failure::MiscFailure, msg), drv(drv) {};+#else     HerculesBuildError(const std::string msg, nix::StorePath drv) : BuildError(msg), drv(drv) {};+#endif };  void copyErrorStrings(const nix::Error &err, const char **msg, const char **trace) noexcept;
cbits/hercules-logger.hh view
@@ -3,11 +3,10 @@ #include <nix/util/error.hh> #include <nix/util/logging.hh> #include <nix/util/sync.hh>-#include <nix/main/shared.hh> - #include <queue> #include <string>+#include <sstream>  class HerculesLogger final : public nix::Logger { 
cbits/nix-2.4/hercules-store.cxx view
@@ -10,20 +10,26 @@ #include <nix/store/store-api.hh> #include <nix/util/callback.hh> #include <nix/expr/get-drvs.hh>-#include <nix/main/shared.hh>  #include "hercules-store.hh"  using namespace nix; -WrappingStore::WrappingStore(const Params& params, ref<Store> storeToWrap)-    : Store(params), wrappedStore(storeToWrap) {}+#if NIX_IS_AT_LEAST(2, 29, 0)+WrappingStore::WrappingStore(ref<Store> storeToWrap)+    : Store(storeToWrap->config), wrappedStore(storeToWrap) {}+#else+WrappingStore::WrappingStore(ref<Store> storeToWrap)+    : Store({}), wrappedStore(storeToWrap) {}+#endif  WrappingStore::~WrappingStore() {} +#if !NIX_IS_AT_LEAST(2, 31, 0) std::string WrappingStore::getUri() {   return "wrapped:" + wrappedStore->getUri();-};+}+#endif  bool WrappingStore::isValidPathUncached(const StorePath & path) {   return wrappedStore->isValidPath(path);  // caches again. Not much we can do.@@ -154,21 +160,29 @@                                  includeDerivers); } +#if NIX_IS_AT_LEAST(2, 30, 0)+MissingPaths WrappingStore::queryMissing(const std::vector<DerivedPath> & targets) {+  return wrappedStore->queryMissing(targets);+}+#else void WrappingStore::queryMissing(const std::vector<DerivedPath> & targets,       StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown,       uint64_t & downloadSize, uint64_t & narSize) {   wrappedStore->queryMissing(targets, willBuild, willSubstitute, unknown,                              downloadSize, narSize); }+#endif   void WrappingStore::connect() {   wrappedStore->connect(); }; +#if !NIX_IS_AT_LEAST(2, 33, 0) Path WrappingStore::toRealPath(const Path& storePath) {   return wrappedStore->toRealPath(storePath);-};+}+#endif;  unsigned int WrappingStore::getProtocol() {   return wrappedStore->getProtocol();@@ -179,20 +193,44 @@   return wrappedStore->isTrustedClient(); } +#if NIX_IS_AT_LEAST(2, 32, 0)+void WrappingStore::registerDrvOutput(const Realisation & output) {+  wrappedStore->registerDrvOutput(output);+}++std::shared_ptr<SourceAccessor> WrappingStore::getFSAccessor(const StorePath & path, bool requireValidPath) {+  return wrappedStore->getFSAccessor(path, requireValidPath);+}+#endif+ ///// -HerculesStore::HerculesStore(const Params& params, ref<Store> storeToWrap)-    : StoreConfig(params)-    , WrappingStore(params, storeToWrap) {}+#if NIX_IS_AT_LEAST(2, 29, 0)+HerculesStore::HerculesStore(ref<Store> storeToWrap)+    : WrappingStore(storeToWrap) {}+#else+HerculesStore::HerculesStore(ref<Store> storeToWrap)+    : StoreConfig(nix::StringMap {})+    , WrappingStore(storeToWrap) {}+#endif +#if !NIX_IS_AT_LEAST(2, 29, 0) const std::string HerculesStore::name() {   return "wrapped " + wrappedStore->name(); }+#endif +#if NIX_IS_AT_LEAST(2, 33, 0) void HerculesStore::queryRealisationUncached(const DrvOutput &drvOutput,+  Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept {+  wrappedStore->queryRealisation(drvOutput, std::move(callback));+}+#else+void HerculesStore::queryRealisationUncached(const DrvOutput &drvOutput,   Callback<std::shared_ptr<const Realisation>> callback) noexcept {   wrappedStore->queryRealisation(drvOutput, std::move(callback)); }+#endif  void HerculesStore::ensurePath(const StorePath& path) {   /* We avoid asking substituters for paths, since@@ -216,10 +254,17 @@ };  // Avoid substituting in evaluator, see `ensurePath` for more details+#if NIX_IS_AT_LEAST(2, 30, 0)+MissingPaths HerculesStore::queryMissing(const std::vector<DerivedPath> & targets) {+  throw nix::Error("HerculesStore::queryMissing is not implemented");+  return MissingPaths{};+}+#else void HerculesStore::queryMissing(const std::vector<DerivedPath> & targets,       StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown,       uint64_t & downloadSize, uint64_t & narSize) {-};+}+#endif  void HerculesStore::buildPaths(const std::vector<DerivedPath> & derivedPaths, BuildMode buildMode, std::shared_ptr<Store> evalStore) {   std::exception_ptr exceptionToThrow(nullptr);
cbits/nix-2.4/hercules-store.hh view
@@ -6,24 +6,26 @@ #include <nix/store/derivations.hh> #include <nix/store/path-with-outputs.hh> #include <nix/store/store-api.hh>-#include <nix/main/shared.hh>  #include "HsFFI.h"  using FSAccessor = nix::SourceAccessor; + using namespace nix;  class WrappingStore : public Store {  public:   ref<Store> wrappedStore; -  WrappingStore(const Params & params, ref<Store> storeToWrap);+  WrappingStore(ref<Store> storeToWrap);     virtual ~WrappingStore(); +#if !NIX_IS_AT_LEAST(2, 31, 0)   virtual std::string getUri() override;+#endif  protected: @@ -98,23 +100,33 @@    virtual ref<FSAccessor> getFSAccessor(bool requireValidPath) override; +#if NIX_IS_AT_LEAST(2, 32, 0)+  virtual void registerDrvOutput(const Realisation & output) override;+  virtual std::shared_ptr<SourceAccessor> getFSAccessor(const StorePath & path, bool requireValidPath = true) override;+#endif+   virtual void addSignatures(const StorePath & storePath, const StringSet & sigs) override;    virtual void computeFSClosure(const StorePathSet & paths,       StorePathSet & out, bool flipDirection = false,       bool includeOutputs = false, bool includeDerivers = false) override; +#if NIX_IS_AT_LEAST(2, 30, 0)+  virtual MissingPaths queryMissing(const std::vector<DerivedPath> & targets) override;+#else   virtual void queryMissing(const std::vector<DerivedPath> & targets,       StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown,       uint64_t & downloadSize, uint64_t & narSize) override;+#endif     virtual unsigned int getProtocol() override;    virtual void connect() override; +#if !NIX_IS_AT_LEAST(2, 33, 0)   virtual Path toRealPath(const Path & storePath) override;-+#endif    virtual std::optional<TrustedFlag> isTrustedClient() override; @@ -125,14 +137,21 @@   StorePathSet ensuredPaths;   void (* builderCallback)(std::vector<nix::StorePathWithOutputs>*, std::exception_ptr *exceptionToThrow); -  HerculesStore(const Params & params, ref<Store> storeToWrap);+  HerculesStore(ref<Store> storeToWrap); +#if !NIX_IS_AT_LEAST(2, 29, 0)   virtual const std::string name() override;+#endif    // Overrides +#if NIX_IS_AT_LEAST(2, 33, 0)   virtual void queryRealisationUncached(const DrvOutput &,+        Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept override;+#else+  virtual void queryRealisationUncached(const DrvOutput &,         Callback<std::shared_ptr<const Realisation>> callback) noexcept override;+#endif    virtual void ensurePath(const StorePath & path) override; @@ -144,9 +163,13 @@   virtual BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv,       BuildMode buildMode = bmNormal) override; +#if NIX_IS_AT_LEAST(2, 30, 0)+  virtual MissingPaths queryMissing(const std::vector<DerivedPath> & targets) override;+#else   virtual void queryMissing(const std::vector<DerivedPath> & targets,       StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown,       uint64_t & downloadSize, uint64_t & narSize) override;+#endif    // Additions 
hercules-ci-agent-worker/Hercules/Agent/Worker/Build/Logger.hs view
@@ -35,7 +35,6 @@  C.include "<cstring>" - C.include "<hercules-ci-cnix/string.hxx>"  C.include "hercules-aliases.h"@@ -240,7 +239,8 @@                 >>= \case                   0 -> LogEntry.Int <$> peek uintPtr                   1 ->-                    LogEntry.String . decode+                    LogEntry.String+                      . decode                       <$> (unsafePackMallocCString =<< peek stringPtr)                   _ -> panic "convertAndDeleteFields invalid internal type" 
hercules-ci-agent-worker/Hercules/Agent/Worker/Build/Prefetched.hs view
@@ -37,6 +37,10 @@ C.include "<nix/store/store-api.hh>" C.include "<nix/util/signals.hh>" +#if NIX_IS_AT_LEAST(2, 29, 0)+C.include "<nix/store/store-open.hh>"+#endif+ C.include "<hercules-ci-cnix/store.hxx>"  C.include "<hercules-ci-cnix/string.hxx>"@@ -90,6 +94,7 @@   }   deriving (Show) +{- ORMOLU_DISABLE -} getDerivation :: Store -> StorePath -> IO (Maybe Derivation) getDerivation (Store store) derivationPath =   nullableMoveToForeignPtrWrapper@@ -108,18 +113,32 @@         } catch (nix::Interrupted &e) {           throw e;         } catch (nix::Error &e) {+#if NIX_IS_AT_LEAST(2, 31, 0)+          printTalkative("ignoring exception during drv lookup in %s: %s", currentStore->config.getHumanReadableURI().c_str(), e.what());+#else           printTalkative("ignoring exception during drv lookup in %s: %s", currentStore->getUri(), e.what());+#endif         } catch (std::exception &e) {+#if NIX_IS_AT_LEAST(2, 31, 0)+          printTalkative("ignoring exception during drv lookup in %s: %s", currentStore->config.getHumanReadableURI().c_str(), e.what());+#else           printTalkative("ignoring exception during drv lookup in %s: %s", currentStore->getUri(), e.what());+#endif         } catch (...) {           // FIXME: remove this and make the "specific" catches above work on darwin+#if NIX_IS_AT_LEAST(2, 31, 0)+          printTalkative("ignoring unknown exception during drv lookup in %s: %s", currentStore->config.getHumanReadableURI().c_str());+#else           printTalkative("ignoring unknown exception during drv lookup in %s: %s", currentStore->getUri());+#endif         }       }       return derivation;     }|]+{- ORMOLU_ENABLE -}  -- | @buildDerivation derivationPath derivationText@+{- ORMOLU_DISABLE -} buildDerivation :: Store -> StorePath -> Derivation -> Maybe [ByteString] -> IO BuildResult buildDerivation (Store store) derivationPath derivation extraInputs =   let extraInputsMerged = C8.intercalate "\n" (fromMaybe [] extraInputs)@@ -175,6 +194,71 @@          nix::BuildResult result = store.buildDerivation(derivationPath, *derivation); +#if NIX_IS_AT_LEAST(2, 32, 0)+        if (auto *success = result.tryGetSuccess()) {+          switch (success->status) {+            case nix::BuildResult::Success::Built:+              status = 0;+              break;+            case nix::BuildResult::Success::Substituted:+              status = 1;+              break;+            case nix::BuildResult::Success::AlreadyValid:+              status = 2;+              break;+            case nix::BuildResult::Success::ResolvesToAlreadyValid:+              status = 13;+              break;+            default:+              status = -1;+              break;+          }+        } else if (auto *failure = result.tryGetFailure()) {+          switch (failure->status) {+            case nix::BuildResult::Failure::PermanentFailure:+              status = 3;+              break;+            case nix::BuildResult::Failure::InputRejected:+              status = 4;+              break;+            case nix::BuildResult::Failure::OutputRejected:+              status = 5;+              break;+            case nix::BuildResult::Failure::TransientFailure:+              status = 6;+              break;+            case nix::BuildResult::Failure::CachedFailure:+              status = 7;+              break;+            case nix::BuildResult::Failure::TimedOut:+              status = 8;+              break;+            case nix::BuildResult::Failure::MiscFailure:+              status = 9;+              break;+            case nix::BuildResult::Failure::DependencyFailed:+              status = 10;+              break;+            case nix::BuildResult::Failure::LogLimitExceeded:+              status = 11;+              break;+            case nix::BuildResult::Failure::NotDeterministic:+              status = 12;+              break;+            case nix::BuildResult::Failure::NoSubstituters:+              status = 14;+              break;+            case nix::BuildResult::Failure::HashMismatch:+              status = 15;+              break;+            default:+              status = -2;+              break;+          }+        } else {+          status = -3;+        }+#else         switch (result.status) {           case nix::BuildResult::Built:             status = 0;@@ -219,9 +303,25 @@             status = result.success() ? -1 : -2;             break;         }+#endif+#if NIX_IS_AT_LEAST(2, 32, 0)+        auto *successPtr = result.tryGetSuccess();+        auto *failurePtr = result.tryGetFailure();+        assert(!(successPtr && failurePtr)); // Both can't be true+        assert(successPtr || failurePtr);    // One must be true++        success = successPtr != nullptr;+        if (failurePtr) {+          printError(failurePtr->errorMsg);+          errorMessage = stringdup(failurePtr->errorMsg);+        } else {+          errorMessage = stringdup("");+        }+#else         printError(result.errorMsg);         success = result.success();         errorMessage = stringdup(result.errorMsg);+#endif         startTime = result.startTime;         stopTime = result.stopTime;       }@@ -241,3 +341,4 @@                       stopTime = stopTimeValue,                       errorMessage = toS errorMessageValue                     }+{- ORMOLU_ENABLE -}
hercules-ci-agent-worker/Hercules/Agent/Worker/HerculesStore.hs view
@@ -36,8 +36,6 @@  C.include "<cstring>" -C.include "<nix/main/shared.hh>"- C.include "hercules-aliases.h"  C.using "namespace nix"@@ -51,7 +49,7 @@     ( liftIO         [C.block| refHerculesStore* {           refStore &s = *$(refStore *wrappedStore);-          refHerculesStore hs(new HerculesStore({}, s));+          refHerculesStore hs(new HerculesStore(s));           return new refHerculesStore(hs);         } |]     )
hercules-ci-agent.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.4  name:           hercules-ci-agent-version:        0.10.7+version:        0.10.8 synopsis:       Runs Continuous Integration tasks on your machines category:       Nix, CI, Testing, DevOps homepage:       https://docs.hercules-ci.com@@ -17,14 +17,21 @@     cbits/hercules-error.hh     cbits/hercules-logger.hh     cbits/nix-2.4/hercules-store.hh+    cbits/nix-2.4/hercules-store.cxx     data/default-herculesCI-for-flake.nix     testdata/vm-test-run-agent-test.drv+    hercules-ci-nix-daemon/daemon.cxx   flag ide   description: Whether to enable IDE workarounds. You shouldn't need this.   default: False +flag nix-2_31+  description: nix-store >= 2.31+  default: False+  manual: False+ source-repository head   type: git   location: https://github.com/hercules-ci/hercules-ci-agent@@ -56,8 +63,12 @@  -- match the C++ language standard Nix is using common cxx-opts-  cxx-options:-    -std=c++2a+  if flag(nix-2_31)+    cxx-options:+      -std=c++23+  else+    cxx-options:+      -std=c++2a    cxx-options:     -Wall@@ -70,12 +81,22 @@   if impl(ghc >= 8.10)     ghc-options:       -optcxx-Wall-      -optcxx-std=c++2a+    if flag(nix-2_31)+      ghc-options:+        -optcxx-std=c++23+    else+      ghc-options:+        -optcxx-std=c++2a   else     -- Remove soon     ghc-options:-      -optc-std=c++2a       -optc-Wall+    if flag(nix-2_31)+      ghc-options:+        -optc-std=c++23+    else+      ghc-options:+        -optc-std=c++2a     if os(darwin)       ghc-options: -pgmc=clang++ @@ -377,10 +398,11 @@     , uuid     , vector   pkgconfig-depends:-      nix-store >= 2.28-    , nix-expr >= 2.28+      nix-store >= 2.28 && < 2.34+    , nix-expr >= 2.28 && < 2.34+    , nix-flake >= 2.28 && < 2.34     -- TODO: replace stack overflow detection and remove nix-main-    , nix-main >= 2.28+    , nix-main >= 2.28 && < 2.34   default-language: Haskell2010  test-suite hercules-ci-agent-unit-tests@@ -468,10 +490,8 @@  executable hercules-ci-nix-daemon   import: cxx-opts-  main-is: main.cc-  cxx-sources: hercules-ci-nix-daemon/daemon.cc+  main-is: hercules-ci-nix-daemon/daemon.cxx   default-language: Haskell2010-  hs-source-dirs: hercules-ci-nix-daemon   pkgconfig-depends:-      nix-store >= 2.28-    , nix-main >= 2.28+      nix-store >= 2.28 && < 2.34+    , nix-main >= 2.28 && < 2.34
hercules-ci-agent/Hercules/Agent/Build.hs view
@@ -9,15 +9,15 @@ import Data.Vector (Vector) import Hercules.API.Agent.Build qualified as API.Build import Hercules.API.Agent.Build.BuildEvent qualified as BuildEvent-import Hercules.API.Agent.OutputInfo-  ( OutputInfo,-  )-import Hercules.API.Agent.OutputInfo qualified as OutputInfo import Hercules.API.Agent.Build.BuildEvent.Pushed qualified as Pushed import Hercules.API.Agent.Build.BuildTask   ( BuildTask,   ) import Hercules.API.Agent.Build.BuildTask qualified as BuildTask+import Hercules.API.Agent.OutputInfo+  ( OutputInfo,+  )+import Hercules.API.Agent.OutputInfo qualified as OutputInfo import Hercules.API.Logs.LogEntry (LogEntry) import Hercules.API.Servant (noContent) import Hercules.API.TaskStatus (TaskStatus)@@ -38,12 +38,12 @@ import Hercules.Agent.WorkerProtocol.Command.Build qualified as Command.Build import Hercules.Agent.WorkerProtocol.Event qualified as Event import Hercules.Agent.WorkerProtocol.Event.BuildResult qualified as BuildResult+import Hercules.Agent.WorkerProtocol.OutputInfo qualified as Proto import Hercules.Agent.WorkerProtocol.ViaJSON (ViaJSON (ViaJSON)) import Hercules.CNix.Store qualified as CNix import Hercules.Error (defaultRetry) import Protolude import System.Process-import qualified Hercules.Agent.WorkerProtocol.OutputInfo as Proto  performBuild :: (Vector LogEntry -> IO ()) -> BuildTask.BuildTask -> App TaskStatus performBuild sendLogEntries buildTask = katipAddContext (sl "taskDerivationPath" buildTask.derivationPath) $ do@@ -106,11 +106,7 @@     Just BuildResult.BuildSuccess {outputs = outs'} -> do       let outs = convertOutputs (BuildTask.derivationPath buildTask) outs'       reportOutputInfos buildTask outs-#if MIN_VERSION_cachix(1, 4, 0) && ! MIN_VERSION_cachix(1, 5, 0)-      CNix.withStore $ \store -> push store buildTask outs-#else-      asks (Cachix.Env.store . Env.cachixEnv) >>= \store -> push store buildTask outs-#endif+      pushToStore buildTask outs       reportSuccess buildTask       pure $ TaskStatus.Successful ()     Just BuildResult.BuildFailure {errorMessage = errorMessage} ->@@ -119,6 +115,15 @@         pure $ TaskStatus.Terminated ()     Nothing -> pure $ TaskStatus.Exceptional "Build did not complete" +-- | Push outputs to the store using the appropriate method based on cachix version+pushToStore :: BuildTask -> Map Text OutputInfo -> App ()+pushToStore buildTask outs = do+#if MIN_VERSION_cachix(1, 4, 0) && ! MIN_VERSION_cachix(1, 5, 0)+  CNix.withStore $ \store -> push store buildTask outs+#else+  asks (Cachix.Env.store . Env.cachixEnv) >>= \store -> push store buildTask outs+#endif+ convertOutputs :: Text -> [Proto.OutputInfo] -> Map Text OutputInfo convertOutputs deriver = foldMap $ \oi ->   M.singleton (decodeUtf8With lenientDecode oi.name) $@@ -127,13 +132,13 @@ convertOutputInfo :: Text -> Proto.OutputInfo -> OutputInfo convertOutputInfo deriver oi =   OutputInfo.OutputInfo-      { OutputInfo.deriver = deriver,-        name = decodeUtf8With lenientDecode oi.name,-        path = decodeUtf8With lenientDecode oi.path,-        size = fromIntegral oi.size,-        hash = decodeUtf8With lenientDecode oi.hash,-        references = Just (decodeUtf8With lenientDecode <$> oi.references)-      }+    { OutputInfo.deriver = deriver,+      name = decodeUtf8With lenientDecode oi.name,+      path = decodeUtf8With lenientDecode oi.path,+      size = fromIntegral oi.size,+      hash = decodeUtf8With lenientDecode oi.hash,+      references = Just (decodeUtf8With lenientDecode <$> oi.references)+    }  push :: CNix.Store -> BuildTask -> Map Text OutputInfo -> App () push store buildTask outs = do
hercules-ci-agent/Hercules/Agent/Cache.hs view
@@ -89,4 +89,4 @@       ( \path -> do           CNix.signPath store key path       )-    <&> foldMap (\case True -> (1, 1); False -> (1, 0))+      <&> foldMap (\case True -> (1, 1); False -> (1, 0))
hercules-ci-agent/Hercules/Agent/Cachix.hs view
@@ -6,25 +6,25 @@   ) where -import qualified Cachix.Client.Push as Cachix.Push-import Cachix.Types.BinaryCache (CompressionMethod(XZ))+import Cachix.Client.Push qualified as Cachix.Push+import Cachix.Types.BinaryCache (CompressionMethod (XZ)) #if MIN_VERSION_cachix(1,4,0) && ! MIN_VERSION_cachix(1,5,0) import qualified Cachix.Client.Store import qualified Cachix.Client.Store as Cachix #endif-import qualified Data.Conduit as Conduit import Control.Monad.IO.Unlift-import qualified Data.Map as M-import qualified Hercules.Agent.Cachix.Env as Agent.Cachix+import Data.Conduit qualified as Conduit+import Data.Map qualified as M+import Hercules.Agent.Cachix.Env qualified as Agent.Cachix import Hercules.Agent.Cachix.Info (activePushCaches) import Hercules.Agent.Env as Agent.Env hiding (activePushCaches)-import qualified Hercules.Agent.EnvironmentInfo as EnvInfo+import Hercules.Agent.EnvironmentInfo qualified as EnvInfo import Hercules.Agent.Log+import Hercules.CNix qualified as CNix import Hercules.CNix.Store (StorePath) import Hercules.Error-import qualified Hercules.Formats.CachixCache as CachixCache+import Hercules.Formats.CachixCache qualified as CachixCache import Protolude-import qualified Hercules.CNix as CNix #if MIN_VERSION_cachix(1,7,2) import qualified Cachix.Client.OptionsParser as Opts #endif@@ -42,62 +42,127 @@       maybeToEither (FatalError $ "Cache not found " <> cache) $         M.lookup cache pushCaches   ul <- askUnliftIO-  let pushParams =-        Cachix.Push.PushParams-          { pushParamsName = Agent.Cachix.pushCacheName pushCache,-            pushParamsSecret = Agent.Cachix.pushCacheSecret pushCache,-            pushParamsStore = cachixStore,+  let pushParams = makePushParams pushCache cachixStore clientEnv+  paths' <- convertPaths nixStore paths+  void $+    Cachix.Push.pushClosure+      (\f l -> liftIO $ Cachix.Push.mapConcurrentlyBounded workers (fmap (unliftIO ul) f) l)+      pushParams+      paths'+  where #if MIN_VERSION_cachix(1,6,0)-            pushOnClosureAttempt = \_ missing -> return missing,-#endif-            pushParamsClientEnv = clientEnv,-            pushParamsStrategy = \storePath ->-#if MIN_VERSION_cachix(1,4,0) && ! MIN_VERSION_cachix(1,5,0)-              let ctx = withNamedContext "path" (Cachix.getPath storePath)+    makePushParams pushCache cachixStore clientEnv =+      Cachix.Push.PushParams+        { pushParamsName = Agent.Cachix.pushCacheName pushCache,+          pushParamsSecret = Agent.Cachix.pushCacheSecret pushCache,+          pushParamsStore = cachixStore,+          pushOnClosureAttempt = \_ missing -> return missing,+          pushParamsClientEnv = clientEnv,+          pushParamsStrategy = makePushStrategy+        } #else-              let ctx = withNamedContext "path" (show storePath :: Text)+    makePushParams pushCache cachixStore clientEnv =+      Cachix.Push.PushParams+        { pushParamsName = Agent.Cachix.pushCacheName pushCache,+          pushParamsSecret = Agent.Cachix.pushCacheSecret pushCache,+          pushParamsStore = cachixStore,+          pushParamsClientEnv = clientEnv,+          pushParamsStrategy = makePushStrategy+        } #endif-               in Cachix.Push.PushStrategy-                    { onAlreadyPresent = pass,-                      onAttempt = \retryStatus size ->-                        ctx $-                          withNamedContext "size" size $-                            withNamedContext "retry" (show retryStatus :: Text) $-                              logLocM DebugS "pushing",-#if MIN_VERSION_cachix(1,3,0)-                      on401 = \err -> throwIO $ FatalError $ "Cachix push is unauthorized: " <> show err,++#if MIN_VERSION_cachix(1,7,2)+    makePushStrategy storePath =+      let ctx = makeContextForPath storePath+       in Cachix.Push.PushStrategy+            { onAlreadyPresent = pass,+              onAttempt = \retryStatus size ->+                ctx $+                  withNamedContext "size" size $+                    withNamedContext "retry" (show retryStatus :: Text) $+                      logLocM DebugS "pushing",+              on401 = makeOn401Handler,+              onError = \err -> throwIO $ FatalError $ "Error pushing to cachix: " <> show err,+              onDone = ctx $ logLocM DebugS "push done",+              compressionMethod = XZ,+              compressionLevel = 2,+              onUncompressedNARStream = \_ _ -> Conduit.awaitForever Conduit.yield,+              chunkSize = Opts.defaultChunkSize,+              numConcurrentChunks = Opts.defaultNumConcurrentChunks,+              omitDeriver = False+            }+#elif MIN_VERSION_cachix(1,6,0)+    makePushStrategy storePath =+      let ctx = makeContextForPath storePath+       in Cachix.Push.PushStrategy+            { onAlreadyPresent = pass,+              onAttempt = \retryStatus size ->+                ctx $+                  withNamedContext "size" size $+                    withNamedContext "retry" (show retryStatus :: Text) $+                      logLocM DebugS "pushing",+              on401 = makeOn401Handler,+              onError = \err -> throwIO $ FatalError $ "Error pushing to cachix: " <> show err,+              onDone = ctx $ logLocM DebugS "push done",+              compressionMethod = XZ,+              compressionLevel = 2,+              onUncompressedNARStream = \_ _ -> Conduit.awaitForever Conduit.yield,+              omitDeriver = False+            }+#elif MIN_VERSION_cachix(1,1,0)+    makePushStrategy storePath =+      let ctx = makeContextForPath storePath+       in Cachix.Push.PushStrategy+            { onAlreadyPresent = pass,+              onAttempt = \retryStatus size ->+                ctx $+                  withNamedContext "size" size $+                    withNamedContext "retry" (show retryStatus :: Text) $+                      logLocM DebugS "pushing",+              on401 = makeOn401Handler,+              onError = \err -> throwIO $ FatalError $ "Error pushing to cachix: " <> show err,+              onDone = ctx $ logLocM DebugS "push done",+              compressionMethod = XZ,+              compressionLevel = 2,+              omitDeriver = False+            } #else-                      on401 = throwIO $ FatalError "Cachix push is unauthorized",+    makePushStrategy storePath =+      let ctx = makeContextForPath storePath+       in Cachix.Push.PushStrategy+            { onAlreadyPresent = pass,+              onAttempt = \retryStatus size ->+                ctx $+                  withNamedContext "size" size $+                    withNamedContext "retry" (show retryStatus :: Text) $+                      logLocM DebugS "pushing",+              on401 = makeOn401Handler,+              onError = \err -> throwIO $ FatalError $ "Error pushing to cachix: " <> show err,+              onDone = ctx $ logLocM DebugS "push done",+              withXzipCompressor = Cachix.Push.defaultWithXzipCompressor,+              omitDeriver = False+            } #endif-                      onError = \err -> throwIO $ FatalError $ "Error pushing to cachix: " <> show err,-                      onDone = ctx $ logLocM DebugS "push done",-#if MIN_VERSION_cachix(1,1,0)-                      compressionMethod = XZ,-                      compressionLevel = 2,++#if MIN_VERSION_cachix(1,4,0) && ! MIN_VERSION_cachix(1,5,0)+    makeContextForPath storePath = withNamedContext "path" (Cachix.getPath storePath) #else-                      withXzipCompressor = Cachix.Push.defaultWithXzipCompressor,-#endif-#if MIN_VERSION_cachix(1,6,0)-                      onUncompressedNARStream = \_ _ -> Conduit.awaitForever Conduit.yield,+    makeContextForPath storePath = withNamedContext "path" (show storePath :: Text) #endif-#if MIN_VERSION_cachix(1,7,2)-                      chunkSize = Opts.defaultChunkSize,-                      numConcurrentChunks = Opts.defaultNumConcurrentChunks,++#if MIN_VERSION_cachix(1,3,0)+    makeOn401Handler = \err -> throwIO $ FatalError $ "Cachix push is unauthorized: " <> show err+#else+    makeOn401Handler = throwIO $ FatalError "Cachix push is unauthorized" #endif-                      omitDeriver = False-                    }-          }+ #if MIN_VERSION_cachix(1,4,0) && ! MIN_VERSION_cachix(1,5,0)-  paths' <- paths & traverse (convertPath nixStore)+    convertPaths nixStore paths = paths & traverse (convertPath nixStore) #else-  let paths' = paths-      _ = nixStore -- silence unused warning+    convertPaths nixStore paths = do+      let _ = nixStore -- silence unused warning+      pure paths #endif-  void $-    Cachix.Push.pushClosure-      (\f l -> liftIO $ Cachix.Push.mapConcurrentlyBounded workers (fmap (unliftIO ul) f) l)-      pushParams-      paths'  #if MIN_VERSION_cachix(1,4,0) && ! MIN_VERSION_cachix(1,5,0) 
hercules-ci-agent/Hercules/Agent/Compat.hs view
@@ -2,7 +2,7 @@  module Hercules.Agent.Compat (katipLevel) where -import qualified Katip as K+import Katip qualified as K import Protolude  katipLevel :: K.Severity -> K.PermitFunc
hercules-ci-agent/Hercules/Agent/Config.hs view
@@ -83,7 +83,8 @@ combiCodec :: Combi' (Config 'Input) combiCodec =   Config-    <$> opt (textAtKey "apiBaseUrl") .=. herculesApiBaseURL+    <$> opt (textAtKey "apiBaseUrl")+    .=. herculesApiBaseURL     <*> opt (boolAtKey "nixUserIsTrusted") .=. nixUserIsTrusted     <*> opt       ( combi@@ -129,7 +130,8 @@ mountableCodec :: Combi' Mountable mountableCodec =   Mountable-    <$> textAtKey "source" .=. Mountable.source+    <$> textAtKey "source"+    .=. Mountable.source     <*> boolAtKey "readOnly" .=. Mountable.readOnly     <*> combi       ((throwImmediately . A.parseJSON) <$> Toml.embedJson "condition")
− hercules-ci-nix-daemon/daemon.cc
@@ -1,113 +0,0 @@-#include <sys/wait.h>-#include <sys/socket.h>-#include <sys/un.h>-#include <unistd.h>--#include <string_view>--#include <nix/util/error.hh>-#include <nix/util/fmt.hh>-#include <nix/util/config-global.hh>-#include <nix/util/serialise.hh>-#include <nix/util/signals.hh>-#include <nix/store/daemon.hh>-#include <nix/main/shared.hh>--using namespace nix;--using nix::unix::closeOnExec;---static void sigChldHandler(int sigNo)-{-    // Ensure we don't modify errno of whatever we've interrupted-    auto saved_errno = errno;-    //  Reap all dead children.-    while (waitpid(-1, 0, WNOHANG) > 0) ;-    errno = saved_errno;-}--static void setSigChldAction()-{-    struct sigaction act, oact;-    act.sa_handler = sigChldHandler;-    sigfillset(&act.sa_mask);-    act.sa_flags = 0;-    if (sigaction(SIGCHLD, &act, &oact))-        throw SysError("setting SIGCHLD handler");-}--extern "C" int main(int argc, char **argv) {-    nix::initNix();-    -    for (int i = 1; i < argc && argv[i]; i++) {-        std::string arg(argv[i]);-        if (arg == "--option") {-            if (i + 2 < argc) {-                nix::globalConfig.set(argv[i+1], argv[i+2]);-                i += 2;-            }-            else {-                std::cerr << "Not enough arguments to --option" << std::endl;-                return 1;-            }-        }-    }--    // See withNixDaemonProxy for stdin (ab)use-    AutoCloseFD socketFD = dup(0);-    closeOnExec(socketFD.get());--    // Put /dev/null on stdin-    int devnull = open("/dev/null", O_RDONLY);-    dup2(devnull, 0);-    close(devnull);--    setSigChldAction();-    while (1) {-        struct sockaddr_un remoteAddr;-        socklen_t remoteAddrLen = sizeof(remoteAddr);-        try {-            AutoCloseFD remote = accept(socketFD.get(), (struct sockaddr *) &remoteAddr, &remoteAddrLen);-            checkInterrupt();-            if (!remote) {-                if (errno == EINTR) continue;-                else throw SysError("hercules-ci-nix-daemon: accepting connection");-            }-            closeOnExec(remote.get());-            ProcessOptions options;-            options.errorPrefix = "hercules-ci-nix-daemon: unexpected error: ";-            options.dieWithParent = false;-            options.runExitHandlers = true;-            options.allowVfork = false;-            startProcess([&]() {-                socketFD = -1;--                // Regular nix daemon creates a new session for connections and-                // does not kill connection child processes. Those are not-                // appropriate behaviors for a temporary proxy.--                FdSource from(remote.get());-                FdSink to(remote.get());-                // TODO: disable caching without interfering with user parameters-                ref<Store> store = openStore();-                TrustedFlag trusted = NotTrusted;-                daemon::RecursiveFlag recursive = daemon::NotRecursive;-                daemon::processConnection(-                    store-                    , std::move(from)-                    , std::move(to)-                    , trusted-                    , recursive-                    );-            });-        } catch (Interrupted & e) {-            return 0;-        } catch (Error & error) {-            ErrorInfo ei = error.info();-            ei.msg = HintFmt("hercules-ci-nix-daemon: error processing connection: %1%", ei.msg.str());-            logError(ei);-        }-    }-    return 0;-}
+ hercules-ci-nix-daemon/daemon.cxx view
@@ -0,0 +1,117 @@+#include <sys/wait.h>+#include <sys/socket.h>+#include <sys/un.h>+#include <unistd.h>++#include <string_view>++#include <nix/util/error.hh>+#include <nix/util/fmt.hh>+#include <nix/util/config-global.hh>+#include <nix/util/serialise.hh>+#include <nix/util/signals.hh>+#include <nix/store/daemon.hh>+#include <nix/main/shared.hh>++#if NIX_IS_AT_LEAST(2, 29, 0)+#include <nix/store/store-open.hh>+#endif++using namespace nix;++using nix::unix::closeOnExec;+++static void sigChldHandler(int sigNo)+{+    // Ensure we don't modify errno of whatever we've interrupted+    auto saved_errno = errno;+    //  Reap all dead children.+    while (waitpid(-1, 0, WNOHANG) > 0) ;+    errno = saved_errno;+}++static void setSigChldAction()+{+    struct sigaction act, oact;+    act.sa_handler = sigChldHandler;+    sigfillset(&act.sa_mask);+    act.sa_flags = 0;+    if (sigaction(SIGCHLD, &act, &oact))+        throw SysError("setting SIGCHLD handler");+}++extern "C" int main(int argc, char **argv) {+    nix::initNix();+    +    for (int i = 1; i < argc && argv[i]; i++) {+        std::string arg(argv[i]);+        if (arg == "--option") {+            if (i + 2 < argc) {+                nix::globalConfig.set(argv[i+1], argv[i+2]);+                i += 2;+            }+            else {+                std::cerr << "Not enough arguments to --option" << std::endl;+                return 1;+            }+        }+    }++    // See withNixDaemonProxy for stdin (ab)use+    AutoCloseFD socketFD = dup(0);+    closeOnExec(socketFD.get());++    // Put /dev/null on stdin+    int devnull = open("/dev/null", O_RDONLY);+    dup2(devnull, 0);+    close(devnull);++    setSigChldAction();+    while (1) {+        struct sockaddr_un remoteAddr;+        socklen_t remoteAddrLen = sizeof(remoteAddr);+        try {+            AutoCloseFD remote = accept(socketFD.get(), (struct sockaddr *) &remoteAddr, &remoteAddrLen);+            checkInterrupt();+            if (!remote) {+                if (errno == EINTR) continue;+                else throw SysError("hercules-ci-nix-daemon: accepting connection");+            }+            closeOnExec(remote.get());+            ProcessOptions options;+            options.errorPrefix = "hercules-ci-nix-daemon: unexpected error: ";+            options.dieWithParent = false;+            options.runExitHandlers = true;+            options.allowVfork = false;+            startProcess([&]() {+                socketFD = -1;++                // Regular nix daemon creates a new session for connections and+                // does not kill connection child processes. Those are not+                // appropriate behaviors for a temporary proxy.++                FdSource from(remote.get());+                FdSink to(remote.get());+                // TODO: disable caching without interfering with user parameters+                ref<Store> store = openStore();+                TrustedFlag trusted = NotTrusted;+                daemon::RecursiveFlag recursive = daemon::NotRecursive;+                daemon::processConnection(+                    store+                    , std::move(from)+                    , std::move(to)+                    , trusted+                    , recursive+                    );+            });+        } catch (Interrupted & e) {+            return 0;+        } catch (Error & error) {+            ErrorInfo ei = error.info();+            ei.msg = HintFmt("hercules-ci-nix-daemon: error processing connection: %1%", ei.msg.str());+            logError(ei);+        }+    }+    return 0;+}
− hercules-ci-nix-daemon/main.cc
@@ -1,4 +0,0 @@-/*-  main() is in daemon.cc, because cabal doesn't pass-  the correct flags to the main-is file.-*/
src/Hercules/Agent/NixFile.hs view
@@ -29,6 +29,7 @@     -- * @onPush@     getVirtualValueByPath,     parseExtraInputs,+    resolveAndInvokeOutputs,   ) where 
src/Hercules/Effect.hs view
@@ -283,13 +283,13 @@                 BindMount {pathInContainer = "/nix/var/nix/daemon-socket/socket", pathInHost = toS forwardedSocketPath, readOnly = True}               ]                 ++ [ BindMount {pathInContainer = "/etc", pathInHost = etcDir, readOnly = False}-                     | not (isExtraBind "/etc")+                   | not (isExtraBind "/etc")                    ]                 ++ [-                     -- TODO: does this apply to crun?-                     -- we cannot bind mount this read-only because of https://github.com/opencontainers/runc/issues/1523-                     BindMount {pathInContainer = "/etc/resolv.conf", pathInHost = "/etc/resolv.conf", readOnly = False}-                     | not (isExtraBind "/etc") && not (isExtraBind "/etc/resolv.conf")+                   -- TODO: does this apply to crun?+                   -- we cannot bind mount this read-only because of https://github.com/opencontainers/runc/issues/1523+                   BindMount {pathInContainer = "/etc/resolv.conf", pathInHost = "/etc/resolv.conf", readOnly = False}+                   | not (isExtraBind "/etc") && not (isExtraBind "/etc/resolv.conf")                    ]                 ++ extraBindMounts_,             executable = decodeUtf8With lenientDecode drvBuilder,
src/Hercules/Effect/Container.hs view
@@ -8,6 +8,7 @@ import Data.Aeson (Value (String), eitherDecode, encode, object, toJSON) import Data.Aeson.Lens import Data.ByteString qualified as BS+import Data.ByteString.Char8 qualified as BS.Char8 import Data.ByteString.Lazy qualified as BL import Data.Map qualified as M import Data.UUID.V4 qualified as UUID@@ -148,7 +149,7 @@         )         ( do             let shovel =-                  handleEOF (BS.hGetLine master) >>= \case+                  handleEOF (BS.Char8.hGetLine master) >>= \case                     "" -> pass                     someBytes | "@nix" `BS.isPrefixOf` someBytes -> do                       -- TODO use it (example @nix { "action": "setPhase", "phase": "effectPhase" })