How to attach tests reports to slack notification through Fastlane - gitlab-ci

I can't find a solution for a pretty trivial (IMHO) setup.
In my iOS application I use Fastlane to run tests through a scan command.
This generates a pretty useful xpretty tests report HTML file.
I would like to send a slack notification at the end of the tests with attached link to my generated HTML tests results file. I am using a Gitlab with a runner installed on a minimac to run my CI pipeline.
So far I cannot find a solution to this setup. Can someone point me to the right direction ?

I hope you already found a solution in the latest 2 years. As pointed in the comments, you can use the webhooks of Slack. And then you can run the slack command in your steps like this:
platform :ios do
before_all do
ENV["SLACK_URL"] = "https://hooks.slack.com/services/T0A6LPW3A/B5B2SBA13/etc..."
desc "Tests, builds and uploads to iTunesConnect"
lane :appstore do
ENV["LANE_NAME"] = "Flicker"
ENV["BUNDLE_ID"] = "com.epri.fem"
ENV["SCHEME_NAME"] = ENV["LANE_NAME"]
ENV["TEAM_NAME"] = "Electric Power Research Institute"
runConfiguration()
end
def runConfiguration()
slack(
message: ENV["LANE_NAME"] + ") Incoming from branch " + sh("git rev-parse --abbrev-ref HEAD") + " - " + sh("git rev-parse HEAD"),
slack_url: ENV["SLACK_URL"]
)
sigh(team_name: ENV["TEAM_NAME"],
app_identifier: ENV["BUNDLE_ID"],
skip_certificate_verification: true) # Update Provisioing Profiles / Code Signing
slack(
message: "Finished updating provisioing profiles",
default_payloads: [],
slack_url: ENV["SLACK_URL"]
)
scan(
scheme: ENV["SCHEME_NAME"],
slack_url: ENV["SLACK_URL"]
) # run tests
gym(scheme: ENV["SCHEME_NAME"],
clean: true) # build the app
slack(
message: "Finished building app",
default_payloads: [],
slack_url: ENV["SLACK_URL"]
)
pilot(skip_submission: true,
team_name: ENV["TEAM_NAME"]) #upload to test flight
slack(
message: "Finished archiving and uploading to iTunesConnect",
default_payloads: [],
slack_url: ENV["SLACK_URL"]
)
end
error do |lane, exception|
slack(
message: exception.message,
default_payloads: [],
slack_url: ENV["SLACK_URL"]
)
end

Related

CDK for setting ALB controller in EKS UPGRADE FAILED: another operation

I have an application that needs to be deployed on EKS, and I'm having trouble setting up an ingress ALB.
I am using the following as a sample for how this should be set up.
https://github.com/aws-samples/nexus-oss-on-aws/blob/d3a092d72041b65ca1c09d174818b513594d3e11/src/lib/sonatype-nexus3-stack.ts#L207-L242
It's in TypeScript and I'm converting it to Python. My code is as below.
from aws_cdk import (
Stack,
aws_eks as eks,
aws_ec2 as ec2,
aws_iam as iam,
Duration
)
from constructs import Construct
class TestStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
vpc = ec2.Vpc(self, "test-vpc",
vpc_name="test-vpc",
cidr="10.0.0.0/16"
)
eks_role = iam.Role(
self, 'test-eks-role',
role_name = 'test-eks-role',
assumed_by=iam.CompositePrincipal(
iam.ServicePrincipal('eks.amazonaws.com')
),
managed_policies=[iam.ManagedPolicy.from_aws_managed_policy_name('AmazonEKSClusterPolicy')],
)
cluster = eks.Cluster(
self, "test-cluster",
cluster_name="test-cluster",
masters_role=eks_role,
version=eks.KubernetesVersion.V1_21,
vpc=vpc,
vpc_subnets=[ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE_WITH_NAT)]
)
alb_service_account = cluster.add_service_account(
'test-cluster-service-account',
name='test-cluster-service-account'
)
import requests
alb_controller_url = 'https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.2.0/docs/install/iam_policy.json'
policy_json = requests.get(url=alb_controller_url).json()
for statement in policy_json['Statement']:
alb_service_account.add_to_principal_policy(iam.PolicyStatement.from_json(statement))
cluster.add_helm_chart(
'aws-load-balancer-controller-helm-chart',
chart='aws-load-balancer-controller',
repository='https://aws.github.io/eks-charts',
release='aws-load-balancer-controller',
version='1.4.1',
wait=True,
timeout=Duration.minutes(15),
values={
"clusterName": cluster.cluster_name,
"image": {
"repository": "602401143452.dkr.ecr.ap-southeast-2.amazonaws.com/amazon/aws-load-balancer-controller:v2.4.1",
},
"serviceAccount": {
"create": False,
"name": alb_service_account.service_account_name,
},
},
)
Right now I'm getting the following cryptic error message.
Received response status [FAILED] from custom resource. Message returned: Error: b'Error: UPGRADE FAILED: another operation (i
nstall/upgrade/rollback) is in progress\n'
Any advice would be greatly appreciated!
There is an AlbController construct available in the CDK, you could try with that and see if that works for you.
I am actually using the construct myself but am facing the same error message. There is this GitHub issue regarding the Helm error itself, however the rollback solution mentioned there is not applicable for me, there appears to be no state of the Helm release despite the error. I have raised this as an issue on the CDK repo.

