使用GitHub Actions编译项目并将Jar发布到Maven Central仓库

在上一篇 GitHub Actions使用入门 文章中,我们了解到了该怎么去启用GitHub Actions功能,本篇文章来介绍下使用GitHub Actions怎么将我们的开源项目自动化构建后发布到Maven Central仓库中。

推荐阅读

新建workflow文件

本篇文章以我的开源框架 ApiBoot 为例,大家有兴趣的也可以去了解下这个开源框架,详情请访问:ApiBoot是什么?

在上一篇文章中我们提到过,GitHub Actions所需要的工作流文件要在.github/workflows文件夹内创建,那么接下来我们创建一个名为deploy.yml的工作流配置文件,配置name为该工作流的名称,如下所示:

1
2
3
# This is a basic workflow to help you get started with Actions

name: Publish package to the Maven Central Repository

配置触发的分支

我们还需要配置当前工作流在什么情况进行触发自动构建的事件,在deploy.yml配置文件内添加触发事件,如下所示:

1
2
3
4
5
6
7
8
9
10
11
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
push:
branches:
- master
- 2.3.x
pull_request:
branches:
- master
- 2.3.x

在上面我们配置了两种触发工作流程的事件,分别是:pushpull_request,也就是仓库收到推送更新以及pull_request时就会触发该工作流程,实现自动化构建。

GitHub Actions其实为我们提供了多种触发工作流程的事件,访问 触发工作流程的事件 了解详情。

配置工作任务

触发事件配置完成后我们就需要来配置当前工作流程所需要的系统环境以及每一个步骤所需要做的事情了。

构建系统

GitHub Actions支持针对工作流程中的每一个任务(Job)进行配置独立的构建系统版本,我们选择最新版本的Ubuntu来作为本次任务的运行系统环境,配置内容如下所示:

1
2
3
4
5
6
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest

我们今天文章的主题是Jar发布到Maven Central仓库,根据分析我们大约需要三个步骤来完成这一工作。

Step1:检出代码

首先我们需要将项目的源码检出到构建环境中,这时我们就可以借助GitHub Actions官方提供的actions/checkout来完成这一步骤,Action源码:https://github.com/actions/checkout

Step2:安装环境

ApiBoot 是一个Java项目(JDK1.8+),而且采用Maven进行构建项目,所以我们需要在构建的环境中安装相关的环境支持,GitHub Actions官方同样提供了相关的Action,名为:actions/setup-java,Action源码:https://github.com/actions/setup-java

Step3:执行发布

最后一步我们就需要通过mvn deploy命令来完成发布Jar,由于项目发布到Release仓库时需要GPG秘钥的支持,而我们期望的只是自动发布快照版本,所以可以通过-Dgpg.skip来排除GPG插件的介入。

全部步骤的配置内容如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checkout source code
- uses: actions/checkout@v2
# Install Java 1.8
- uses: actions/setup-java@v1
with:
server-id: hengyu
java-version: 1.8
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
# Publish to Apache Maven Central
- run: mvn -B deploy -Dgpg.skip
env:
MAVEN_USERNAME: ${{ secrets.MAVEN_CENTER_USER_NAME }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTER_PASSWORD }}

注意事项:使用Action时,需要指定版本号,通过@v?的这种方式,其实这个版本号是仓库源码的标签

配置GitHub Secrets

actions/setup-java@v1在执行时会创建Maven所需要的settings.xml文件,而在该文件内我们可以通过配置server-usernameserver-password来指定发布的目标仓库的用户名、密码。

由于该工作流配置文件是公开的,我们肯定不会明文进行配置GitHub针对这一点,提供了Secrets配置的方式,我们需要将存在安全性的变量进行配置,使用时注意变量名称的对应即可。

Secrets在使用时需要根据约定的格式配置:

1
${{ secrets.MAVEN_CENTER_USER_NAME }}

secrets为前缀,而后面的变量名必须与GitHub内的配置一致,如果你的相关Secrets配置需要用于多个项目,可以在组织下进行配置。

