Jenkins shared library loading dynamically with groovy file under `src/**` - jenkins

I'm constructing a Jenkins pipeline to verify the shared-libs (from Gerrit) automatically, by reuse whatever pipelines we have right now.
the original thoughts should be very simple, which :
#Library( 'shared-libs#master' ) _
// |
// |
// variable instead of hard code
// |
// v
#Library( "shared-libs#${refs_params}" ) _
the libraries structure :
(root)
+- src # Groovy source files
| +- org
| +- jenkins
| +- FooDefinition.groovy # for org.jenkins.FooDefinition
| +- BarDefinition.groovy # for org.jenkins.BarDefinition
| +- ... # for org.jenkins....
| +- virtualization
| +- PodDefinition.groovy # for org.virtualization.PodDefinition
| +- ... # for org.virtualization....
+- vars
| +- foo.groovy # for global 'foo' variable
| +- logger.groovy # for global 'logger' variable
For regular pipeline, I'm using the groovy shared library (pre-setup in Manage Jenkins -> Configure System -> Global Pipeline Libraries) by:
#Library( 'shared-libs#master' ) _
import org.virtualization.PodDefinition
// generate pod
PodDefinition.runWith( ... ) {
// pipeline content
}
make sure the refs/changes/x works in Specify ref specs : +refs/changes/*:refs/remotes/#{remote}/changes/*:
// works by using hard code `refs/changes/x/x/123`
#Library( 'shared-libs#refs/changes/x/x/123' ) _
import org.virtualization.PodDefinition
However, when I using GERRIT_REFSPEC, it dosen't work due to WorkflowScript: #Library value ‘shared-libs#$GERRIT_REFSPEC’ was not a constant either way as below:
#Library( 'shared-libs#${GERRIT_REFSPEC}' ) _
#Library( 'shared-libs#${env.GERRIT_REFSPEC}' ) _
#Library( 'shared-libs#${params.GERRIT_REFSPEC}' ) _
So, I've modified the library usage according from the official document Extending with Shared Libraries to library( "shared-libs#${GERRIT_REFSPEC}" ), the libs clone works, but import org.virtualization.PodDefinition failed :
library( "shared-libs#${GERRIT_REFSPEC}" )
// or
this._ = library( "shared-libs#${GERRIT_REFSPEC}" )
// or
this = library( "shared-libs#${GERRIT_REFSPEC}" )
// or
library( "shared-libs#${GERRIT_REFSPEC}" ) _
import org.virtualization.PodDefinition
// WorkflowScript: 5: unable to resolve class org.virtualization.PodDefinition
// # line 3, column 1.
// import org.virtualization.PodDefinition
// ^
//
// 1 error
So, I've tried:
load path/to/x.grovy
library( "shared-libs#${GERRIT_REFSPEC}" )
node( 'built-in' ) {
load "../${env.JOB_BASE_NAME}#libs/<reivsion>/src/org/jenkins/FooDefinition.groovy"
load "../${env.JOB_BASE_NAME}#libs/<reivsion>/src/org/jenkins/BarDefinition.groovy"
load "../${env.JOB_BASE_NAME}#libs/<reivsion>/src/org/virtualization/PodDefinition.groovy"
}
// --- shows thrid party libs import failure ---
// org.jenkinsci.plugins.workflow.cps.CpsCompilationErrorsException: startup failed:
// Script7.groovy: 3: unable to resolve class com.cwctravel.hudson.plugins.extended_choice_parameter.ExtendedChoiceParameterDefinition
// # line 3, column 1.
// import com.cwctravel.hudson.plugins.extended_choice_parameter.ExtendedChoiceParameterDefinition
// ^
//
// 1 error
def x = library() org.x.x ( get hints from Importing class from git - unable to resolve class ) : it will not exact reuse current pipeline any more, and also dozens of groovy file make difficult of naming
def a = library( "shared-libs#${GERRIT_REFSPEC}" ) org.jenkins.FooDefinition.groovy
def b = library( "shared-libs#${GERRIT_REFSPEC}" ) org.jenkins.BarDefinition.groovy
def c = library( "shared-libs#${GERRIT_REFSPEC}" ) org.jenkins.xxx.groovy
def d = library( "shared-libs#${GERRIT_REFSPEC}" ) org.virtualization.PodDefinition.groovy
def e = library( "shared-libs#${GERRIT_REFSPEC}" ) org.virtualization.xxx.groovy
#Grab :
library( "shared-libs#${GERRIT_REFSPEC}" )
#Grab( 'org.virtualization.PodDefinition' )
#Grab( group='org.virtualization', module='PodDefinition' )
// WorkflowScript: 3: The missing attribute "version" is required in #Grab annotations
// # line 3, column 1.
// #Grab( group='org.virtualization', module='PodType' )
// ^
//
// 1 error
#Grab( group='org.virtualization', module='PodDefinition', version='latset' )
// org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
// General error during conversion: Error grabbing Grapes -- [unresolved dependency: org.virtualization#PodDefinition;latest: not found]
#Grab( group='org.virtualization', module='PodDefinition', version='default' )
// org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
// General error during conversion: Error grabbing Grapes -- [unresolved dependency: org.virtualization#PodDefinition;default: not found]
So, I don't know what I should do next, either "change" "shared-libs#${GERRIT_REFSPEC}" to constant to use #Library(...) _, or using library(...) to import all libs under src/**
BTW, here the way I've tried to "convert" variable to constant:
Object.metaclass.SHARED_LIBS = "shared-libs#${GERRIT_REFSPEC}"
#Library( SHARED_LIBS ) _
// or
class SHARED_LIBS {
final String REFSPEC = "shared-libs#${GERRIT_REFSPEC}"
}
#Library( SHARED_LIBS.REFSPEC ) _
// or
import groovy.transform.Field
#Field final String SHARED_LIBS = "shared-libs#${GERRIT_REFSPEC}"
#Library( SHARED_LIBS ) _
// or
def bindings = new Binding()
bindings.setVariable("SHARED_LIBS", "shared-libs#${GERRIT_REFSPEC}")
#Library( SHARED_LIBS ) _
// or
withEnv([ 'SHARED_LIBS=shared-libs#${GERRIT_REFSPEC}' ]) {
#Library( SHARED_LIBS ) _
}

You can dynamically load the library at any point of your groovy file and use the full class name to use the function. Maybe this is something that could help you.
def myLib = dsl.library 'my-shared-lib#<SHA>'
myLib.net.vy.a.v1.Sonarqube.call(dsl, parameters)
Here net.vy.a.v1.Sonarqube is the actual package. dsl is an object of Script

Related

Pattern Matching does not allow me to change values

so I am currently working on a new programming language tr-lang
and I am currently in the process of writing the parser of the language
this piece of code is where the bug lies
BlockToken::İse(bip) => {
let ise = &mut parsed[bip]; // Access method 1
match ise.typ {
TokenType::İse ( mut yoksa ) => {
yoksa = Some(ip);
},
TokenType::Yoksa ( mut tp ) => {
tp = Some(ip);
},
_ => unreachable!(),
}
ip + 1
},
BlockToken::İken(bip) => {
let iken = parsed.get_mut(bip).unwrap(); // Trying other access methods
match iken.typ {
TokenType::İken ( mut yoksa ) => {
yoksa = Some(ip + 1);
},
_ => unreachable!(),
}
bip
},
_ => unimplemented!(),
};
and this is part of the code that parses and produces an executable program
and it gives a few warnings but i think the problem lies in these ones:
warning: variable `yoksa` is assigned to, but never used
--> src/parser/parser.rs:121:54
|
121 | ... TokenType::İse ( mut yoksa ) => {
| ^^^^^
|
= note: consider using `_yoksa` instead
warning: value assigned to `yoksa` is never read
--> src/parser/parser.rs:122:37
|
122 | ... yoksa = Some(ip);
| ^^^^^
|
= help: maybe it is overwritten before being read?
warning: variable `tp` is assigned to, but never used
--> src/parser/parser.rs:124:56
|
124 | ... TokenType::Yoksa ( mut tp ) => {
| ^^
|
= note: consider using `_tp` instead
warning: value assigned to `tp` is never read
--> src/parser/parser.rs:125:37
|
125 | ... tp = Some(ip);
| ^^
|
= help: maybe it is overwritten before being read?
warning: variable `yoksa` is assigned to, but never used
--> src/parser/parser.rs:134:55
|
134 | ... TokenType::İken ( mut yoksa ) => {
| ^^^^^
|
= note: consider using `_yoksa` instead
warning: value assigned to `yoksa` is never read
--> src/parser/parser.rs:135:37
|
135 | ... yoksa = Some(ip + 1);
| ^^^^^
|
= help: maybe it is overwritten before being read?
as you can see for some reason even though i pattern-match like usual when i try to set the value to something else it treats the variables as different
and instead of changing the value of yoksa/tp the end result just does not change anything
i tried changing the way i access ise/iken however it didn't change anything
i also tried using if let instead of match
it doesn't change the value of ise.typ.yoksa or ise.typ.tp
for extra info BlockToken is this enum
enum BlockToken {
İse(usize),
İken(usize),
İkiNoktaNokta(usize),
}
Token is this struct
struct Token {
pub typ: TokenType,
pub line: usize,
pub col: usize,
}
what i want from here is the ability to change the contents of the enum structs İse, İken and Yoksa
it can be unsafe although a safe method is preferred
Use Option::replace to fit the new value into the mutable option:
yoksa.replace(ip + 1);
Also you probably want a mutable reference:
TokenType::İken(ref mut yoksa)
I think you need to match on a mutable reference when matching otherwise you are just creating a local variable and mutating that.
For example this code:
#[derive(Debug)]
enum Blah {
A(u64),
}
mod test {
use super::Blah;
#[test]
fn test_match() {
let mut a = Blah::A(23);
println!("{:?}", a);
match a {
Blah::A(ref mut x) => *x = 5,
}
println!("{:?}", a);
}
}
will output:
running 1 test
A(23)
A(5)
If you run it with cargo test -- --nocapture.

Purescript compiles but js throws error : component.initialState is not a function

I'm building a simple video player component using purescript-halogen. The component is supposed to show a blank div with only an input button for the user to select a local file which will then act as a source URL for the video element.
I completed a working model in plain javascript and wanted to port it to purescript/halogen. I got the purescript version to compile but the web console gives me an error message Uncaught TypeError: component.initialState is not a function and points me to this MDN reference.
This would suggest an issue with how I defined my initialState function but it's fairly standard:
component :: forall q i o m. MonadAff m => H.Component q i o m
component =
H.mkComponent
{ initialState
, render
, eval: H.mkEval $ H.defaultEval { handleAction = handleAction }
}
type State =
{ videoUrl :: Maybe String }
initialState :: forall i. i -> State
initialState _ =
{ videoUrl : Nothing
}
Is it possible that the function is called at the wrong time during its lifecycle, hence making it undefined?
The code for the component is hosted on this Github gist. And I've been following this Github issue as reference.
My package.json :
"private": true,
"devDependencies": {
"parcel": "1.12.3",
"purescript": "^0.14.0",
"spago": "^0.19.1"
},
"scripts": {
"build": "spago build",
"test": "spago test",
"serve": "parcel dev/index.html --open",
"build-prod": "mkdir -p prod && cp dev/index.html prod/ && rm -rf dist && spago bundle-app --to prod/index.js && parcel build prod/index.html"
},
"dependencies": {
"node": "^15.12.0"
}
}
I compiled using purescript v0.14.0, spago v0.20.0, node v16.3.0 and tested on Firefox v89.0 in Ubuntu 20.04.2 LTS.
Seems the bug is from a pesky line in the code:
HH.input
[ ...
, HP.value "Select file"
...]
According to MDN, the value property of an input element is used to hold the path to the selected files. Therefore, setting it during element creation is not a well defined action.
The final code (which runs as expected) is:
module App.Video (component) where
import DOM.HTML.Indexed.InputAcceptType (InputAcceptType, InputAcceptTypeAtom(..))
import Data.Foldable (traverse_)
import Data.Maybe (Maybe(..))
import Data.MediaType (MediaType(..))
import Data.Traversable (for_)
import Effect.Aff.Class (class MonadAff)
import Halogen as H
import Halogen.HTML as HH
import Halogen.HTML.Events as HE
import Halogen.HTML.Properties as HP
import Prelude (Unit, bind, const, discard, pure, unit, ($), (=<<), (>>=))
import Web.Event.Event as Event
import Web.File.File as File
import Web.File.FileList as FileList
import Web.File.FileReader.Aff as FileReaderAff
import Web.HTML.HTMLInputElement as InputElement
data Action = HandleFileUpload Event.Event
type State =
{ videoUrl :: Maybe String }
component :: forall q i o m. MonadAff m => H.Component q i o m
component =
H.mkComponent
{ initialState
, render
, eval: H.mkEval $ H.defaultEval { handleAction = handleAction }
}
initialState :: forall input. input -> State
initialState inp =
{ videoUrl : Nothing
}
render :: forall m slots. State -> H.ComponentHTML Action slots m
render state =
case state.videoUrl of
Nothing -> blank_player
Just url -> video_player url
supported_formats :: InputAcceptType
supported_formats =
HP.InputAcceptType
[ AcceptMediaType (MediaType "video/mp4")
, AcceptMediaType (MediaType "video/webm")
]
blank_player :: forall w. HH.HTML w Action
blank_player =
HH.div_
[ HH.span_ [HH.text "Choose file to upload"]
, HH.input
[ HP.type_ HP.InputFile
, HP.accept supported_formats
, HE.onChange HandleFileUpload
]
]
video_player :: forall w i. String -> HH.HTML w i
video_player url =
HH.div_ [
HH.video [HP.src url] []
]
handleAction :: forall m slots o. MonadAff m => Action -> H.HalogenM State Action slots o m Unit
handleAction = case _ of
HandleFileUpload ev → do
traverse_ handleFileUpload (InputElement.fromEventTarget =<< Event.target ev)
handleFileUpload :: forall m slots o. MonadAff m => InputElement.HTMLInputElement -> H.HalogenM State Action slots o m Unit
handleFileUpload inputEl = do
H.liftEffect (InputElement.files inputEl) >>= traverse_ \files ->
for_ (FileList.item 0 files) \file → do
video_url ← H.liftAff $ FileReaderAff.readAsDataURL (File.toBlob file)
H.modify_ (const { videoUrl : Just video_url})
pure unit

value is a function while a set was expected while evaluating 'outputs'

I'm getting the above error when attempting to check a flake; I'm trying to use flake-compat on a non-NixOS system for compatibility with home-manager.
This is the flake that's causing the trace below:
error: value is a function while a set was expected
at /nix/store/l22dazwy8cgxdvndhq45br310nap92x3-source/etc/nixos/flake.nix:167:136:
166|
167| outputs = inputs#{ self, nix, nixpkgs, flake-utils, flake-compat, ... }: with builtins; with nixpkgs.lib; with flake-utils.lib; let
|
^
168|
… while evaluating 'outputs'
at /nix/store/l22dazwy8cgxdvndhq45br310nap92x3-source/etc/nixos/flake.nix:167:15:
166|
167| outputs = inputs#{ self, nix, nixpkgs, flake-utils, flake-compat, ... }: with builtins; with nixpkgs.lib; with flake-utils.lib; let
| ^
168|
… from call site
at «string»:45:21:
44|
45| outputs = flake.outputs (inputs // { self = result; });
| ^
46|
… while evaluating anonymous lambda
at «string»:10:13:
9| builtins.mapAttrs
10| (key: node:
| ^
11| let
… from call site
… while evaluating the attribute 'root'
… while evaluating anonymous lambda
at «string»:2:23:
1|
2| lockFileStr: rootSrc: rootSubdir:
| ^
3|
… from call site
Unfortunately, I cannot provide a minimal reproducible example as I do not know from where in the flake this error is originating.
Turns out, my lib value was actually a function; unfortunately, since nix flakes is still unstable, it didn't quite show where this was happening.

DotCover not working

I am using DotCoverNUnit in FAKE for code coverage .
It is giving some error
`Starting Target: TestCoverage (==> BuildUnitTest)
./Buildtools/dotCover/dotCover.exe "cover" "/TargetExecutable=./Libs/NUnit.Runners.2.6.3/tools/nunit-console.exe" "/TargetArguments="-nologo" "-labels" "D:\Project\build\project.UnitTest.dll" "-xml:D:\Project\TestResult.xml"" "/Output=./test/NUnitDotCover.xml"
./Buildtools/dotCover/dotCover.exe "cover" "/TargetExecutable=./Libs/NUnit.Runners.2.6.3/tools/nunit-console.exe" "/TargetArguments="-nologo" "-labels" "D:\Project\build\Project.UnitTest.dll" "-xml:D:\Project\TestResult.xml"" "/Output=./test/NUnitDotCover.xml"
JetBrains dotCover Console Runner v2.6.608.684. Copyright (c) 2009–2017 JetBrains s.r.o. All rights reserved.
**Command 'cover' doesn't support 4 unnamed arguments**
Type 'dotCover help' for usage.
Running build failed.
Error:
System.Exception: Error running ./Buildtools/dotCover/dotCover.exe with exitcode -1
at Fake.DotCover.buildParamsAndExecute#124-6.Invoke(String message)
at Fake.DotCover.buildParamsAndExecute[a](a parameters, FSharpFunc2 buildArguments,String toolPath, String workingDir, Boolean failBuild)
at Fake.DotCover.DotCoverNUnit(FSharpFunc 2 setDotCoverParams, FSharpFunc2 setNUnitParams, IEnumerable 1 assemblies)
at FSI_0005.Build.clo#98-8.Invoke(Unit _arg6) in D:\ICIS API develop\icis-api\build.fsx:line 99`
I am not able to figure out the problem out there in this code , I was able to run this code earlier but right now it is not wroking .
Here is the code that I am using for DotCover :
Target "TestCoverage" (fun _ ->
!! (buildDir ## "/Project.UnitTest.dll")
|> DotCoverNUnit
(fun p -> { p with TargetExecutable ="nunit-console.exe"
Output ="NUnitDotCover.xml"
ToolPath = "dotCover.exe"
ErrorLevel = DontFailBuild
Filters = filters })
(fun nunitOptions ->
{ nunitOptions with DisableShadowCopy = true })
tracefn "##teamcity[importData type='dotNetCoverage' tool='dotcover' path='%s']" (testDir ## "NUnitDotCover.xml")
)

Spock does not execute when clause

One of my spock tests is skipping the when clause and moving right to the then clause.
#Unroll
void "test refresh metadata with #consumerNames"() {
setup:
consumerNames.each {
new CredentialConsumer(name: it).save(validate: false)
}
when:
service.refreshMetadata()
then:
consumerNames.each { consumerName ->
Metadata metadata = new Metadata(content: "Metadata for $consumerName")
ConsumerDefinition consumerDefinition = new ConsumerDefinition(name: consumerName, metadata: metadata)
1 * mockApplicationLibraryService.fetchConsumerDefinition(consumerName) >> consumerDefinition
assert CredentialConsumer.findByName(consumerName)?.metadata?.content == metadata.content
}
where:
consumerNames | _
["bacon"] | _
["bacon", "eggs"] | _
}
I get the following results...
Condition not satisfied:
CredentialConsumer.findByName(consumerName)?.metadata?.content == metadata.content
| | | | | | |
| bacon null null | | Metadata for bacon
| | com.datapriviasoftware.completesso.configuration.Metadata#487cd177
| false
com.datapriviasoftware.completesso.CredentialConsumer : 1
Expected :Metadata for bacon
Actual :null
When I step through it with the debugger, it executes the setup clause, skips the when clause, and immediately executes the then clause.
So, I knew that Spock uses AST transformations to process mocks in the then clause before it executes the when clause. When I thought through it, I realized that processing the mocks in the then clause required the entire each loop to execute, so I needed to separate the explicit assertion from the mock definition.
This works...
#Unroll
void "test refresh metadata with #consumerNames"() {
setup:
consumerNames.each {
new CredentialConsumer(name: it).save(validate: false)
}
when:
service.refreshMetadata()
then:
consumerNames.each { consumerName ->
Metadata metadata = new Metadata(content: "Metadata for $consumerName")
ConsumerDefinition consumerDefinition = new ConsumerDefinition(name: consumerName, metadata: metadata)
1 * mockApplicationLibraryService.fetchConsumerDefinition(consumerName) >> consumerDefinition
}
and:
consumerNames.each { consumerName ->
assert CredentialConsumer.findByName(consumerName)?.metadata?.content == "Metadata for $consumerName"
}
where:
consumerNames | _
["bacon"] | _
["bacon", "eggs"] | _
}

Resources