Invoking plugins in declarative Jenkins pipeline - jenkins-declarative-pipeline

Trying to port the following syntax from scripted pipeline to declarative pipeline and it is not working. Obviously, I am getting error message that step is not a valid keyword in declarative Jenkinsfile. Could not find any documentation to fix the issue. Any help?
stage("publish to s3") {
step([
$class: 'S3BucketPublisher',
entries: [[
sourceFile: 'mybinaryFile',
bucket: 'GoBinaries',
selectedRegion: 'eu-west-1',
noUploadOnFailure: true,
managedArtifacts: true,
flatten: true,
showDirectlyInBrowser: true,
keepForever: true,
]],
profileName: 'myprofile',
dontWaitForConcurrentBuildCompletion: false,
])
}

This should work as long as the code is in a script block. This is the standard way to run scripted pipeline code within a declarative pipeline.
stage("publish to s3") {
steps {
script {
step([
$class: 'S3BucketPublisher',
entries: [[
sourceFile: 'mybinaryFile',
bucket: 'GoBinaries',
selectedRegion: 'eu-west-1',
noUploadOnFailure: true,
managedArtifacts: true,
flatten: true,
showDirectlyInBrowser: true,
keepForever: true,
]],
profileName: 'myprofile',
dontWaitForConcurrentBuildCompletion: false,
])
}
}
}

In declarative pipelines, stage should have steps block
stages{
stage('someName'){
steps {
//s3bucketpublisher step
}
}
}
Reference: Jenkins documentation
The stage directive goes in the stages section and should contain a steps section, an optional agent section, or other stage-specific directives.

Related

Jenkins: pipelineJob with SCM and static script

