利用Gitlab CI将代码部署至FTP服务器

作为Github的拥趸,最初这篇文章的标题是《利用Github Travis CI将代码部署至FTP服务器》。本来盘算的很好,利用这篇文章,一来是记录一下自己解决的问题,二来是宣传一下Github是多好用。
众所周知,Github等一众在线同性交友代码托管平台随着开发方法论的不断进化,已经演变成了CI/CD平台。哪家平台要是说自己不支持CI/CD,都不好意思出来打招呼。而Gitbub原来并没有自己的CI/CD功能,Travis CI充当了这一角色。最近,Github也推出了自己的Gitbub Actions来弥补这一块空缺,目前仍然在beta阶段。我也申请了测试资格,但目前仍然没有轮到我。

作为个人立场,很喜欢使用Github来托管代码。以前免费账号只能托管公开仓库,而收费账户又舍不得银子,无奈只能把私有仓库分散在Bitbucket和Gitlab上。
后来大家都知道了,Github被微软收购之后,免费账号也可以托管私有仓库了。我就琢磨着把所有repo都集中到Github上吧,结果猜怎么着?Travis CI免费版仍然只能用在公开仓库上。只好作罢。

当然,这次放弃Github+Travis CI组合的原因之中,Repo必须公开是其中一方面。另一方面是在使用Travis CI时遇到了无法解决的问题。

俗话说,先有问题才有的工具,而不是先有的工具而后产生的问题。首先说这次要解决的问题是什么。
其实这个问题很简单。平时在写文章或者写插件的过程中会遇到一些不懂的web技术,然后就需要做一些小demo或者简单的概念验证放到我自己的服务器上。由于有多设备切换开发的需求,任何代码都要放在远程git上做版本管理与同步。这样的话,就会出现一个稍许繁琐的操作————改完代码之后,要先commit到本地仓库,然后再push到远程仓库,然后将本地文件通过FTP工具上传到服务器,之后在浏览器打开网站进行测试,如果有问题则循环本套操作。

如果在我将代码提交到远程仓库之后,能够自动部署到FTP上该多好啊~!
很久很久以前,在SFDX还没发布的那个年代,我曾经利用GitHub+Travis CI做过一个Salesforce StandardSetController的小Demo的自动部署。每次提交完改动,就能自动部署到指定环境。我觉得部署到FTP怎么也得比部署到Salesforce Org还要简单吧!

说干就干,由于对Travis CI还算熟悉,立马查了一下文档,自信满满的写下了如下的yml文件。

# .travis.yml
language: node_js
script:
- echo "skipping tests"
after_success:
- curl --ftp-create-dirs
       -T index.html
       ftp://${FTPUSER}:${FTPPASSWORD}@${FTPENDPOINT}

语言无所谓,测试跳过,直接将文件通过ftp传送到服务器上。
结果执行之后,发现不对劲了。正常传送一个文件不说是瞬间完成,也不至于10分钟都传不完,导致被Travis强行把任务中止吧?然后去FTP上瞧了一眼,文件是创建出来了,但是大小是0KB。这肯定不对劲啊,查查吧。结果查到一篇Travis的官方博客,解释他们的NAT因为什么什么原因,导致FTP的被动模式失败之类的。总之就是ftp命令不能用了。
那行,我改用sftp命令。结果这次直接报错了,说不支持sftp命令。Execuse me? 然后搜了大半天,也没找到什么靠谱的解决方案。这就让人觉得不可思议了,对于CI工具来讲,FTP上传不比连接AWS、Heroku之类的简单多了?

正在感到弱小无助之际,我想起了一直在默默当备胎的Gitlab。
Gitlab也有自己的CI/CD工具,并且是免费,且可以用在私有Repo上的。
但是Gitlab的yml文件语法与Travis不同,只好硬着头皮速读了一下Gitlab CI的yml写法。
经过不断的研究与尝试,终于写下了如下的yml文件。(其实是从sample yml文件改造出来的)

# .gitlab-ci.yml
# This file is a template, and might need editing before it works on your project.
# Full project: https://gitlab.com/pages/plain-html
pages:
  stage: deploy
  script:
    - mkdir .public
    - cp -r * .public
    - mv .public public
    - apt-get update -qq && apt-get install -y -qq lftp
  artifacts:
    paths:
      - public
  only:
    - master
  after_script:
    - lftp -c "set ftp:ssl-allow no; open -u $USERNAME,$PASSWORD $HOST; mirror -Rev public/ ./ --ignore-time --parallel=10 --exclude-glob .git* --exclude .git/"

任务名称随意,artifact就是本次部署的全部文件归档,这里文件夹名字叫public。为了使用lftp命令,在脚本中提前安装lftp命令。
在CI/CD的setting页面提前配置好USERNAME, PASSWORD, HOST三个变量可以避免将敏感信息放到仓库文件中。
接下来在Gitlab仓库中启用CI/CD,就可以享受了。

其实同理,既然能用Gitlab CI部署代码到FTP,也能部署代码到Salesforce。之后还会写一篇Salesforce的兄弟篇。而这篇文章呢,也不想写CI/CD是什么,也不想谈论DevOps的优势,毕竟这种东西用关键字一搜索,满大街都是,感兴趣的人在看到文章头两个自然段之后早就自己去搜了。毕竟我说它千好万好,不如举一个实际的,好上手的例子让大家看到实实在在的东西来的实惠。

// 后记

也很长时间没有更新了。有人问我哪去了。其实。。。这期间发生了很多事情,也经历了很多事情。素材也是越攒越多。奇怪的是素材攒的越多越觉得没什么值得写的东西。可能,大家都在进步,对于Salesforce平台的基本认知已经都跨越了那道门槛,现在更需要的是Salesforce这款产品以外的,更关乎于计算机世界的、网络世界的基础知识,软件工程的基本概念。还有对于各个行业是如何运转的行业基本了解。

随着年龄增加,进入到了人生的不同阶段,会发现你完全属于你自己的时候越来越少。你逐渐被必须要承担的各种角色完全瓜分。以前争不到的东西现在更加的争不到,原来拥有的东西反而越丢越多。Whatever,要不然又能怎样呢,要不然选择随波逐流,要不然选择自己受的苦自己咽下去,你敢选第三条路吗?(摊手)