显示导航

将提交信息添加到 Grails 应用程序

了解应用程序运行的代码的确切版本非常重要

作者:科林·哈灵顿

Grails 版本 4.0.1

1 Grails 培训

Grails 培训 - 由创建和积极维护 Grails 框架的人员开发和交付!

2 开始

在本指南中,我们将向 Grails 构建工件和正在运行的应用程序添加 Git 提交信息。随手保留提交信息有很多好处

  • 提交信息封装在构建的工件中

  • 快速权威地识别运行在环境中的特定代码

  • 此解决方案不依赖于外部跟踪机制

  • 调查问题时的透明度和可复制性

如果您喜欢摘要文档,请查看 tl;dr

2.1 所需项

要完成本指南,您将需要以下内容

  • 一些空闲时间

  • 优秀的文本编辑器或 IDE

  • 安装了 JDK 1.8 或更高版本且正确配置了 JAVA_HOME

2.2 如何完成指南

要开始,请执行以下操作

Grails 指南代码库包含两个文件夹

  • initial 初始项目。通常是简单的 Grails 应用程序,其中包含一些额外代码,帮助您快速上手。

  • complete 已完成示例。它是按照指南所述步骤操作和将这些更改应用于 initial 文件夹的结果。

要完成该指南,请进入 initial 文件夹

  • grails-guides/adding-commit-info/initialcd

并按照下一节中的说明操作。

如果你向 grails-guides/adding-commit-info/completecd,你可以直接转到完成的示例

3 历史

过去采用过多种不同的方法来完成此任务,这些方法值得一提。

3.1 早期的做法

Grails 早期采用了在 scripts/_Events.groovy 中利用构建事件(如 eventCompileStart)的方法来捕获 git-sha("git rev-parse HEAD".execute().text)并将它包含在应用程序中,如此文章所述。

3.2 application.properties

Grails 2.x 及更低版本具有可以用于存储提交属性的 application.properties。这是 Grails 用于存储其应用程序名称和版本的相同位置。

在此示例中,需要一些机制来将提交信息追加/更新到 application.properties 中。构建系统可能会在生成 war 之前将 git 提交信息作为构建步骤追加。

将提交信息添加到 application.properties 中后,我们可以通过多种方式访问该元数据

  • 通过 grailsApplication.metadata['git.sha'] 使用 GrailsApplication

  • 在视图中使用标签 <g:meta name='git.sha'/>

3.3 构建信息插件

另一种在 Grails 2.x 中流行的方法是利用构建信息插件。构建信息插件通过利用 Jenkins 等构建系统中可用的环境变量来工作。

  • BUILD_NUMBER

  • BUILD_ID

  • BUILD_TAG

  • SVN_REVISION

  • GIT_COMMIT

  • GIT_BRANCH

然后,可以通过访问 /buildInfo 端点来获得这些值。

4 编写应用程序

有两个基本步骤

让我们开始吧!

4.1 Gradle 插件

Grails 3.x 的一项功能是,应用程序附带 Gradle 作为构建工具。

与其实现我们自己的机制来捕获 git 提交信息,我们可以利用 gradle-git-properties 插件。此插件的目标是捕获提交信息并将它存储在名为 git.properties 的文件中

添加 Gradle 插件相当直接简单。这涉及几个步骤。

  1. build.gradle 中向 buildscript { …​ } 块添加依赖项。这意味着你将依赖项添加到构建中,而不是可交付应用程序中。

  2. 确保构建脚本依赖项将通过适当的 maven 存储库解决

  3. 应用插件

/complete/build.gradle
buildscript {
    repositories {
        maven { url "https://plugins.gradle.org.cn/m2/" }
    }
    dependencies {
        classpath "gradle.plugin.com.gorylenko.gradle-git-properties:gradle-git-properties:2.2.0"
    }
}
apply plugin: "com.gorylenko.gradle-git-properties"