How to add cookie to Selenium IDE test running in grid via selenium-side-runner for Zalenium messages

I've recorded a test using Selenium IDE and am submitting the generated .side file to selenium-side-runner to run on a Selenium Grid built using Zalenium. Is it possible to run a command that calls driver.manage().addCookie() from the test that was submitted to selenium-side-runner? I want to do this to send messages back to Zalenium with test progress and status
I added a command executeScript to the Selenium IDE editor with a target of driver.manage().addCookie({name: 'test', value: 'test'})
I see that the command that selenium-side-runner generated in commons.js was
await driver.executeScript(`driver.manage().addCookie({name:'test', value: 'test'});`);
Doing this causes the browser to report an error JavascriptError: javascript error: driver is not defined
I think what I need is the code to be generated without the driver.executeScript wrapper. Is there a way to accomplish this without exporting my Selenium IDE test to NUnit?
I was able to make this functionality work by crudely modifying the selenium-side-runner package on my Windows dev machine
In file ~\node_modules\selenium-side-runner\node_modules\selianize\dist\selianize.cjs.js
Change
function generateScript(script, isExpression = false) {
return `await driver.executeScript(\`${isExpression ? `return (${script.script})` : script.script}\`${script.argv.length ? ',' : ''}${script.argv.map(n => `vars["${n}"]`).join(',')});`;
}
to
function generateScript(script, isExpression = false) {
if (script.script.indexOf('zalenium') > -1)
{
return script.script;
} else
{
return `await driver.executeScript(\`${isExpression ? `return (${script.script})` : script.script}\`${script.argv.length ? ',' : ''}${script.argv.map(n => `vars["${n}"]`).join(',')});`;
}
}
Now when running a test with selenium-side-runner, calling "executeScript" with any value that contains zalenium will generate the command verbatim in the test script

How to ask for a user input from a remote server with SSHKit?

