使用 Jenkins X、Kubernetes 和 Spring Boot 實現 CI/CD

本文首發於:Jenkins 中文社區css

過去五年中的變化,如遷移到公有云以及從虛擬機向容器的轉變,已經完全改變了構建和部署軟件的意義。html

以 Kubernetes 爲例。Google 於2014年開源,如今全部主流的公有云供應商都支持它---它爲開發人員提供了一種很好的方式,能夠將應用程序打包到 Docker 容器中,並部署到任意 Kubernetes 集羣中。java

使用 CI/CD、Kubernetes 和 Jenkins X 進行高性能開發

在技術上,高性能團隊幾乎老是成功的必要條件,而持續集成、持續部署(CI/CD)、小迭代以及快速反饋是構建模塊。爲你的雲原生應用程序設置 CI/CD 可能比較困難。經過自動化全部內容,開發人員能夠花費寶貴的時間來交付實際的業務。node

如何使用容器、持續交付和 Kubernetes 成爲高效團隊?這就是 Jenkins X 的切入點。linux


「Jenkins X 的理念是爲全部開發人員提供他們本身的海軍航海管家,能夠幫助你航行持續交付的海洋。」 - James Strachanwebpack


Jenkins X 幫助你自動化你在 Kubernetes 中的 CI/CD - 你甚至不須要學習 Docker 或 Kubernetes!git

Jenkins X 能作什麼?

Jenkins X 在 Kubernetes 上自動安裝,配置和升級 Jenkins 和其餘應用程序(Helm,Skaffold,Nexus 等)。它使用 Docker 鏡像、Helm 圖表和流水線來自動化應用程序的 CI/CD。它使用 GitOps 來管理環境之間的升級,並經過在拉取請求和生產時對其進行評論來提供大量反饋。github

Jenkins X 入門

要安裝 Jenkins X,首先須要在你的機器或雲供應商上安裝 jx 二進制文件。從 Google Cloud 能夠得到300美圓的積分,因此我決定從那裏開始。web

在 Google Cloud 上安裝 Jenkins X 並建立羣集

瀏覽到cloud.google.com並登陸。若是你尚未賬戶,請註冊免費試用。轉到控制檯(右上角有一個連接)並激活 Google Cloud shell。將如下命令複製並粘貼到 shell 中。spring

curl -L https://github.com/jenkins-x/jx/releases/download/v1.3.79/jx-linux-amd64.tar.gz | tar xzv
sudo mv jx /usr/local/bin

注意:Google Cloud Shell 將在一小時後終止在你的主目錄以外所作的任何更改,所以你可能必須從新運行這些命令。好消息是它們將在你的歷史中,因此你只須要向上箭頭並進入。你也能夠刪除上面的 sudo mv 命令,並將如下內容添加到 .bashrc 中。

export PATH=$PATH:.

使用如下命令在 GKE(Google Kubernetes Engine)上建立集羣。你可能必須爲你的賬戶啓用 GKE

jx create cluster gke --skip-login

若是系統提示你下載 helm,請確認你要安裝。系統將提示你選擇 Google Cloud Zone。我建議選擇一個靠近你的位置。我選擇 us-west1-a,由於我住在 Denver, Colorado 附近。對於 Google Cloud Machine 類型,我選擇了 n1-standard-2 並使用了 min(3)和 max(5)個節點數的默認值。

對於 GitHub 名稱,鍵入你本身的(例如 mraible)和你在 GitHub 上註冊的電子郵件(例如 matt.raible@okta.com)。我試圖使用 oktadeveloper(一個 GitHub 組織),但我沒法使其工做。

注意:若是你的賬戶啓用了兩步認證,則 GitHub 集成將失敗。若是你但願成功完成該過程,則須要在 GitHub 上禁用它。

當提示安裝 ingress controller 時,按 Enter肯定。再次按 Enter 鍵選擇默認 domain。

