Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@ on: [push, pull_request]
jobs:
build:
name: ghc ${{ matrix.ghc }}
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
strategy:
matrix:
ghc: ["8.6.5", "8.8.4", "8.10.5", "9.0.1"]
cabal: ["3.4.0.0"]
env:
CONFIG: "--enable-tests --enable-benchmarks"
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v6
- name: Install system dependencies
run: sudo apt-get install -y libsodium-dev
- name: Setup Haskell
id: setup-haskell-cabal
uses: haskell/actions/setup@v1
uses: haskell-actions/setup@v2
with:
ghc-version: ${{ matrix.ghc }}
cabal-version: ${{ matrix.cabal }}
- run: cabal v2-update
- run: cabal v2-freeze $CONFIG
- uses: actions/cache@v2
- uses: actions/cache@v5
with:
path: |
~/.cabal/store
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.stack-work/
dist/
dist-newstyle/
result
24 changes: 21 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
# jenkinsPlugins2nix

```
Usage: jenkinsPlugins2nix [-r|--dependency-resolution [as-given|latest]]
Usage: jenkinsPlugins2nix [-r|--dependency-resolution [as-given|latest|jenkins[:VERSION]]]
[--skip-optional]
(-p|--plugin PLUGIN_NAME{:PLUGIN_VERSION})
Generate nix expressions for requested Jenkins plugins.

Available options:
-r,--dependency-resolution [as-given|latest]
Dependency resolution (default: latest)
-r,--dependency-resolution [as-given|latest|jenkins[:VERSION]]
Dependency resolution (default: latest). Use
`jenkins:<VERSION>` to resolve against a specific
Jenkins version (for example: `-r jenkins:2.401`).
-p,--plugin PLUGIN_NAME{:PLUGIN_VERSION}
Plugins we should generate nix for. Latest version is
used if not specified.
--skip-optional Skip optional dependencies when downloading plugins
-h,--help Show this help text

```
Expand Down Expand Up @@ -45,3 +49,17 @@ latest one.

In case we only ask for `A`, the version of `B` will depend on
`--resolution-strategy`.

### Jenkins-specific strategy

You can select a specific Jenkins version for dependency resolution with
`-r jenkins:<VERSION>`. When this strategy is used, dependencies without an
explicit version will be resolved with regard to the supplied Jenkins
version (for example `-r jenkins:2.401`).

### Optional dependencies

By default the tool downloads all dependencies (including optional ones) to
avoid backward-compatibility problems. Use `--skip-optional` to exclude
optional dependencies from downloads when you prefer a minimal set of
dependencies.
24 changes: 15 additions & 9 deletions app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ module Main (main) where

import qualified Data.Bimap as Bimap
import Data.List (intersperse)
import Data.Monoid (mconcat, (<>))
import qualified Data.Text as Text
import Data.Text.Prettyprint.Doc.Render.Terminal (putDoc)
import qualified Prettyprinter.Render.Terminal as Pretty
import Nix.JenkinsPlugins2Nix
import Nix.JenkinsPlugins2Nix.Types
import qualified Options.Applicative as Opt
Expand All @@ -28,7 +27,7 @@ main = do
hPutStrLn stderr err
exitFailure
Right p -> do
putDoc p
Pretty.putDoc p
exitSuccess
where
opts = Opt.info (parseConfig Opt.<**> Opt.helper)
Expand All @@ -43,23 +42,30 @@ parseConfig = Config
<> Opt.short 'r'
<> Opt.help "Dependency resolution"
<> Opt.showDefaultWith (resolutions Bimap.!)
<> Opt.metavar (printf "[%s]" . mconcat . intersperse "|" $ Bimap.keysR resolutions)
<> Opt.metavar (printf "[%s]" . concat . intersperse "|" $ Bimap.keysR resolutions)
<> Opt.value Latest )
<*> Opt.some (Opt.option requestedPluginReader
( Opt.metavar "PLUGIN_NAME{:PLUGIN_VERSION}"
<> Opt.long "plugin"
<> Opt.short 'p'
<> Opt.help "Plugins we should generate nix for. Latest version is used if not specified." )
)
<*> Opt.flag Optional Mandatory
( Opt.long "skip-optional"
<> Opt.help "skip optional dependencies" )
where
resolutions :: Bimap.Bimap ResolutionStrategy String
resolutions = Bimap.fromList [(AsGiven, "as-given"), (Latest, "latest")]
resolutions = Bimap.fromList [(AsGiven, "as-given"), (Latest, "latest"), (JenkinsVersion(""), "jenkins")]