推送更新

到目前为止,我们的项目已经完成了GitHub Actions的配置,接下来需要将该工作流程配置文件推送()push)到目标仓库,推送后我们查看项目的Actions标签页的内容,如下所示:

每当我们推送代码时都会自动触发构建工作流程的事件,一个工作流程的任务都会有完整的日志记录,如下所示:

当一个任务的全部步骤都执行成功后,当前任务也算是真正的执行成功,如果一个工作流程文件内配置了多个任务,则是需要多个任务都构建成功后才算成功。

槽点

目前针对GPG的支持确实有点问题,GitHub官方所提供的Action也是会有一些问题,导致无法完成通过GPG的方式完成构建项目,如果这一点可以解决,就可以实现在GitHub仓库创建发布版本时触发工作事件,实现自动上传JarRelease仓库,省去了在本地发布的工作。

示例

本文的workflow配置文件内容可以访问:https://github.com/minbox-projects/api-boot/blob/2.3.x/.github/workflows/deploy.yml

GitHub Actions使用入门

简介

GitHub Actions 是由GitHub2018年推出的一款持续集成的服务方案,对于GitHub上托管的开源项目来说比较友好,集成使用简单,个人感觉比 Travis-CI 玩法要更多,而且还是可以自己去编写Actions在构建的过程中使用。

推荐阅读

基本概念

GitHub Actions内有一些概念性的定义,如下所示:

  • workflow:顾名思义这是工作流程,在GitHub Actions中每执行一次就是一个工作流程。
  • job:工作流程中的一个任务,一个工作流程可以配置多个任务
  • step:工作任务中的步骤,根据配置的先后顺序执行,一个任务内可以配置多个步骤
  • action:每个步骤所使用的构建动作,可以使用GitHub官方提供的动作实现,也可以自动编写。

使用GitHub Actions

当我们打开项目的主页时可以看到Actions功能标签页,这就是该仓库的GitHub Actions,如果你的仓库没有添加过workflow文件,看到的效果如下所示:

配置Workflow YML

每一个工作流都是由一个YML文件进行配置的,在该文件内我们可以配置仓库的GitHub Actions所相关的全部内容,GitHub针对文件所处的目录进行了约定,必须在仓库根下的.github/workflows目录内。

方式一:直接在GitHub页面上添加

在上面的截图中,我们点击set up a workflow yourself ->回跳转添加workflow文件的页面,在该页面中我们可以修改文件名,也可以修改workflow文件的配置内容,如下所示:

方式二:项目源码中添加后推送

我们也可以在项目源码中添加后进行推送,首先在项目的根目录下创建.github/workflows目录,然后在新创建的目录下添加一个名为deploy.yml的工作流配置文件,将修改提交后pushGitHub仓库即可。

GitHub提供的Actions

GitHub官方所提供的Actions都是开源的,而且都位于 https://github.com/actions 开源组织下,比较常用到的Actions

  1. checkout:用于checkout一个仓库源码到构建环境中
  2. setup-java:用于安装MavenJDK等构建项目的依赖到构建环境中
  3. setup-node:用于安装nodeJs到构建环境中

无意间发现一个好用的视频转换gif图片的开源框架

简介

Gifify是一款工具类的开源框架,可以将任何视频文件转换为优化的动画GIF。

有些时候我们需要将视频转换为动画GIF图,可以更生动形象的描述我们想要说明的事物以及框架的使用方式,它对于程序员来说是一个不可或缺的工具之一。

环境支持

在安装Gifify之前首先我们需要先安装它所需要的运行环境:

  • Node.jsbrew install node
  • FFmpegbrew install ffmpeg
  • ImageMagickbrew install imagemagick
  • giflossybrew install giflossy

安装

可以通过npm直接安装Gifify,如下所示:

1
npm install -g gifify

命令行参数

下面是Gifify所支持的命令行参数列表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
➜  ~ gifify -h
Usage: gifify [options] [file]