系統將提示你建立 GitHub API Token。單擊 提供的 URL 並將其命名爲 「Jenkins X」。將 token 值複製並粘貼回控制檯。

在安裝完成後喝杯咖啡、飲料或作一些俯臥撐。可能須要幾分鐘。

下一步是將 API token 從 Jenkins 複製到你的控制檯。按照控制檯中提供的說明進行操做。

完成後,運行 jx console 並單擊連接以登陸到 Jenkins 實例。單擊 Administration 並升級 Jenkins 及其全部插件(插件管理器 > 滾動到底部並選擇所有)。若是未能執行此步驟,將沒法從 GitHub pull request 到 Jenkins X CI 進程。

建立一個 Spring Boot 應用程序

當我第一次開始使用 Jenkins X 時,我嘗試導入現有項目。即便個人應用程序使用了 Spring Boot,可是根目錄中沒有 pom.xml,因此 Jenkins X 認爲它是一個 Node.js 應用程序。出於這個緣由,我建議首先建立一個空白的 Spring Boot 應用程序,以保證 Jenkins X 正確建立。

從 Cloud Shell 建立一個簡單的 Spring Boot 應用程序:

jx create spring -d web -d actuator

此命令使用 Spring Initializr,所以系統會提示你進行一些選擇。如下是個人選擇:

QUESTION ANSWER
Language java
Group com.okta.developer
Artifact okta-spring-jx-example

提示:爲你的 artifact name 選取一個簡潔的名稱將減輕你的痛苦。Jenkins X 對於版本名稱有53個字符的限制,oktadeveloper/okta-spring-boot-jenkinsx-example 將會使它超過兩個字符。

爲 git 用戶名、初始化 git 和提交消息都選擇默認值。若是你不想使用我的賬戶,能夠選擇要使用的組織。運行如下命令以查看應用程序的 CI/CD 流水線。

jx get activity -f okta-spring-jx-example -w

運行 jx console,單擊生成的連接,而後導航到你的項目(若是你想要一個更富視覺效果的視圖)。

![Image title]

此過程將執行一些任務:

  1. 爲你的項目建立一個版本
  2. 爲演示環境項目建立 pull request
  3. 將其自動部署到演示環境,以便你能夠查看它的運行狀況。
Merge status checks all passed so the promotion worked!
Application is available at: http://okta-spring-jx-example.jx-staging.35.230.106.169.nip.io

注意:因爲 Spring Boot 默認狀況下不提供歡迎頁面,因此打開上面的 URL 時將返回404。

使用 Jenkins X 將 Spring Boot 應用程序部署到生產環境中

默認狀況下,Jenkins X 只會自動部署到演示環境。你能夠手動改進從演示到生產使用:

jx promote okta-spring-jx-example --version 0.0.1 --env production

你可使用 jx edit environment 更改生產環境,以使用自動部署。

既然你已經知道如何使用 Jenkins X 和一個簡單的 Spring Boot 應用程序,讓咱們來看看如何經過一個更實際的示例使其工做。

保護你的 Spring Boot 應用程序並添加 Angular PWA

在過去的幾個月裏,我寫了一系列有關使用 Ionic/Angular 和 Spring Boot 構建 PWA(漸進式 Web 應用程序)的博文。

  1. 使用 Okta 保護你的加密貨幣財富跟蹤 PWA
  2. 使用 Okta(而不是本地存儲)安全地存儲用戶的數據
  3. 使用 WireMock、Jest、Protractor 和 Travis CI 測試 Spring Boot API 和 Angular 組件的 Hitchhiker 指南
  4. 將你的 Spring Boot + Angular PWA 部署爲一個 Artifact 這是該系列的最後一篇博客文章。我相信這是一個真實應用程序的很好的例子,由於它有許多單元和集成測試,包括與 Protractor 的端到端測試。讓咱們看看如何使用 Jenkins X 和 Kubernetes 自動化生產路徑!

克隆剛剛從GitHub建立的Spring Boot項目(確保在URL中更改{yourUsername}):