resolutionReader :: Opt.ReadM ResolutionStrategy
resolutionReader = Opt.eitherReader $ \s -> case Bimap.lookupR s resolutions of
Nothing -> Left $ "Invalid dependency resolution, needs to be one of "
<> show (Bimap.keysR resolutions)
Just v -> Right v
resolutionReader = let
strat = \s -> (Text.unpack (head (Text.splitOn ":" (Text.pack s))))
version = \s -> (Text.unpack(last (Text.splitOn ":" (Text.pack s))))
in Opt.eitherReader $ \s -> case Bimap.lookupR (strat s) resolutions of
Nothing -> Left $ "Invalid dependency resolution, needs to be one of "
<> show (Bimap.keysR resolutions)
Just (JenkinsVersion("")) -> Right (JenkinsVersion(version s))
Just v -> Right v

requestedPluginReader :: Opt.ReadM RequestedPlugin
requestedPluginReader = Opt.maybeReader $ \p -> Just $! case break (== ':') p of
Expand Down
20 changes: 10 additions & 10 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 1 addition & 8 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
description = "jenkinsPlugins2nix";
inputs = {
flake-utils.url = "github:numtide/flake-utils";
nixpkgs.url = "github:NixOS/nixpkgs/21.05";
nixpkgs.url = "github:NixOS/nixpkgs/23.05";
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
Expand All @@ -28,11 +28,4 @@
});
}
);

# packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello;

