草庐IT

巧用GitHub Action实现自动化部署Java项目

Robod 2024-06-04 原文

本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star

⭐⭐⭐⭐⭐转载请注明出处:https://blog.csdn.net/weixin_43461520/article/details/127475965

前言

我在前几天写了篇文章,是说如何使用GitLab CICD实现项目的自动化部署到指定的Web服务器中,没看过的小伙伴可以去看看:你是个成熟的项目了,该学会自动构建自动部署了。但是如果是我的个人项目,我应该是不大会使用GitLab的,因为如果仅仅是为了自动化部署而去安装一个GitLab的话,对我而言代价高了点。所以我更愿意把代码放在GitHub、Gitee这样的平台。如果GitHub、Gitee能实现同样的功能,那自然是最好不过了。我本来是想用Gitee试试的,不过Gitee的自动化部署是收费的,只有200分钟的试用时间,感觉也用不了多久,所以还是用GitHub吧。

流程介绍

GitHub的自动化部署功能叫做GitHub Actions,就是图中红框的部分,而GitHub_Action是我用来测试自动化部署功能创建的项目。

它的使用方式和GitLab CICD差不多。在项目中指定一个workflow文件,然后在workflow文件中定义任务去指定具体的执行步骤,然后代码提交时,GitHub就会开一个虚拟机去执行workflow,从而达到自动化部署的功能。既然是在虚拟机中运行任务,所以理论上实现方式就有两种:

这两个方案的区别就是编译的过程是在GitHub提供的虚拟机里面还是在我们自己的Web服务器中。

如果使用方案二的话,就需要在我们自己的Web服务器中安装Maven。而本地的Maven仓库动不动就长到了几个G,我的服务器只有40G的容量,我不想让Maven仓库去占用我的空间,所以下面的讲解是基于方案一的。

workflow定义

在此之前,我们需要在Secrets中定义几个变量,用于在后面的workflow文件中引用。


这里我将Web服务器的ip密码定义在了这里。这一步其实并不是必须的,不过如果不定义的话就需要将这些敏感的信息写在workflow文件中。如果仓库是private的话,当然没有问题,但要是public的话,所有人都可以在workflow文件中看到你服务器的ip和密码了,这显然是不安全的。所以可以将一些敏感的信息定义到Secrets里面。


👆点击页面中的New workflow按钮就可以去新建一个workflow了。

👆然后就会跳到选择workflow的界面了,这里官方提供了一些,要是你觉得不适用的话,也可以点击set up aworkflow yourself去自己创建workflow。

这里面有几点说明一下:

  • 虚拟机环境:前面说过这些任务是运行在GitHub提供的虚拟机里面,所以GitHub提供了几个不同的虚拟机环境。在Documentation里也列出来了。小伙伴们根据自己的实际情况自行选择即可。

  • action:一个action其实就是一个操作,比如拉取代码、设置JDK等。这些其实都是通用的操作,如果Marketplace里面有的话,直接引用就好,不必所有的脚本都自己编写。

workflow文件中前面的内容其实都是一些环境的配置,steps里才是具体的执行步骤。

jobs:
  develop_build:
    runs-on: ubuntu-latest
    steps:
      - name: 拉取最新提交的代码
        uses: actions/checkout@v3

      - name: 设置jdk
        uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '8'
          cache: 'maven'

      - name: 项目打包
        run: mvn -B package

      - name: 删除旧的jar包以及运行脚本
        run: sshpass -p ${{secrets.REMOTE_PWD}} ssh -o StrictHostKeyChecking=no root@${{secrets.REMOTE_IP}} "cd /root/GitHub_Action && rm -rf ./*"

      - name: 上传jar包和启动脚本到服务器中
        run: sshpass -p ${{secrets.REMOTE_PWD}} scp -r -o StrictHostKeyChecking=no ./target/GitHub_Action-0.0.1-SNAPSHOT.jar ./run.sh root@${{secrets.REMOTE_IP}}:/root/GitHub_Action

      - name: 启动项目
        run: sshpass -p ${{secrets.REMOTE_PWD}} ssh -o StrictHostKeyChecking=no root@${{secrets.REMOTE_IP}} "cd /root/GitHub_Action && chmod +x run.sh && ./run.sh"

第一步将最新提交的代码拉到运行任务的虚拟机中,这一步用的是官方提供的action。

第二步设置jdk,用的也是官方提供的action,关于这个action的详细说明,可以参考https://github.com/marketplace/actions/setup-java-jdk

第三步打包。

然后将打好的jar包以及启动脚本通过scp上传到Web服务器中。**sshpass -p s e c r e t s . R E M O T E P W D s s h − o S t r i c t H o s t K e y C h e c k i n g = n o r o o t @ {{secrets.REMOTE_PWD}} ssh -o StrictHostKeyChecking=no root@ secrets.REMOTEPWDsshoStrictHostKeyChecking=noroot@{{secrets.REMOTE_IP}}**是ssh连接指定的服务器,后面引号内则是具体的shell命令,和我们在控制台写的是一样的。启动脚本run.sh是我提前写好的。

# run.sh
# 切换到jar包目录下
cd /root/XXX
# 杀死之前的项目进程。这里的cut -c9-14是截取进程id,不一定都是-c9-14
# 可以先运行ps -ef|grep java|grep GitHub_Action-0.0.1-SNAPSHOT.jar看一下进程id是第几位到第几位
ps -ef|grep java|grep XXXX.jar|cut -c9-14|xargs kill -9
# 停5秒
sleep 5s
# 使环境变量生效
source /root/.bash_profile
# 运行项目
nohup java -jar XXXX.jar >/root/cicd.log 2>&1 &

测试

现在将代码提交到develop分支后,就可以触发这个workflow。


可以看到,这个workflow已经运行完成了,访问一下我写的测试接口,也可以正常的访问,说明项目已经部署成功了:

将接口稍作修改后再提交一次:

又成功了✌️

更多更详细的用法,可以阅读官方文档:https://docs.github.com/cn/actions

⭐⭐⭐⭐⭐转载请注明出处:https://blog.csdn.net/weixin_43461520/article/details/127475965

本文已收录至我的Github仓库DayDayUPgithub.com/RobodLee/DayDayUP,欢迎Star

如果您觉得文章还不错,请给我来个点赞收藏关注

有关巧用GitHub Action实现自动化部署Java项目的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  4. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

    我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

  5. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  6. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  7. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  8. Ruby 从大范围中获取第 n 个项目 - 2

    假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit

  9. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  10. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

随机推荐