git clone https://github.com/{yourUsername}/okta-spring-jx-example.git okta-jenkinsx

在鄰近目錄中,將建立的具備 Spring Boot + Angular 的項目克隆爲一個 artifact:

git clone https://github.com/oktadeveloper/okta-spring-boot-angular-auth-code-flow-example.git spring-boot-angular

在終端中,導航到 okta-jenkinsx 並刪除再也不須要的文件:

cd okta-jenkinsx
rm  -rf .mvn src mvnw* pom.xml

結果應該是包含如下文件的目錄結構:

$ tree .
.
├── charts
│   ├── okta-spring-jx-example
│   │   ├── Chart.yaml
│   │   ├── Makefile
│   │   ├── README.md
│   │   ├── templates
│   │   │   ├── deployment.yaml
│   │   │   ├── _helpers.tpl
│   │   │   ├── NOTES.txt
│   │   │   └── service.yaml
│   │   └── values.yaml
│   └── preview
│       ├── Chart.yaml
│       ├── Makefile
│       ├── requirements.yaml
│       └── values.yaml
├── Dockerfile
├── Jenkinsfile
└── skaffold.yaml

4 directories, 15 files

spring-boot-angular 全部文件複製到 okta-jenkinsx

cp  -r ../spring-boot-angular/* .

使用 Travis CI 測試此應用程序時,我運行了 npm install 做爲該過程的一部分。使用 Jenkins X,使用一個容器(例如 maven 或者 nodejs)保存全部內容更簡單,所以在 frontend-maven-plugin(在 holdings-api/pom.xml)中添加執行以運行 npm install (提示:你將須要執行 id==’npm install' 添加到現有的pom.xml中)。

如今是 okta-jenkinsx 在 IntelliJ IDEA、Eclipse、Netbeans 或 VS Code 等 IDE 中做爲項目打開目錄的好時機!

<plugin>
   <groupId>com.github.eirslett</groupId>
   <artifactId>frontend-maven-plugin</artifactId>
   <version>${frontend-maven-plugin.version}</version>
   <configuration>
       <workingDirectory>../crypto-pwa</workingDirectory>
   </configuration>
   <executions>
       <execution>
           <id>install node and npm</id>
           <goals>
               <goal>install-node-and-npm</goal>
           </goals>
           <configuration>
               <nodeVersion>${node.version}</nodeVersion>
           </configuration>
       </execution>
       <execution>
           <id>npm install</id>
           <goals>
               <goal>npm</goal>
           </goals>
           <phase>generate-resources</phase>
           <configuration>
               <arguments>install --unsafe-perm</arguments>
           </configuration>
       </execution>
       ...
   </executions>
</plugin>

注意:--unsafe-perm 標誌是必要的,由於 Jenkins X 以 root 用戶身份運行構建。我從 node-sass 的故障排除說明中找到了這個解決方案。

增長 Actuator 並關閉 HTTPS

Jenkins X 依靠 Spring Boot 的 Actuator 進行健康檢查。這意味着若是你不將其包含在你的項目中(或有 /actuator/health 防禦),Jenkins X 會報告你的應用程序啓動失敗。

將 Actuator starter 做爲依賴項添加到 holdings-api/pom.xml 中:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

你還須要容許訪問其運行健康檢查。Jenkins X 將部署你的應用程序在一個 NGINX 服務器中,所以你也須要強制關閉 HTTPS,不然你將沒法訪問你的應用程序。修改 holdings-api/src/main/java/.../SecurityConfiguration.java 以容許 holdings-api/src/main/java/.../SecurityConfiguration.java 和刪除 requiresSecure()

public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
   @Override
   public void configure(WebSecurity web) throws Exception {
       web.ignoring().antMatchers("/**/*.{js,html,css}");
   }
   @Override
   protected void configure(HttpSecurity http) throws Exception {
       http
               .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
           .and()
               .authorizeRequests()
               .antMatchers("/", "/home", "/api/user", "/actuator/health").permitAll()
               .anyRequest().authenticated();
   }
}