Options:
-V, --version output the version number
--colors <n> Number of colors, up to 255, defaults to 80 (default: 80)
--compress <n> Compression (quality) level, from 0 (no compression) to 100, defaults to 40 (default: 40)
--from <position> Start position, hh:mm:ss or seconds, defaults to 0
--fps <n> Frames Per Second, defaults to 10 (default: 10)
-o, --output <file> Output file, defaults to stdout
--resize <W:H> Resize output, use -1 when specifying only width or height. `350:100`, `400:-1`, `-1:200`
--reverse Reverses movie
--speed <n> Movie speed, defaults to 1 (default: 1)
--subtitles <filepath> Subtitle filepath to burn to the GIF
--text <string> Add some text at the bottom of the movie
--to <position> End position, hh:mm:ss or seconds, defaults to end of movie
--no-loop Will show every frame once without looping
-h, --help output usage information

视频转换为GIF

我使用Mac自带的屏幕录制软件QuickTime Player录制了一个测试视频,根据上面的命令行参数来看如果我们不做一些其他的自定义,只添加-o、--output输出的gif文件名即可,如下所示:

1
2
➜ gifify 屏幕录制2020-08-05\ 上午8.58.01.mov --output example.gif
Generating GIF, please wait...

当我们看到提示信息Generating GIF, please wait...时,说明已经开始转换了,因为视频文件的大小有差异,所以转换所需要的时间也所有不同。

自动创建的example.gif文件与转换的视频文件在同一目录下。

GIF截取

如果你只需要转换视频中的一个时间段,我们可以通过指定--from--to参数来配置,如下所示:

1
➜ gifify 屏幕录制2020-08-05\ 上午8.58.01.mov --output example.gif --from 00:00:10 --to 00:00:15

GIF压缩

Gifify默认压缩比例为40%,压缩后的Gif图可能会比较模糊,我们可以通过--compress参数来修改压缩比例,0表示无压缩,取值范围为0~100,如下所示:

1
➜ gifify 屏幕录制2020-08-05\ 上午8.58.01.mov --output example.gif --from 00:00:10 --to 00:00:12 --compress 0

总结

Gifify还有很多隐藏的功能,比如在GIF图片上添加文字描述,缩放视频比例,反转视频等功能,赶快去发掘它的隐藏功能吧。

面试攻略

被访问0


又到了一年一度的跳槽旺季,面试官要问的问题你真的准备好了吗?

恒宇少年最近在公众号陆续整理面试题、面试攻略,从面试官的心理来分析回答问题。

公众号的二维码在右侧,有需要实时获取微信公众号推送的同学可以扫码关注下。

Java基础

消息队列

高并发

持续更新,敬请期待…

官宣,GitHub正式发布了移动端v1.0版本

GitHub在2019年开发者大会上已经表明正在研发手机客户端,而就在昨天(2020-3-18)提供了正式版本的下载链接,苹果端也已经上架到了AppStore

安装

GitHub移动端 官网上仅提供了两种安装方式,如下图所示:

如果你手机上可以访问Google那么你就可以通过Google Play直接安装,当然手机上访问Google还是需要一点灰色手段的,不过不用怕, 我已经将Apk下载了,放到了阿里云的对象存储内,可以直接访问下载。

IOS安装

https://apps.apple.com/cn/app/github/id1477376905

复制上面的地址到Safari浏览器中打开。

Android 安装

https://hengboy-image.oss-cn-beijing.aliyuncs.com/GitHub.v1.0.0.apk

复制上面的地址在浏览器直接访问即可。

当我们安装完成就可以看到在你的手机上多了一个 “黑猫” 应用。

开箱

打开GitHub App 然后登录我们的账号。

首页