I need to ask a user input from a ruby script on a remote server. I managed to perform it with bash with the following code
class ConfirmHandler
def on_data(command, stream_name, data, channel)
puts "data received: #{data}"
if data.to_s =~ /\?$/
prompt = Net::SSH::Prompt.default.start(type: 'confirm')
response = prompt.ask "Please enter your response (y/n)"
channel.send_data "#{response}\n"
end
end
end
require 'sshkit'
require 'sshkit/dsl'
include SSHKit::DSL
on '<ssh-server-name>' do |host|
cmd = <<-CMD
echo 'Do something?';
read response;
echo response=$response
CMD
capture(cmd.squish , interaction_handler: ConfirmHandler.new)
end
When I run this script on my local machine I see
data received: Do something?
Please enter your response (y/n)
data received: response=y
I try to wrap the bash CMD code into a ruby script:
on '<ssh-server-name>' do |host|
cmd = <<-CMD
ruby -e "
puts 'Do something?';
require 'open3';
response = Open3.capture3('read response; echo $response');
puts 'response=' + response.to_s;
"
CMD
capture(cmd.squish , interaction_handler: ConfirmHandler.new)
end
and get the following result:
data received: Do something?
Please enter your response (y/n)
data received: response=["\n", "", #<Process::Status: pid 9081 exit 0>]
I was writing the code above looking at the Interactive commands section on the SSHKit Github home page
How can I capture the user response from a ruby script with SSKKit on the remote server?
I was able to capture the user response from a ruby script on a remote server with the following code:
# ask_response.rb
puts 'Do something?';
response = `read response; echo $response`;
puts 'response=' + response.to_s;
ask_response.rb is a ruby script which is located on a remote server. And locally I run:
on '<ssh-server-name>' do |host|
capture("ruby ask_response.rb" , interaction_handler: ConfirmHandler.new)
end

Getting Error. java.lang.RuntimeException: unexpected 'configure' key: 'afterScenario'

here is a similar code that im usein
Feature: Create a company instance
Background: Creating the company instance in background
* url baseUrl
* def login = call read('classpath:blackbook/common/getToken.feature')
* def newCI = call read('../endpoints/create_companyinstance.feature')
* def id = newCI.response.data.id
* configure afterScenario =
"""
function(){
var ciID = karate.get('id');
console.log(ciID);
}
"""
After that i will run it. and the login call and newCI call runs fine but then i will get the following error
[ERROR] Scenario: Doing a get call and then some verifications Time
elapsed: 0.005 s <<< ERROR!
java.lang.RuntimeException: unexpected 'configure' key:
'afterScenario'
Please forgive noobness.
Jawad - apologies as I am responsible for prematurely adding documentation for un-released features.
"After hooks" is available in 0.7.0.RC2 - it would be great if you can try that and confirm if it looks good. Even though it is a "release candidate" - as the dev of Karate, I can confirm it should be good for use - and you will not have any breaking changes when "final" arrives (soon).

Gradle ternary/elvis operator not setting 'else' value when external property not set

The 'else' value of the elvis/ternary operator in my gradle build file is not setting the property value if I do not run gradle with the "-P" option.
Here's the root project's build.gradle
defaultTasks 'loadConfiguration'
task loadConfiguration << {
def profile = hasProperty('profile') ? profile : 'dev'
ext.profile = profile
def configFile = file('profile.properties')
def config = new ConfigSlurper(profile).parse(configFile.toURL())
ext.config = config
}
configure (subprojects) {
profile = profile //inject property into sub-project
println profile
task buildear << {
ear
}
}
The sub-project 'ear' is in the settings.gradle file.
Below are the results of a build attempt-
With external property set:
$ gradle -Pprofile=wwww
Parallel execution is an incubating feature.
wwww
wwww
wwww
:loadConfiguration
BUILD SUCCESSFUL
Total time: 5.834 secs
With empty external property set:
$ gradle -Pprofile
Parallel execution is an incubating feature.
:loadConfiguration
BUILD SUCCESSFUL
Total time: 5.389 secs
With no external property set:
$ gradle
Parallel execution is an incubating feature.
FAILURE: Build failed with an exception.
* Where:
Build file '/home/robert/codingk/kazi/trunk2/mazama2/build.gradle' line: 13
* What went wrong:
A problem occurred evaluating root project 'mazama2'.
> Could not find property 'profile' on project ':ear'.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 2.104 secs
Line 13 is the line "profile = profile //inject property into sub-project"
I cannot figure out why the 'profile' property is not getting set to 'dev'. A few things I've tried without success:
profile= "${profile}
def profile = project.hasProperty('profile') ? profile : 'dev'
project.ext.profile = profile
some remarks about your initial build script.
In your initial build script you declared a task (loadConfiguration) to set the profile. This logic is executed AFTER the configure block below
is executed. That's one reason why "profile" is always null in the configuration block
The second problem is, that you need to be careful about scoping. In the snippet
ext.profile = profile
you add a dynamic property to the loadConfiguration task, not to the project itself. That's why you can't reference
The profile property if you havn't passed it via commandline.
Maybe instead of doing the configuration loading in a seperate task, do it on the top level of your build:
ext.profile = hasProperty('profile') ? profile : 'dev'
def configFile = file('profile.properties')
def config = new ConfigSlurper(profile).parse(configFile.toURL())
ext.config = config
configure (subprojects) {
profile = profile //inject property into sub-project
println profile
task buildear << {
ear
}
}
Got it working with the following modifications. I may be wrong but I believe it had to do with task ordering; declaring loadConfiguration() as a default task did not cause it to be executed first which is what I needed
def loadConfiguration() {
def profile = hasProperty('profile') ? profile : 'dev'
ext.profile = profile
def configFile = file('profile.properties')
def config = new ConfigSlurper(profile).parse(configFile.toURL())
ext.config = config
}
configure (subprojects) {
loadConfiguration()
profile = profile //inject property into sub-project
println profile
task buildear << {
ear
}
}