现在,每次编译或运行应用程序(特别是JavaPlugin 的 classes 任务)时,您都会发现 git.properties 已生成。在本地运行 app 时,此文件可在 /build/resources/main/git.properties 中找到。打包为 war 或独立 jar 时,您会发现 git.properties 包含在 WEB-INF/classes

$ unzip -l ./build/libs/complete-0.1.war | grep git.properties
      276  2017-02-02 11:53   WEB-INF/classes/git.properties

检查 git.properties 会显示已捕获的提交信息

git.branch=master
git.commit.id=777d70650bb055862436fc59071072aae8cd0ddd
git.commit.id.abbrev=777d706
git.commit.user.name=Colin Harrington
[email protected]
git.commit.message.short=Adding gradle-git-properties plugin
git.commit.message.full=Adding gradle-git-properties plugin

git.commit.time=1487262171

可以通过配置 gradle 任务(在 build.gradle 中)来配置/影响 git.properties 的生成方式。

gitProperties {
    dateFormat = "yyyy-MM-dd'T'HH:mmZ"
    dateFormatTimeZone = "CST"
}

4.2 Spring Boot Actuator 端点

现在,我们已通过 git.properties 文件捕获了 git 提交信息并将其包含在我们的应用程序中,是时候利用它了。

Grails 3.x 基于 Spring Boot,我们可以利用已包含在应用程序中的一些基础工具。

Spring Boot 包含许多其他功能,可帮助您在将应用程序推送到生产环境后对其进行监控和管理。您可以选择使用 HTTP 端点、JMX 甚至通过远程 Shell(SSH 或 Telnet)来管理和监控应用程序。可以自动将审计、健康和指标收集应用到您的应用程序中,其中内置了一些与生产环境相关的功能。

Spring boot 中内置了一个名为 spring-boot-actuator 的模块,可提供这些端点。端点默认情况下处于禁用状态,因此第一步是启用它们。


如果您打开 grails-app/conf/application.yml,您会发现一个类似于以下内容的配置块

grails-app/conf/application.yml
# Spring Actuator Endpoints are Disabled by Default
endpoints:
    enabled: false

您只需通过将 enabled: true 设置为 enabled: true 来启用 actuator 端点

/grails-app/conf/application.yml
endpoints:
    enabled: true

5 运行应用程序

要运行应用程序,请使用 ./gradlew bootRun 命令,该命令将在端口 8080 上启动应用程序。

启用 actuator 端点后,当您运行应用程序时,您可以在 http://localhost:8080/actuator/info 处访问 /actuator/info 端点,您应该看到一些 JSON 格式的信息,如下所示

{
    app: {
        name: "complete",
        grailsVersion: "3.2.6",
        version: "0.1"
    },
    git: {
        commit: {
            time: "2017-02-16T10:31-0600",
            id: "2f27f2c"
        },
        branch: "master"
    }
}

6 配置

您可能不想启用所有默认 actuator 端点。如果您只想启用 info 端点,您将需要通过配置设置 endpoints.info.enabled=true 并保留 endpoints.enabled=false

# Spring Actuator Endpoints are Disabled by Default
endpoints:
    enabled: false
    info:
        enabled: true
你应该了解,启用执行器端点的所有功能可能会打开几个你可能不想公开的端点。某些端点公开敏感信息,你可能需要对这些端点进行保护或禁用。有关更多信息,请查阅文档 https://docs.springframework.org.cn/spring-boot/docs/current/reference/html/production-ready-endpoints.html

6.1 配置显示的提交信息

你可能已注意到/actuator/info端点只是git.properties中属性的一个子集,如简略 SHA、提交时间和分支。你可以通过设置management.info.git.mode=full在配置中显示全部 git 属性

你将在grails-app/conf/application.yml中设置这些值

/complete/grails-app/conf/application.yml
management:
    endpoints:
        enabled-by-default: true
#    info:
#        enabled: true
#    info:
#        git:
#            mode: full
#    endpoint:
#        jmx:
#            enabled: true