首页中间的内容分为了三个部分,分别是:My Work(我的工作台)Favorites(收藏夹)Recent(最近动态)

  1. Issues

    点进去可以查看由我创建的、分配给我的、提到我的Issues列表,支持搜索功能。

  2. Pull Requests

    点进去可以查看由我创建、分配给我、提到我的、已合并的Pull Requests列表,支持搜索功能。

  3. Repositories

    点进去可以查看账号下的全部仓库(加入组织创建的、由我创建的、Fork的)

  4. Organizations

    点进去可以看到我所加入的组织,可以查看组织的详情、组织内的仓库列表。

消息通知

搜索

输入关键字可以搜索GitHub内匹配关键字的仓库列表。

个人首页

点击左上角的头像可以进去我的主页,主页的顶部是个人的详细信息,中间为自定义固定的展示仓库(最多6个),底部则是创建的仓库、点赞的仓库、加入的组织。

设置

自定义皮肤

皮肤默认根据手机系统的设定而来,我手机设置为深色系,而GitHub App也是黑色,可以自行修改为亮色。

自定义Icon图标

![](/images/post/github-app-release/IMG_1675 2.PNG)

手机App的图标也支持自定义,内部提供了多种样式供你选择。

浏览代码

浏览代码比较麻烦,需要一层一层进入Package,不过返回的时候比较简单,点击文件名称后面的箭头,可以选择返回任意一层,当然也可以直接返回Root目录,查看代码的质感还是很不错的。

项目主页

查看项目主页详情的功能基本跟网页版的差不多,点击Browse code就可以查看该项目的全部代码,点击右上角的“+”号可以直接创建Issues

优缺点

  1. 使用起来不太稳定,需要开代理
  2. 由于App安装文件较小,使用起来流畅度很不错
  3. 基本的功能很完整,该有的都有了
  4. 只能分享一个链接地址

使用nginx的负载均衡机制实现用户无感更新服务

前言

用户请求的转发是接口服务在部署时必须要做的一步。

请求转发的步骤大约分为如下几步:

  1. 域名解析到转发服务器
  2. 转发服务器会根据权重(weight)、备用(backup)配置转发到统一网关
  3. 如果统一网关存在灰度的配置,需要根据身份或者头信息过滤请求
  4. 转发到具体的业务服务

目前市面上优秀的请求转发有很多种,比如:NginxF5KongTengine等,其中Tengine是阿里巴巴基于Nginx进行封装,我们本章的内容基于Nginx进行讲解,我们先来准备下nginx的测试环境。

准备环境

如果你的测试环境没有安装Nginx,下面我通过两种方式来说下具体的安装过程。

使用Brew安装Nginx

如果你是OSX系统,可以直接使用brew管理工具进行安装,这种方式比较简单,自动从远程服务器下载最新稳定的版本进行解压、配置环境等。

1
2
# 安装nginx
➜ ~ brew install nginx

静静等待~

安装完成后,我们先来修改下端口号(brew安装包把默认的监听端口号改为了8080,一般在使用解压的方式安装时监听端口都是80)。

我们需要先找到nginx.conf这个文件的位置:

1
2
➜  ~ sudo find / -name nginx.conf           
/usr/local/etc/nginx/nginx.conf

找到文件后,我们通过sudo vi /usr/local/etc/nginx/nginx.conf命令来修改默认的端口号,位置如下:

1
2
3
4
5
server {
listen 80;
server_name localhost;
#...
}

修改后保存退出。

最后不要忘记重启Nginx服务。

1
➜  ~ brew services restart nginx

解压包方式

首先去nginx官方提供 http://nginx.org/download 的下载地址去挑选自己中意的版本,下面以1.17.7版本示例:

点击下载完成后解压安装即可(注意编译环境,可能会缺少一些依赖库,本机安装对应的依赖就可以了)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 解压nginx
tar -xvf nginx-1.17.7.tar.gz
# 进入目录
cd nginx-1.17.7
# 配置
./configure --prefix=/usr/local/nginx
# 编译
sudo make
# 安装
sudo make install
# 进入nginx执行目录
cd /usr/local/nginx/sbin
# 启动nginx
./nginx

安装完成如果访问 http://127.0.0.1 可以看到Welcome to nginx!字样,说明我们已经安装成功了。

