|
How to Set up Mailgun configuration to email newsletters for your Ghost blog
cy.request with FormData and QueryString
|
2023, new start! new ghost!
|
Share files between different agent workspace in the same Jenkins Pipeline via stash|unstash
I was working on a legacy app recently. The legacy app has angular as its frontend and spring boot app as its backend. Originally the frontend build outputs are committed in the app's git repository and packaged by spring boot by copying them to the ${project.basedir}/target/classes/static/ class path(since content under the folder will be served as static resources by spring boot). And we are using Jenkins pipeline to run the build for this app. Hence the pipeline only use a java jenkins slave to compile and package the spring boot app. But that is not the right way, isn't it?
We should run both build the pipeline for frontend angular app and backend sprint boot app. But an angular app required a node slave to build it out. We don't have a Jenkins slave that has both java and node installed. Then issue comes: How to build java and javascript apps in a single Jenkins pipeline?
Then I found Pipeline allows utilizing multiple agents in the Jenkins environment from within the sameJenkinsfile
, which can helpful for more advanced use-cases such as executing builds/tests across multiple platforms.
utilizing multiple agents in Pipeline
Good. We could use node agent to build the angular app and use java agent to compile the spring boot app.
agent {
label 'maven' # agent can build java app
}
stages {
stage('Build UI') {
agent {
label 'node8' # agent can build javascript app
}
steps {
sh 'npm install'
sh 'run build'
}
}
stage('Compile') {
// Build the code to generate the spring-boot jar
steps {
sh "mvn -B clean install -f ${POM_FILE}"
}
}
}
The above snippet works well, both frontend and backend got built out. I encountered another challenge: Each agent will run the steps in its own container, which means we are not able to access the dist build out from node agent in the maven agent, since they are using different workspaces.
Share files between agents
While I was searching a proper way to address the above concern, I found stash and unstash directives:
stash
: Stash some files to be used later in the buildunstash
: Restore files previously stashed
Jenkinsfile
pipeline {
agent {
label 'maven'
}
environment {
POM_FILE 'server/pom.xml'
}
stages {
stage('Build UI') {
agent {
label 'node8'
}
steps {
sh 'npm --prefix=ui install'
sh 'npm --prefix=ui run build'
stash includes: 'ui/dist/**', name: 'uidist'
}
}
stage('Compile') {
// Build the code to generate the spring-boot jar
steps {
sh "mvn -B clean install -f ${POM_FILE}"
}
}
stage('Package') {
// Build the code to generate the spring-boot jar
steps {
unstash "uidist"
sh "ls -all ui/dist"
sh "mvn -DskipTests=true -B package -f ${POM_FILE}"
}
}
}
}
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.basedir}/target/classes/static/</outputDirectory>
<resources>
<resource>
<directory>../ui/dist</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
References:
Swagger annotations for API that allows downloading files as zip
I have built out an API that allows you downloading log files as zip in a sprint boot app. The app also integrated with Swagger 3, so I also want this API can be hit in the Swagger UI. In this post, I will demonstrate how to use @ApiOperation annotation to tell Swagger UI download the response as a zip file.
use @ApiOperation for your method
The key is set media type to "application/octet-stream" which can be recognized by Swagger UI. By doing so, you are set "accept":"application/octet-stream" in the request header. Put below annotation section on top of your API's controller method.
@Operation(
summary = "",
description = "",
method="GET",
responses = {
@ApiResponse(responseCode = "200", description = "", content = {
@Content(
mediaType = "application/octet-stream"
)
})
})
You also need to set 'produces = {"application/octet-stream"}' in the Mapping annotation. This is to set the response's header with "Content-Type":"application/octet-stream".
@GetMapping(value = "/yourpath", produces = {"application/octet-stream"})
set response Header, "content-disposition": "attachment; filename=xxx.zip"
In a regular HTTP response, the Content-Disposition
response header is a header indicating if the content is expected to be displayed inline in the browser, that is, as a Web page or as part of a Web page, or as an attachment, that is downloaded and saved locally.
@GetMapping(value = "/yourpath", produces = {"application/octet-stream"})
public void method(HttpServletResponse response) {
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment; filename=%s.zip", transactionId));
}
Try it out in Swagger UI
You will be able to see a 'Download file' anchor once the api successfully response you the zip file.
You also be able find in the response headers:
content-disposition: attachment; filename=xxx.zip
fixed: embedded-redis: Unable to run on macOS Sonoma
Issue you might see below error while trying to run embedded-redis for your testing on your macOS after you upgrade to Sonoma. java.la...
-
F:\webrowser>react-native run-android Scanning folders for symlinks in F:\webrowser\node_modules (73ms) Starting JS server... Buildin...
-
Refer: https://github.com/bazelbuild/bazel/wiki/Building-with-a-custom-toolchain https://www.tensorflow.org/tutorials/image_recognition
-
Solution react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android...