然后,当你重新启动应用程序并在 http://localhost:8080/actuator/info 处访问/actuator/info端点时,你应该会看到类似这样的信息

{
    app: {
        name: "complete",
        grailsVersion: "3.2.6",
        version: "0.1"
    },
    git: {
        commit: {
            message: {
                full: "Enabling Spring Actuator Endpoints",
                short: "Enabling Spring Actuator Endpoints"
            },
            time: "2017-02-16T11:46-0600",
            id: "1695eb2c925e486acb962acf771f813a36568719",
            id.abbrev: "1695eb2",
            user: {
                email: "[email protected]",
                name: "Colin Harrington"
            }
        },
        branch: "master"
    }
}
在底层,此行为由 GitInfoContributor 处理。 InfoEndpoint 是可扩展的,它将聚合实现 org.springframework.boot.actuate.info.InfoContributor 的所有已启用 bean

此外,我们可以添加一个功能测试,以验证 git 信息是否出现在了 rest 响应中。

grails-datastore-rest-client 插件添加到你的dependencies块中

/complete/build.gradle
    testCompile "io.micronaut:micronaut-http-client"
/complete/src/integration-test/groovy/demo/InfoSpec.groovy
package demo

import grails.testing.mixin.integration.Integration
import grails.testing.spock.OnceBefore
import io.micronaut.http.HttpRequest
import io.micronaut.http.HttpResponse
import io.micronaut.http.HttpStatus
import io.micronaut.http.client.HttpClient
import spock.lang.Shared
import spock.lang.Specification

@Integration
class InfoSpec extends Specification {

    @Shared
    HttpClient client

    @OnceBefore
    void init() {
        String baseUrl = "http://localhost:$serverPort"
        this.client  = HttpClient.create(baseUrl.toURL())
    }

    def "test git commit info appears in JSON"() {
        when:
        HttpResponse<Map> resp = client.toBlocking().exchange(HttpRequest.GET("/actuator/info"), Map)

        then:
        resp.status == HttpStatus.OK
        resp.body()
        resp.body().git
        resp.body().git.commit.time
        resp.body().git.commit.id
        resp.body().git.branch
    }
}

6.2 环境配置

在你的应用程序中添加 git 提交信息对于调试和透明度而言非常方便。默认的简单模式仅公开 SHA、时间和分支名称。一些组织更希望在其更敏感的环境中进一步限制 git 信息。

一种方法是利用 按环境配置 根据环境的不同启用/禁用和配置端点。例如,如果你只想在生产环境中启用简单模式,你可以使用以下配置

/complete/grails-app/conf/application.yml
environments:
    production:
        management:
            info:
                git:
                    mode: simple

6.3 根据需要保护你的端点

除了针对特定环境的配置,一些组织可能希望仅向经过身份验证的用户或特定的一组角色限制使用权限。这可以通过插入你的安全插件来实现。我们将使用 Spring Security 作为规范示例。/actuator/info端点不是 Grails 控制器,因此如果你使用默认的基于注解的方法,你将必须配置grails.plugin.springsecurity.controllerAnnotations.staticRules

grails.plugin.springsecurity.controllerAnnotations.staticRules = [
   [pattern: '/',               access: ['permitAll']],
   [pattern: '/error',          access: ['permitAll']],
   [pattern: '/index',          access: ['permitAll']],
   // ...
   [pattern: '/actuator/info',           access: ['ROLE_ADMIN', 'isFullyAuthenticated()']]
]

使用请求 URL 的 RequestMaps简单映射 安全配置方法,因此它们不需要任何特殊处理。请参阅 Spring 安全库的插件文档,了解更多信息。

7 tl;dr(太长;没读完)

摘要

  • 添加 gradle-git-properties 插件

  • 通过 endpoints.info.enabled=trueendpoints.enabled=true 启用执行器端点

  • 配置 并针对端点实施您所需的 安全性

  • …​

  • 确切了解正在运行的代码版本(收益!