示例项目

为了演示更新服务用户无痛感知,我们先来创建一个简单的SpringBoot示例项目,在项目内添加一个测试接口,项目pom.xml依赖如下所示:

1
2
3
4
5
6
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

示例接口

创建一个名为TestController的测试控制器,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 测试控制器
*
* @author 恒宇少年
*/
@RestController
@RequestMapping(value = "/test")
public class TestController {
@Autowired
private ServerProperties serverProperties;

@GetMapping
public String hello() {
return "请求分发到了,端口号:" + serverProperties.getPort() + "的服务,接口访问成功.";
}
}

配置转发

我们测试所需要的请求接口已经准备好了,接下来需要在访问nginx时将请求转发到我们测试的接口,配置转发时需要用到nginx的两个关键字,分别是upstreamlocation

  • upstream:服务器组,配置请求分发到组内多台服务器。
  • location:转发的路径前缀,如:”/user/“,当我们访问http://127.0.0.1/user/1时,就会执行该location的转发业务。

upstream转发流程如下图所示:

配置UpStream

nginx.conf文件http内添加转发的服务器组(upstream),如下所示:

1
2
3
4
5
6
# 负载配置
upstream test {
server 127.0.0.1:8080 weight=1;
server 127.0.0.1:9090 weight=2;
server 127.0.0.1:9000 backup;
}

配置Location

在上面已经配置好了服务器组,我们需要把名为test的服务器组作为代理的方式配置在location,在locationserver下新增一个location,如下所示:

1
2
3
4
5
6
7
8
9
10
# 配置"/lb/"路径的请求全部转发到本地8080端口
location /lb/ {
proxy_pass http://test/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 50;
proxy_read_timeout 50;
proxy_send_timeout 50;
}

重启Nginx

我这里是使用brew的方式安装的nginx,所以重启的命令如下所示:

1
brew services restart nginx

如果你是安装包的方式安装:

1
2
3
4
# 进入安装包目录
cd /usr/local/nginx/sbin
# 重载
./nginx -s reload

权重配置

nginx中有一个权重的概念,根据权重值的大小来控制请求流量,当权重的配值越大时,流量分发就会越多,我们在test服务器组内配置权重解释:

  • server 127.0.0.1:8080 weight 1; 权重占比为1/3,每3次请求会转发1次到这台服务器上。
  • server 127.0.0.1:9090 weight 2; 权重占比为2/3,每3次请求会转发2次到这台服务器上。

备用配置

当我们在upstream内的server尾部添加backup时,表示这台服务器是备用服务器,只有其他服务器都停机时才会启用,我们更新时其实就利用的这一点。

运行测试

为了演示方便我们直接将本章测试项目package打包后,通过--server.port来指定运行的端口号来模拟多台服务器的场景。

1
2
3
4
5
6
# 启动127.0.0.1:8080服务器
java -jar target/use-nginx-loadbalance-upgrade-service-0.0.1-SNAPSHOT.jar --server.port=8080
# 启动127.0.0.1:9090服务器
java -jar target/use-nginx-loadbalance-upgrade-service-0.0.1-SNAPSHOT.jar --server.port=9090
# 启动127.0.0.1:9000备用服务器
java -jar target/use-nginx-loadbalance-upgrade-service-0.0.1-SNAPSHOT.jar --server.port=9000

注意:使用多个终端窗口运行服务。

nginx.conf>server中配置location的转发条件为/lb/路径前缀,所以我们访问 http://127.0.0.1/lb/test (由于nginx监听的端口号是80,所以通过nginx访问转发时不需要携带端口号)就会被转发到test服务器组内的服务器上。

测试点:权重转发

1
2
3
4
5
6
7
8
9
10
11
curl http://localhost/lb/test
端口号:8080,接口访问成功.

curl http://localhost/lb/test
端口号:9090,接口访问成功.

curl http://localhost/lb/test
端口号:9090,接口访问成功.

curl http://localhost/lb/test
端口号:8080,接口访问成功.