I would love to use Jenkins job-dsl pipelineJob for creating a build job for a GitHub repository with a static (and centrally maintained) pipeline.
But looking at the documentation (https://jenkinsci.github.io/job-dsl-plugin/#path/javaposse.jobdsl.dsl.DslFactory.pipelineJob-definition) I can either create a cps with a static script or cpsScm with a SCM and a reference to the Jenkinsfile in the repository.
The requirement for having SCM defined comes from the gitParameter plugin, which I want to use for picking a git revision.
Is there a way how I can use a static script for the pipeline together with the SCM?
Update:
This is concretely what I would like to do:
defining a pipeline job
using a git Parameter to select the revision
declare the particular script inline
pipelineJob("test") {
parameters {
gitParameter {
name('revision')
type('PT_BRANCH_TAG')
defaultValue('origin/master')
selectedValue('DEFAULT')
description('')
branch('')
branchFilter('')
tagFilter('')
useRepository('')
quickFilterEnabled(true)
}
}
logRotator {
numToKeep(50)
}
definition {
cpsScm {
scm {
git {
remote {
github("<my-repo>")
credentials('github')
}
branch('$revision')
}
}
script("""
#Library(value='pipeline-lib#master', changelog=false) _
myPipeline projectName: 'test-name'
""")
}
}
}
Pipeline as code has incorporated many functions of jobs-dsl, which is probably why some of the fine tuning capabilities are missing from jobs-dsl's pipelineJob. The examples given on the the Git Parameter plugin page are actually in the pipelines, which could be be the script portion of the cps portion of the jobs-dsl definition. The code quoted in the question could be converted to:
pipelineJob("test") {
logRotator {
numToKeep(50)
}
definition {
cps {
script('''
pipeline {
agent any
libraries {
lib("pipeline-lib#master")
}
parameters {
gitParameter name: 'revision',
type: 'PT_BRANCH_TAG',
defaultValue: 'origin/master',
selectedValue: 'DEFAULT',
description: '',
branch: '',
branchFilter: '',
tagFilter: '',
useRepository: '',
quickFilterEnabled: true
}
stages {
stage('Build') {
steps {
git branch: "${revision}",
url: <myrepo>,
credentialsId: 'github'
// not familiar with what the next line does, assuming it's a pipeline step
myPipeline projectName: 'test-name'
}
}
}
''')
}
}
}
This is for a declarative pipeline. There is also an example of scripted pipeline on the git parameter plugin page.

Babel giving Plugin/Preset did not return an object after adding #babel/helper-annotate-as-pure

I've recently added #babel/helper-annotate-as-pure to my list of babel plugins:
require('babel-plugin-macros'),
require('#babel/helper-annotate-as-pure').default,
require('babel-plugin-dev-expression'),
[
require('#babel/plugin-proposal-class-properties').default,
{
loose: true,
},
],
[require('#babel/plugin-proposal-decorators').default, { legacy: true }],
require('#babel/plugin-proposal-numeric-separator').default,
[
require('#babel/plugin-transform-runtime').default,
{
corejs: false,
helpers: true,
version: require('#babel/runtime/package.json').version,
regenerator: true,
useESModules: moduleFormat === 'esm',
} as RuntimeOptions,
],
require('#babel/plugin-syntax-dynamic-import').default,
require('#babel/plugin-proposal-optional-chaining').default,
require('#babel/plugin-proposal-nullish-coalescing-operator').default,
isDevelopment && require.resolve('react-refresh/babel'),
I previously used 'babel-plugin-annotate-pure-calls' but after adding the plugin I continually get the same error at different points:
Plugin/Preset did not return an object
If I comment out the plugin, everything works
#babel/helper-annotate-as-pure is a helper utility module that is part of Babel itself, it is not a plugin, so it cannot be used in the plugins array. All plugins in the #babel namespace start with plugin- in their name.
You'd have to see if babel-plugin-annotate-pure-calls, the original plugin you used, works properly.

Protractor W3C capability

I am using Protractor with Selenoid. I need to use the dockerized Windows images so that I can test Internet Explorer and Edge from Linux boxes.
I was able to make it work from curl by running:
curl -X POST http://127.0.0.1:4444/wd/hub/session -d '{"capabilities":{"browserName":"MicrosoftEdge","count":1,"alwaysMatch":{"browserName":"MicrosoftEdge","selenoid:options":{"enableVNC":true,"enableVideo":false,"enableLog":true,"logName":"edge-18.0.log"}}}}'
My protractor config looks like:
multiCapabilities: [
{
browserName: "MicrosoftEdge",
"alwaysMatch": {
browserName: "MicrosoftEdge",
"selenoid:options": {
enableVNC: true,
enableVideo: false,
enableLog: true,
logName: "edge-18.0.log"
}
}
}
]
But protractor send it over the selenoid server like this:
{
"desiredCapabilities": {
"browserName": "MicrosoftEdge",
"count": 1,
"alwaysMatch": {
"browserName": "MicrosoftEdge",
"selenoid:options": {
"enableVNC": true,
"enableVideo": false,
"enableLog": true,
"logName": "edge-18.0.log"
}
}
}
}
The issue is that desiredCapabilities should just be 'capabilities`. I have been looking everywhere trying to find out where is that created so that I can created some sort of flag to be able to switch it.
Any ideas?
Using Protractor 6.0 solve my issue, but broke all my tests.
I was able to keep using 5.4.1 by patching the selenium-webdriver package. Looking at the way Protractor 6 did it, I did it to Protractor 5.4.1:
I edited the file located at node_modules/selenium-webdriver/lib/webdriver.js and added the following:
// Capability names that are defined in the W3C spec.
const W3C_CAPABILITY_NAMES = new Set([
'acceptInsecureCerts',
'browserName',
'browserVersion',
'platformName',
'pageLoadStrategy',
'proxy',
'setWindowRect',
'timeouts',
'unhandledPromptBehavior',
]);
Then in the same file I modify the static createSession(executor, capabilities, opt_flow, opt_onQuit) method to add the following:
let W3CCaps = new Capabilities(capabilities);
for (let k of W3CCaps.keys()) {
// Any key containing a colon is a vendor-prefixed capability.
if (!(W3C_CAPABILITY_NAMES.has(k) || k.indexOf(':') >= 0)) {
W3CCaps.delete(k);
}
}
cmd.setParameter('capabilities', W3CCaps);
After all those changes the request getting to Selenoid is like this:
{
"desiredCapabilities": {
"browserName": "MicrosoftEdge",
"version": "18.0",
"enableVNC": true,
"enableVideo": false,
"count": 1
},
"capabilities": {
"browserName": "MicrosoftEdge"
}
}
And my Protractor 5 config looks like this:
multiCapabilities: [{
browserName: 'MicrosoftEdge',
version: '18.0',
enableVNC: true,
enableVideo: false
}]
Note:
So that I don't have to worry about refresh installs or updates I use the package patch-package (https://github.com/ds300/patch-package) to create a patch that is applied when any of those events happen. Here is a great video explaining how to use that package https://www.youtube.com/watch?v=zBPcVGr6XPk

Automating webrtc Screenshare

I am trying to automate screen share workflow in a webRTC application.
I need to bypass the screenshare prompt. I am using --use-fake-ui-for-media-stream, use-fake-device-for-media-stream and --auto-select-desktop-capture-source flags in my config file.
Doesn't seem work.
Here is my config file :
exports.makeDefaultCapabilities = function(that) {
return {
browserName: 'chrome',
chromeOptions: {
// disable Password manager popup
prefs: {
credentials_enable_service: false,
download: {
prompt_for_download: false,
directory_upgrade: true,
default_directory: '~/Downloads'
}
},
args: [
'disable-infobars=true',
'--use-fake-device-for-media-stream',
'--use-fake-ui-for-media-stream',
'--auto-select-desktop-capture-source = "Entire screen"'
]
},
loggingPrefs: {
driver: 'WARNING',
server: 'WARNING',
browser: 'INFO'
},
I tried flipping between using fake-device and fake-ui flags and they do not get along if i understand correctly.
I do not understand what is missing here. Appreciate your inputs.
Thanks
https://bugs.chromium.org/p/chromium/issues/detail?id=459532#c22 explains why those flags don't play well together and how to workaround it by creating a custom profile that has already accepted getUserMedia permissions which makes the use-fake-ui-for-media-stream flag unnecessary.
See here for some code.

How do I parameterize the baseUrl property of the protractor config file

I need to run my protractor tests in different contexts with different baseUrls in the config files. I don't want to use separate config files for each situation since that is more difficult to maintain. Rather, I want to pass the base url in as a command line parameter. Here is what I have tried so far:
The protractor.conf.js:
exports.config = {
onPrepare : {
...
exports.config.baseUrl = browser.params.baseUrl;
...
}
}
And to invoke protractor:
protractor protractor.conf.js --params.baseUrl 'http://some.server.com'
This does not work since it seems like the browser instance is already configured before onPrepare is called.
Similarly, I have tried this:
exports.config = {
baseUrl : browser.params.baseUrl
}
But this doesn't work either since it seems like the browser instance is not available when the config is being generated.
It looks like I can use standard node process.argv to access all command line arguments, but that seems to be going against the spirit of protractor.
What is the best way for me to do what I need to do?
Seems like this is already possible, but the documentation is spotty in this area. Looking at the code, however, protractor does support a number of seemingly undocumented command line arguments.
So, running something like this will work:
protractor --baseUrl='http://some.server.com' my.conf.js
The other option is to use gruntfile.js and have it call the protractor config file.
//gruntfile.js
module.exports = function (grunt) {
grunt.registerTask("default", "", function () {
});
//Configure main project settings
grunt.initConfig({
//Basic settings and infor about our plugins
pkg: grunt.file.readJSON('package.json'),
//Name of plugin
cssmin: {
},
protractor: {
options: {
configFile: "conf.js", // Default config file
keepAlive: true, // If false, the grunt process stops when the test fails.
noColor: false, // If true, protractor will not use colors in its output.
args: {
baseUrl: grunt.option('baseUrl') || 'http://localhost:6034/'
}
},
your_target: { // Grunt requires at least one target to run so you can simply put 'all: {}' here too.
options: {
configFile: "conf.js", // Target-specific config file
args: {
baseUrl: grunt.option('baseUrl') || 'http://localhost:63634/'
}
}
},
},
//uglify
uglify: {
}
});
//Load the plugin
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-protractor-runner');
//Do the Task
grunt.registerTask('default', ['cssmin']);
};
the Protractor config file: conf.js
exports.config = {
directConnect: true,
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome',
'chromeOptions': {
args: ['--no-sandbox']
}
},
chromeOnly: true,
// Framework to use. Jasmine is recommended.
framework: 'jasmine',
// Spec patterns are relative to the current working directory when
// protractor is called.
specs: ['specs/*/*_spec.js'],
suites : {
abcIdentity : 'specs/abcIdentity/*_spec.js' //picks up all the _spec.js files
},
params: {
UserName: 'abc#test.com',
Password: '123'
},
// Options to be passed to Jasmine.
jasmineNodeOpts: {
defaultTimeoutInterval: 30000,
includeStackTrace: true
},
onPrepare: function () {
browser.driver.manage().window().maximize();
if (process.env.TEAMCITY_VERSION) {
var jasmineReporters = require('jasmine-reporters');
jasmine.getEnv().addReporter(new jasmineReporters.TeamCityReporter());
}
}
};
//To run with default url http://localhost:6034
grunt protractor
//To run with any other url
grunt protractor --baseUrl:"http://dev.abc.com/"
I know, old one. but if anyone is still looking for a way to define a url based on capability (I had to do this because Ionic 5 will run in browser on port 8100, but in the app - unchangable - without port declaration on port 80, I use Appium)
add a baseUrl parameter inside your capability declaration.
{
browserName: 'chrome',
baseUrl: 'http://localhost:8100' //not required but as example
}
{
...
app: 'path to app.apk',
baseUrl: 'http://localhost'
...
}
and then configure your onPrepare method as follows.
async onPrepare() {
const config = await browser.getProcessedConfig();
if(config.capabilities.hasOwnProperty('baseUrl')) {
browser.baseUrl = config.capabilities.baseUrl;
}
}
OnPrepare runs for each capability you define in your multiCapabilities array. the getProcessedConfig returns the config as you defined it, with the addition of the current capability. Since that method returns a promise, I use async/await for readability.
This way, you can have multiple capabilities running, with each different a different host.
Base url should be declared baseUrl: "", in config.ts
I am using cucumber hooks and the below code is added in hooks file to pass the required url based upon the environments
if(browser.params.baseUrl==="QA"){
console.log("Hello QA")
await browser.get("https://www.google.com");
} else {
console.log("Hi Dev")
await browser.get("https://www.gmail.com");
}
run the tests using protractor command
protractor --params.baseUrl 'QA' typeScript/config/config.js --cucumberOpts.tags="#CucumberScenario"