# defaultPackage.x86_64-linux = self.packages.x86_64-linux.hello;



}
21 changes: 11 additions & 10 deletions jenkinsPlugins2nix.cabal
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: jenkinsPlugins2nix
version: 0.5.0.0
version: 0.5.0.2
synopsis: Generate nix for Jenkins plugins.
description: Generate nix for Jenkins plugins.
homepage: https://github.com/Fuuzetsu/jenkinsPlugins2nix#readme
Expand All @@ -20,15 +20,15 @@ library
Nix.JenkinsPlugins2Nix.Parser
Nix.JenkinsPlugins2Nix.Types
build-depends: base >=4.7 && < 5
, attoparsec >=0.13 && <0.14
, bytestring >=0.10 && <0.11
, attoparsec >=0.13 && <0.15
, bytestring >=0.10 && <0.12
, containers >=0.6 && <0.7
, cryptonite >=0.24 && <0.30
, hnix >=0.6 && <0.15
, cryptonite >=0.24 && <0.31
, hnix >=0.6 && <0.18
, http-conduit >=2.3 && <2.4
, mtl >=2.2 && <2.3
, mtl >=2.2 && <2.4
, prettyprinter >=1.2 && <1.8
, text >=1.2 && <1.3
, text
, zip-archive >=0.4 && <0.5
default-language: Haskell2010
ghc-options: -Wall
Expand All @@ -38,9 +38,9 @@ executable jenkinsPlugins2nix
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall
build-depends: base
, bimap >=0.3 && <0.5
, bimap >=0.3 && <0.6
, jenkinsPlugins2nix
, optparse-applicative >=0.14 && <0.17
, optparse-applicative >=0.14 && <0.18
, prettyprinter-ansi-terminal >=1.1 && <1.2
, text
default-language: Haskell2010
Expand All @@ -53,7 +53,8 @@ test-suite jenkinsPlugins2nix-test
build-depends: base
, containers
, jenkinsPlugins2nix
, tasty-hspec >=1.1 && <1.2
, hspec
, tasty-hspec >=1.1 && <1.3
, text
ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall
default-language: Haskell2010
Expand Down
2 changes: 1 addition & 1 deletion jenkinsPlugins2nix.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
}:
mkDerivation {
pname = "jenkinsPlugins2nix";
version = "0.3.0.1";
version = "0.5.0.1";
src = ./.;
isLibrary = true;
isExecutable = true;
Expand Down
22 changes: 13 additions & 9 deletions src/Nix/JenkinsPlugins2Nix.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ import qualified Crypto.Hash as Hash
import qualified Data.ByteString.Lazy as BSL
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Data.Monoid ((<>))
import qualified Data.Set as Set
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text
import qualified Data.Text.IO as Text
import Data.Text.Prettyprint.Doc (Doc)
import Prettyprinter (Doc)
import qualified Network.HTTP.Simple as HTTP
import qualified Nix.Expr as Nix
import Nix.Expr.Shorthands ((@@))
Expand Down Expand Up @@ -70,11 +70,12 @@ downloadPlugin p = do
-- | Download the given plugin as well as recursively download its dependencies.
downloadPluginsRecursive
:: ResolutionStrategy -- ^ Decide what version of dependencies to pick.
-> PluginResolution -- ^ Wheter to include or skip optional dependencies
-> Map Text RequestedPlugin -- ^ Plugins user requested.
-> Map Text Plugin -- ^ Already downloaded plugins.
-> RequestedPlugin -- ^ Plugin we're going to download.
-> MTL.ExceptT String IO (Map Text Plugin)
downloadPluginsRecursive strategy uPs m p = if Map.member (requested_name p) m
downloadPluginsRecursive strategy presolution uPs m p = if Map.member (requested_name p) m
then return m
else do
-- Adjust the requested plugin based on whether it was
Expand All @@ -90,26 +91,29 @@ downloadPluginsRecursive strategy uPs m p = if Map.member (requested_name p) m
-- It's not a user-specified plugin and we want the latest
-- version per strategy so download the latest one.
Latest -> p { requested_version = Nothing }
-- Use a specific Jenkins version supplied by the strategy.
JenkinsVersion v -> p { requested_version = Just (Text.pack v) }
-- The user has asked for this plugin explicitly so use
-- their possibly-versioned request rather than picking
-- based on versions listed in manifest dependencies.
Just userPlugin -> userPlugin
plugin <- MTL.ExceptT $ downloadPlugin adjustedPlugin
foldM (\m' p' -> downloadPluginsRecursive strategy uPs m' $
foldM (\m' p' -> downloadPluginsRecursive strategy presolution uPs m' $
RequestedPlugin { requested_name = plugin_dependency_name p'
, requested_version = Just $! plugin_dependency_version p'
})
(Map.insert (requested_name p) plugin m)
(plugin_dependencies $ manifest plugin)
(Set.filter (\dep -> plugin_dependency_resolution dep <= presolution)
(plugin_dependencies $ manifest plugin))

-- | Pretty-print nix expression for all the given plugins and their
-- dependencies that the user asked for.
mkExprsFor :: Config
-> IO (Either String (Doc ann))
mkExprsFor (Config { resolution_strategy = st, requested_plugins = ps }) = do
mkExprsFor (Config { resolution_strategy = st, requested_plugins = ps, plugin_resolution = pr }) = do
eplugins <- MTL.runExceptT $ do
let userPlugins = Map.fromList $ map (requested_name &&& id) ps
plugins <- foldM (downloadPluginsRecursive st userPlugins) Map.empty ps
plugins <- foldM (downloadPluginsRecursive st pr userPlugins) Map.empty ps
return $ Map.elems plugins
return $! case eplugins of
Left err -> Left err
Expand All @@ -123,8 +127,8 @@ mkExprsFor (Config { resolution_strategy = st, requested_plugins = ps }) = do
]
False) $
Nix.mkSym "stdenv.mkDerivation" @@ Nix.mkNonRecSet
[ Nix.inherit [ Nix.StaticKey "name"
, Nix.StaticKey "src" ] Nix.nullPos
[ Nix.inherit [ "name"
, "src" ]
, "phases" Nix.$= Nix.mkStr "installPhase"
, "installPhase" Nix.$= Nix.mkStr "cp $src $out"
]
Expand Down
2 changes: 0 additions & 2 deletions src/Nix/JenkinsPlugins2Nix/Parser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ module Nix.JenkinsPlugins2Nix.Parser
import Control.Applicative
import Control.Monad (void)
import qualified Data.Attoparsec.Text as A
import Data.Either (either)
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Data.Monoid ((<>))
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Text (Text)
Expand Down
3 changes: 3 additions & 0 deletions src/Nix/JenkinsPlugins2Nix/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ data ResolutionStrategy =
AsGiven
-- | Always pick latest version of the dependency we're told about.
| Latest
| JenkinsVersion(String)
deriving (Show, Eq, Ord)

-- | Program configuration
Expand All @@ -35,6 +36,8 @@ data Config = Config
resolution_strategy :: !ResolutionStrategy
-- | User-required plugins.
, requested_plugins :: ![RequestedPlugin]
-- | Plugin resolution
, plugin_resolution :: !PluginResolution
} deriving (Show, Eq, Ord)

-- | Plugin that user requested on the command line.
Expand Down
2 changes: 1 addition & 1 deletion test/Nix/JenkinsPlugins2Nix/Tests/Parser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import qualified Data.Set as Set
import qualified Data.Text as Text
import Nix.JenkinsPlugins2Nix.Parser (runParseManifest)
import Nix.JenkinsPlugins2Nix.Types
import qualified Test.Tasty.Hspec as Hspec
import qualified Test.Hspec as Hspec

spec :: Hspec.Spec
spec = Hspec.describe "parser spec" $ do
Expand Down
2 changes: 1 addition & 1 deletion test/Spec.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Main where

import qualified Nix.JenkinsPlugins2Nix.Tests.Parser as Parser
import qualified Test.Tasty.Hspec as Hspec
import qualified Test.Hspec as Hspec

main :: IO ()
main = Hspec.hspec $ do
Expand Down