根据访问的结果来看,8080端口号的服务是每3次中请求了1次,而9090则是每3次中请求了2次,这一点正是符合我们配置的权重(weight),测试通过。

测试点:备用生效

我们把80809090这两个服务都停掉,再次访问 http://127.0.0.1/lb/test

1
2
3
4
5
6
7
8
curl http://localhost/lb/test
端口号:9000,接口访问成功.

curl http://localhost/lb/test
端口号:9000,接口访问成功.

curl http://localhost/lb/test
端口号:9000,接口访问成功.

可以看到我们的备用服务器启用了,已经把全部的请求流量转发到9000这台服务上,测试通过。

敲黑板,划重点

当我们把80809090都停掉时,备用服务器会启用,这时我们就可以来更新80809090这两个服务的运行代码,更新完成后重启,只要80809090这两台服务器有一台处于运行状态,nginx就不会把流量分发到备用的9000,以此类推把全部的服务都更新完成。

代码示例

如果您喜欢本篇文章请为源码仓库点个Star,谢谢!!!
本篇文章示例源码可以通过以下途径获取,目录为use-nginx-loadbalance-upgrade-service

GitHub标星超1万的Chrome插件,助你轻松查看文件Git历史

前言

之前给大家介绍过一款好用的GitHub代码层级阅读浏览器插件Octotree,该插件直接可以读取GitHub源码仓库的全部文件并生成树形层级关系,省去了连续不断地点击进入目录的操作。

GitHistory Chrome Plugin

有些时候我们需要查看源码仓库中某一个文件的修改历史记录,方便我们做一些变动的追溯,在GitHub上还真有一款大神级别的浏览器插件,该插件可以界面图形化查看某一个文件的全部修改历史记录,很是方便,今天推荐给大家。

该插件在Chrome商店内可以找到,名为:Git History Browser Extension,由Luis Reinoso提供。

它是一款开源的浏览器插件,仓库地址:https://github.com/pomber/git-history,目前Star已经超过11k。

怎么使用?

通过Chrome商店安装完成后,这时我们打开GitHub的任意仓库(这里以ApiBoot仓库为例),找到某一个文件点击后,效果如下:

可以看到在工具栏多出了一个名为Open in Git History的按钮,我们点击该按钮会跳转到 https://github.githistory.xyz/ ,效果如下图所示:

在地址栏中除了域名以外,后面的地址与访问GitHub时是一样的。

该页面分了两部分:

  1. 顶部横向滚动条

    初次访问该页面时默认是最新的提交的历史文件内容,在顶部会列出该文件的全部的提交记录,当我们点击任意一个记录时,在下面都会显示属于这个文件这次提交的内容。

  2. 底部文件历史内容

    对应顶部的提交信息当前文件的变动内容。

不能访问Chome商店?

由于网络访问受限,我们无法直接访问Chrome商店,我在之前文章中推荐了一款科学上网的神器,GHelper也是一款浏览器插件(该插件可直接通过源码方式安装)。

关注 “程序员恒宇少年”微信公众号,回复”Google”获取GHelper源码方式安装包。

使用Gitbook创建文档并导出PDF

导出PDF的方式有很多种,之前使用过马克飞象的导出功能,不过只是简单的导出并不能添加目录,因为源文件是markdown编写的,经过筛选后采用了gitbook的方式进行编写文档并且使用gitbook pdf .的方式导出为PDF文件。

在阿里Java大牛们都是这样对Java项目代码分层的

代码分层,对于任何一个Java开发来说应该都不陌生。一个好的层次划分不仅可以能使代码结构更加清楚,还可以使项目分工更加明确,可读性大大提升,更加有利于后期的维护和升级。

作为高级Java,你应该了解的Linux知识

作为一个javaer,我以前写过很多关于Linux的文章。但经过多年的观察,发现其实对于大部分人,有些东西压根就用不着。用的最多的,就是到线上排查个问题而已,这让人很是苦恼。那么,我们就将范围再缩小一下。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×