調整 Dockerfile 和 Jenkinsfile 中的路徑

因爲此項目構建在子目錄而不是根目錄中,所以請更新 ./Dockerfile 以查找 holdings-api 文件。

FROM openjdk:8-jdk-slim
ENV PORT 8080
ENV CLASSPATH /opt/lib
EXPOSE 8080
# copy pom.xml and wildcards to avoid this command failing if there's no target/lib directory
COPY holdings-api/pom.xml holdings-api/target/lib* /opt/lib/
# NOTE we assume there's only 1 jar in the target dir
# but at least this means we don't have to guess the name
# we could do with a better way to know the name - or to always create an app.jar or something
COPY holdings-api/target/*.jar /opt/app.jar
WORKDIR /opt
CMD ["java", "-jar", "app.jar"]

你還須要更新 Jenkinsfile,以便它能夠運行 holdings-api 目錄中的任何 mvn 命令。也添加 -Pprod 配置文件。例如:

// in the 'CI Build and push snapshot' stage
steps {
 container('maven') {
   dir ('./holdings-api') {
     sh "mvn versions:set -DnewVersion=$PREVIEW_VERSION"
     sh "mvn install -Pprod"
   }
 }
 ...
}
// in the 'Build Release' stage
dir ('./holdings-api') {
  sh "mvn versions:set -DnewVersion=\$(cat ../VERSION)"
}
...
dir ('./holdings-api') {
  sh "mvn clean deploy -Pprod"
}

這應該足以讓這個應用程序與 Jenkins X 一塊兒使用。可是,除非你有一個 Okta 賬戶並相應地配置它,不然你將沒法登陸它。

爲何使用Okta?

簡而言之,咱們使標識管理比你可能習慣的更簡潔、更安全、更具可擴展性。Okta 是一種雲服務,容許開發人員建立、編輯和安全存儲用戶賬戶和用戶賬戶數據,並將其與一個或多個應用程序相鏈接。咱們的 API 使你可以:

  • 對用戶進行身份驗證受權
  • 存儲關於用戶的數據
  • 執行基於密碼和社交登陸
  • 使用多重身份驗證保護應用程序
  • 瞭解更多!查看咱們的產品文檔 你心動了嗎?註冊一個永遠免費的開發者賬戶,當你完成後,請返回,以便咱們能夠經過 Spring Boot 和 Jenkins X 瞭解有關 CI/CD 的更多信息!

在 Okta 中爲 Spring Boot 應用程序建立一個 Web 應用程序

完成設置過程後,登陸到你的賬戶並導航到 Applications > Add Application。單擊 Web下一步。在下一頁中,輸入如下值並單擊 Done (必須單擊 Done,而後編輯以修改註銷重定向 URI)。

  • 應用名稱: Jenkins X
  • 默認 URI: http://localhost:8080
  • 登陸重定向 URI: http://localhost:8080/login
  • 註銷重定向 URI: http://localhost:8080 打開 holdings-api/src/main/resources/application.yml 並將你 org/app 中的值粘貼到其中。
okta:
 client:
   orgUrl: https://okta.okta.com
   token: XXX
security:
   oauth2:
     client:
       access-token-uri: https://okta.okta.com/oauth2/default/v1/token
       user-authorization-uri: https://okta.okta.com/oauth2/default/v1/authorize
       client-id: {clientId}
       client-secret: {clientSecret}
     resource:
       user-info-uri: https://okta.okta.com/oauth2/default/v1/userinfo

你將注意到 token 值是 xxx。這是由於我更喜歡從環境變量中讀取它,而不是簽入源代碼控制。你可能也想爲你的客戶密鑰執行此操做,但我只是爲了簡潔而作一個屬性。要建立 API token:

  1. 導航到 API > Tokens ,而後單擊 Create Token
  2. 爲令牌命名(例如 「Jenkins X」),而後將其值設置爲 OKTA_CLIENT_TOKEN 環境變量。 你須要在組織的用戶配置文件中添加一個 holdings 屬性,以便將你的加密貨幣存儲在 Okta 中。導航到 Users > Profile Editor。點擊 Profile 表格中的第一個配置文件。你能夠經過其 Okta 標識來識別它。單擊 Add Attribute 並使用如下值:
  • 顯示名稱: Holdings
  • 變量名: holdings
  • 描述: Cryptocurrency Holdings 執行這些步驟後,你應該可以導航到 http://localhost:8080, 並在運行如下命令後登陸:
cd holdings-api
./mvnw -Pprod package
java -jar target/*.jar

在 Jenkins X 中存儲 Secrets 在本地存儲環境變量很是簡單。可是你如何在 Jenkins X 中作到這一點?看看它的憑證功能就知道了。下面是使用方法:

  1. 在 Google Cloud Shell 上運行 jx console,以獲取 Jenkins X 網址
  2. 單擊該連接,登陸,而後單擊頂部的 Administration
  3. 單擊 Credentials > (global) > Add Credentials(在左側)
  4. 從下拉列表中選擇 Secret text,併爲 ID 輸入 OKTA_CLIENT_TOKEN
  5. 將 Okta API token 複製/粘貼到 Secret 字段中 當你在裏面,添加 secrets:OKTA_APP_IDE2E_USERNAMEE2E_PASSWORD。第一個是你建立的 Jenkins X OIDC 應用程序的 ID。您能夠經過在 Okta 上導航到您的應用程序並從 URL 複製值來得到它的值。該 E2E-* 密鑰應該是要用來運行終端到終端(Protractor)測試的憑證。你可能想爲此建立一個新用戶。

你能夠經過將這些值添加到 environment 頂部附近的部分來訪問 Jenkinsfile 中的這些值 。

environment {
  ORG               = 'mraible'
  APP_NAME          = 'okta-spring-jx-example'
  CHARTMUSEUM_CREDS = credentials('jenkins-x-chartmuseum')
  OKTA_CLIENT_TOKEN = credentials('OKTA_CLIENT_TOKEN')
  OKTA_APP_ID       = credentials('OKTA_APP_ID')
  E2E_USERNAME      = credentials('E2E_USERNAME')
  E2E_PASSWORD      = credentials('E2E_PASSWORD')
}

將環境變量轉移到 Docker 容器

要將 OKTA_CLIENT_TOKEN 環境變量轉移到 Docker 容器,請查看:

sh "make preview"

並將其更改成:

sh "make OKTA_CLIENT_TOKEN=\$OKTA_CLIENT_TOKEN preview"

此時,你能夠建立分支,提交更改,並驗證 Jenkins X 中的全部內容是否正常工做。

cd ..
git checkout -b add-secure-app
git add .
git commit -m "Add Bootiful PWA"
git push origin add-secure-app

打開瀏覽器並導航到 GitHub 上的存儲庫並建立 pull request。建立後它應該以下所示。

Add Bootiful PWA Pull Request

若是你的 pull request 測試經過,你應該能看到一些綠色標記和 Jenkins X 的評論,說明你的應用程序在預覽環境中可用。

PR Success!

若是你單擊此處連接並嘗試登陸,則可能會從 Okta 獲得一個錯誤,指出重定向 URI 還沒有列入白名單。

在 Okta 中自動添加劇定向 URI

當你在 Okta 中建立應用程序並在本地運行它們時,很容易知道應用程序的重定向 URI 將是什麼。對於這個特定的應用程序,它們將 http://localhost:8080/login 用於登陸,http://localhost:8080 用於註銷。當您進入生產環境時,URL一般也是衆所周知的。可是,使用 Jenkins X,URL 是動態的,並根據你的 pull request 編號動態建立的。

要使用 Okta 進行此操做,你能夠建立一個 Java 類,該類與 Okta API 進行交互。建立 holdings-api/src/test/java/.../cli/AppRedirectUriManager.java 並使用如下代碼完善它。

package com.okta.developer.cli;
import com.okta.sdk.client.Client;
import com.okta.sdk.lang.Collections;
import com.okta.sdk.resource.application.OpenIdConnectApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@SpringBootApplication
public class AppRedirectUriManager implements ApplicationRunner {
   private static final Logger log = LoggerFactory.getLogger(AppRedirectUriManager.class);
   private final Client client;
   @Value("${appId}")
   private String appId;
   @Value("${redirectUri}")
   private String redirectUri;
   @Value("${operation:add}")
   private String operation;
   public AppRedirectUriManager(Client client) {
       this.client = client;
   }
   public static void main(String[] args) {
       SpringApplication.run(AppRedirectUriManager.class, args);
   }
   @Override
   public void run(ApplicationArguments args) {
       log.info("Adjusting Okta settings: {appId: {}, redirectUri: {}, operation: {}}", appId, redirectUri, operation);
       OpenIdConnectApplication app = (OpenIdConnectApplication) client.getApplication(appId);
       String loginRedirectUri = redirectUri + "/login";
       // update redirect URIs
       List<String> redirectUris = app.getSettings().getOAuthClient().getRedirectUris();
       // use a set so values are unique
       Set<String> updatedRedirectUris = new LinkedHashSet<>(redirectUris);
       if (operation.equalsIgnoreCase("add")) {
           updatedRedirectUris.add(loginRedirectUri);
       } else if (operation.equalsIgnoreCase("remove")) {
           updatedRedirectUris.remove(loginRedirectUri);
       }
       // todo: update logout redirect URIs with redirectUri (not currently available in Java SDK)
       app.getSettings().getOAuthClient().setRedirectUris(Collections.toList(updatedRedirectUris));
       app.update();
       System.exit(0);
   }
}

該類使用 Spring Boot 的 CLI(命令行接口)支持,這使得可使用 Exec Maven 插件調用它。要添加對 Maven 運行它的支持,請在 holdings-api/pom.xml 進行如下修改 。

<properties>
    ...
   <exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
   <appId>default</appId>
   <redirectUri>override-me</redirectUri>
</properties>
<!-- dependencies -->
<build>
   <defaultGoal>spring-boot:run</defaultGoal>
   <finalName>holdings-app-${project.version}</finalName>
   <plugins>
       <!-- existing plugins -->
       <plugin>
           <groupId>org.codehaus.mojo</groupId>
           <artifactId>exec-maven-plugin</artifactId>
           <version>${exec-maven-plugin.version}</version>
           <executions>
               <execution>
                   <id>add-redirect</id>
                   <goals>
                       <goal>java</goal>
                   </goals>
               </execution>
           </executions>
           <configuration>
               <mainClass>com.okta.developer.cli.AppRedirectUriManager</mainClass>
               <classpathScope>test</classpathScope>
               <arguments>
                   <argument>appId ${appId} redirectUri ${redirectUri}</argument>
               </arguments>
           </configuration>
       </plugin>
   </plugins>
</build>

而後更新 Jenkinsfile 以在構建鏡像以後添加一段 mvn exec:java 供運行。

dir ('./charts/preview') {
  container('maven') {
    sh "make preview"
    sh "make OKTA_CLIENT_TOKEN=\$OKTA_CLIENT_TOKEN preview"
    sh "jx preview --app $APP_NAME --dir ../.."
  }
}
// Add redirect URI in Okta
dir ('./holdings-api') {
  container('maven') {
    sh '''
      yum install -y jq
      previewURL=$(jx get preview -o json|jq  -r ".items[].spec | select (.previewGitInfo.name==\\"$CHANGE_ID\\") | .previewGitInfo.applicationURL")
      mvn exec:java@add-redirect -DappId=$OKTA_APP_ID -DredirectUri=$previewURL
    '''
  }
}

提交併推送你的更改,應用程序應該更新爲 http://{yourPreviewURL}/login 的重定向 URI。你須要手動爲 http://{yourPreviewURL} 添加一個註銷重定向 URI, 由於 Okta 的 Java SDK 目前不支持此功能

Okta app with URI settings

要將你的 pull request 上傳到演示環境,請將其合併,並將主分支推送到演示環境。不幸的是,你將沒法登陸。這是由於沒有進程使用你的 Okta 應用程序註冊登臺站點的重定向 URI。若是手動添加 URI,一切都應該有效。

在 Jenkins X 中運行 Protractor 測試

對我來講,弄清楚如何在 Jenkins X 中運行端到端測試是最難的。我首先添加了一個新的 Maven 配置文件,它容許我使用 Maven 而不是 npm 運行測試。

注意:要使此配置文件起做用,你須要將 http://localhost:8000/login 登陸重定向 URI 添加到你的應用程序,並將 http://localhost:8000 做爲註銷重定向URI。

<profile>
   <id>e2e</id>
   <properties>
       <!-- Hard-code port instead of using build-helper-maven-plugin. -->
       <!-- This way, you don't need to add a redirectUri to Okta app. -->
       <http.port>8000</http.port>
   </properties>
   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
               <executions>
                   <execution>
                       <id>pre-integration-test</id>
                       <goals>
                           <goal>start</goal>
                       </goals>
                       <configuration>
                           <arguments>
                               <argument>--server.port=${http.port}</argument>
                           </arguments>
                       </configuration>
                   </execution>
                   <execution>
                       <id>post-integration-test</id>
                       <goals>
                           <goal>stop</goal>
                       </goals>
                   </execution>
               </executions>
           </plugin>
           <plugin>
               <groupId>com.github.eirslett</groupId>
               <artifactId>frontend-maven-plugin</artifactId>
               <version>${frontend-maven-plugin.version}</version>
               <configuration>
                   <workingDirectory>../crypto-pwa</workingDirectory>
               </configuration>
               <executions>
                   <execution>
                       <id>webdriver update</id>
                       <goals>
                           <goal>npm</goal>
                       </goals>
                       <phase>pre-integration-test</phase>
                       <configuration>
                           <arguments>run e2e-update</arguments>
                       </configuration>
                   </execution>
                   <execution>
                       <id>ionic e2e</id>
                       <goals>
                           <goal>npm</goal>
                       </goals>
                       <phase>integration-test</phase>
                       <configuration>
                           <environmentVariables>
                               <PORT>${http.port}</PORT>
                               <CI>true</CI>
                           </environmentVariables>
                           <arguments>run e2e-test</arguments>
                       </configuration>
                   </execution>
               </executions>
           </plugin>
       </plugins>
   </build>
</profile>

提示:你可能會注意到,我必須爲 e2e-updatee2e-test 分兩次不一樣的執行。我發現運行 npm e2e 與 frontend-maven-plugin 不兼容,由於它只調用其餘 npm run 命令。看來你須要在使用 frontend-maven-plugin 時直接調用二進制文件。

這裏使用的不是 TRAVIS 環境變量,而是 CI 變量。此更改須要更新 crypto-pwa/test/protractor.conf.js 來匹配。

baseUrl: (process.env.CI) ? 'http://localhost:' + process.env.PORT : 'http://localhost:8100',

進行這些更改,你應該可以運行 ./mvnw verify -Pprod,e2e 以在本地運行端到端測試。請注意,你須要將 E2E_USERNAMEE2E_PASSWORD 定義爲環境變量。

當我第一次在 Jenkins X 中嘗試這個功能時,我發現 jenkins-maven 代理沒有安裝 Chrome。我發現很難安裝並發現 jenkins-nodejs 預安裝了 Chrome 和 Xvfb。當我第一次嘗試它時,我遇到如下錯誤:

[21:51:08] E/launcher - unknown error: DevToolsActivePort file doesn't exist

此錯誤是由 Chrome on Linux 問題引發的 。我發現解決辦法是在 Protractor 的 chromeOptions 中指定 -disable-dev-shm-usage。我還添加了一些推薦的額外標誌。我特別喜歡 --headless,在本地運行時,所以瀏覽器不會彈出並妨礙我。若是我想實時看到這個過程,我能夠快速刪除該選項。

若是你但願在 Jenkins X 上看到項目的 Protractor 測試運行,則須要修改 crypto-pwa/test/protractor.conf.js 以指定如下內容 chromeOptions

capabilities: {
  'browserName': 'chrome',
  'chromeOptions': {
    'args': ['--headless', ''--disable-gpu', '--no-sandbox', '--disable-extensions', '--disable-dev-shm-usage']
  }
},

而後向 Jenkinsfile 添加一個新的 Run e2e tests 階段,該階段位於 「CI 構建」和「構建發佈」階段之間。若是有幫助,你能夠看到最終的 Jenkins 文件

stage('Run e2e tests') {
 agent {
   label "jenkins-nodejs"
 }
 steps {
   container('nodejs') {
     sh '''
       yum install -y jq
       previewURL=$(jx get preview -o json|jq  -r ".items[].spec | select (.previewGitInfo.name==\\"$CHANGE_ID\\") | .previewGitInfo.applicationURL")
       cd crypto-pwa && npm install --unsafe-perm && npm run e2e-update
       Xvfb :99 &
       sleep 60s
       DISPLAY=:99 npm run e2e-test -- --baseUrl=$previewURL
     '''
   }
 }
}

完成全部這些更改後,建立一個新分支,簽入你的更改,並在 GitHub 上建立一個 pull request。

git checkout -b enable-e2e-tests
git add .
git commit -m "Add stage for end-to-end tests"
git push origin enable-e2e-tests

我確實須要作一些額外的調整才能經過全部的 Protractor 測試:

  1. crypto-pwa/e2e/spec/login.e2e-spec.ts 中,我沒法經過 should show a login button 測試,因此我忽略了它,將 it(…) 改成 xit(…)。
  2. 在同一個文件中,我將2000 ms 超時更改成5000 ms,將5000 ms 超時更改成30000 ms。
  3. crypto-pwa/test/protractor.conf.js 中,我將 defaultTimeoutInterval 更改成 600000。 第一次運行時測試可能會失敗,由於未爲新預覽環境配置註銷重定向URI。更新 Okta 應用程序的註銷重定向 URI 以匹配你的 PR 的預覽環境 URI,從新 pull request 測試,一切都應該經過!

blog/spring-boot-jenkins-x/jenkinsx-everything-is-awesome.png

你能夠在 GitHub 上的此示例中找到已完成應用程序的源代碼 。

瞭解有關 Jenkins X、Kubernetes 和 Spring Boot 的更多信息

要了解有關 Spring Boot、Jenkins X 和 Kubernetes 的更多信息,請查看如下資源:

Jenkins X 還包括一個 DevPods 功能,能夠在筆記本電腦上進行開發時,能夠自動部署保存。我不肯定 DevPods 是否適用於須要具備生產轉換步驟的 JavaScript 應用程序。我寧願讓 webpack 和 Browsersync 在幾秒鐘內刷新個人本地瀏覽器,而不是等待幾分鐘建立並部署 Docker 鏡像到 Kubernetes。

要得到 Jenkins X 的精彩概述和演示,請觀看 James Strachan 在2018年6月的 Virtual JUG 會議上爲 Kubernetes 發佈的 Jenkins X: Continuous Delivery

若是你有任何疑問,請在下面添加評論,在 Twitter 上發帖,或在咱們的開發者論壇 上發帖提問。要得到有關將來博客文章和開發人員智慧的通知,你能夠在Twitter上關注個人整個團隊

使用 Jenkins X 和 Kubernetes 將 CI/CD 添加到 Spring Boot 應用程序中,最初於2018年7月11日發佈到 Okta 開發人員博客。

譯者:史彥軍

相關文章
相關標籤/搜索