月度归档:2021年01月

工具创造者的自我修养

工具创造者的自我修养

独立开发者中有一大批人是通过做工具来获取收入的。做工具也算是独立开发者圈子中经久不衰的话题了。

但到了具体的工具开发之时,其中又有不少可以拿来讨论的内容。

而这里,我最想讨论的是工具的理念。

对于工具类的软件开发而言,最容易出现的就是「别人做了一个什么东西,我觉得不够新/便宜/不爽,我自己也要开发一个」。对于开发者来说,遇见问题, 并自己解决问题是非常常见的。 但是,工程师常常的问题也在于此,因为复制一个产品的成本越来越低,所以最先选择的是复制,而不是思考这个产品的长期发展道路。这会让产品陷入简单的 Copy and Paste 的模式下,长期来看,并不利于产品发展。

在我看来,如果工程师想要做好一款工具,那么一定要为自己的工具准备一个最基本的方法论。这个方法论一定是基于你自己对于问题的看法做出的拆解,而不能是依赖于其他第三方软件的。

这个方法论将指导你的产品朝着最终的目标,要解决的问题,奋力前行。你后续所遇见的问题,都会成为你前行的助力,为拓宽前进的道路。

而一个没有方法论的产品,则会被途中遇见的各种问题引导偏离最初的目的地。我们目前的市场中有太多的工具了,每一款工具都有其优秀之处,倘若没有自己核心的理念,那只会被众多的 Feature 搞得「乱花渐欲迷人眼」,最终失去了自己对于工具的定位,抄成了一个四不像。

总结

如果你想要以一个小团队打造一款好用、生命力持久的工具,那么先想清楚你的目标和理念,再动手开发,是一个好的路子。需求有很多,但并不是每一个都适合你。工具有很多,也不是每一个都适合你,预期去抄别人的理念,做别人要做的工具,不如发现自己的需求,做自己的工具。

物联网设备如何链接到你的小程序?

物联网设备如何链接到你的小程序?

物联网项目在涉及到传统行业的数字化改造时,是一个非常常见的选择。通过对于传统的物联网设备进行改造,就可以和云计算设备链接起来,并辅以大数据设施,完成对于产业的优化和迭代。

而到了具体物联网设备和小程序开发时,主要有以下几种链接方式:

直接链接 · 蓝牙

蓝牙链接物联网设备算是最为常见的方式。小程序提供了蓝牙的接口,你只需要调用蓝牙接口,链接到物联网设备上,并读取数据,就可以实现和物联网设备的链接。

比如你可以使用小程序来链接小米手环(如果你知道他的蓝牙配置)。

直接链接 · NFC

小程序提供了 NFC 接口,有了 NFC 接口,你就可以调用机身自带的 NFC Reader 和 NFC Writer 对 NFC 卡片进行读取和写入,来完成和外部设备的交互。

对于 Android 用户来说,使用 NFC 交互可以快速完成近场通讯的数据同步问题。

直接链接 · WiFi

小程序提供了 WiFi 接口,如果你的物联网设备可以对外提供 WiFi 服务,则可以通过调用 WiFi 接口,连接到指定 WiFi,并通过标准的 HTTP 接口来获取数据。

间接链接 · WiFi

WiFi 除了可以用作直接链接,还可以用作间接链接,你可以让设备通过 WiFi 连接到互联网上,并通过 HTTP 协议与服务器进行沟通,从而与服务器之间进行交互,交互完成后,你就可以在小程序端直接读取数据了。

间接链接 · NBIoT

NBIoT 你可以简单理解为手机卡链接,只不过使用的是物联网卡和2G/3G模组。如果你的设备上链接了 NBIoT 设备,就可以直接通过 NBIoT 设备访问到你自己的服务器,并提交信息。

总结

物联网的链接方式随着基础设施的迭代,会有不断的更新。如果你知道有别的方法, 欢迎留言告诉我。

如何将 HTTP 请求中的 UA 转化为可读的 UA 信息

如何将 HTTP 请求中的 UA 转化为可读的 UA 信息

什么是 UA (User Agent)

UA 是 HTTP 在发送请求的时候,带上的请求方的各项基本信息。就我自己为例,我的 UA 是 Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36 Edg/88.0.705.50

这个 UA 当中包含了大量的我的基本信息,包括我的电脑信息、我的操作系统、浏览器的版本等。

在具体的 UA 信息中,具体的结构为

User-Agent: <product> / <product-version> <comment>

如果有多组 UA 信息,则语法如下

User-Agent: Mozilla/5.0 (<system-information>) <platform> (<platform-details>) <extensions>

UA 能够帮助我们理解什么?

UA 可以提供设备的基本信息,比如浏览器、比如设备的版本号等,有了这些信息,我们就可以分析用户的使用习惯、使用场景等信息。

比如,当 UA 中有大量的访问是来自微信浏览器,那么你就可以考虑针对微信的浏览器提供一些优化,比如使用微信自带的第三方 SDK 等信息。

如何将 UA 转换为可读的 UA 信息?

各种语言都有自己的 SDK 来实现从 UA 的 String 提取出操作系统的信息,一般来说,都是通过正则表达式来识别的,你可以在 Github 上找到你所使用的语言提供的 SDK。

不过,除了使用开源的 SDK 以外,你还可以考虑使用一些服务来进行解析,比如我今天发现的 User Stack

UserStack 是一个 UA 识别服务,如果你接入该服务,就无需自己维护 User Agent 的识别规则,由服务帮你维护,你只需要调用该 API 即可实现对设备的识别。

总结

UA 转换为人类可读的信息需要通过第三方 API 或开源的 SDK 来实现,你可以根据自己的需要来选择不同的方案。SDK 免费可用,但可能更新不够频繁,无法很好的兼容一些重要的设备。

如何修复 Beego 运行测试时的报错 undefined: web.Trace

如何修复 Beego 运行测试时的报错 undefined: web.Trace

Beego 近来已经更新了 2.X,因此,你现在可以使用更新版本的 Beego 来完成你的快速开发。

不过,beego 2.x 在使用 bee 工具初始化一个新的项目时,默认的项目中有一个 bug,当你在项目根目录下执行 go test ./... 时,会提示 tests 目录中有一个错误。而你并没有修改任何的源文件。

如果单独执行 tests 目录,就会报错如下内容

tests/default_test.go:28:2: undefined: web.Trace

你会发现这段代码指向了 default_test.go 中的这行代码。

beego.Trace("testing", "TestBeego", "Code[%d]\n%s", w.Code, w.Body.String())

这段代码中的 Trace 找不到导致无法正常使用。

我通过一些搜索,找到了答案。在 GitHub 中,beego 的 repo 下有一个 issue 和一个 pull request 与这个 bug 相关。结论是这个方法已经被移动到 log 文件夹,因此需要调整一下输出的来源。

在代码中引入 "github.com/beego/beego/v2/core/logs" 并将 beego.Trace 替换为 logs.Trace ,即可解决这个问题。

修改后的代码如下:

package test
import (
    "net/http"
    "net/http/httptest"
    "testing"
    "runtime"
    "path/filepath"
    _ "backend-server/routers"
    "github.com/beego/beego/v2/core/logs"
    beego "github.com/beego/beego/v2/server/web"
    . "github.com/smartystreets/goconvey/convey"
)
func init() {
    _, file, _, _ := runtime.Caller(0)
    apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".." + string(filepath.Separator))))
    beego.TestBeegoInit(apppath)
}
// TestBeego is a sample to run an endpoint test
func TestBeego(t *testing.T) {
    r, _ := http.NewRequest("GET", "/", nil)
    w := httptest.NewRecorder()
    beego.BeeApp.Handlers.ServeHTTP(w, r)
    logs.Trace("testing", "TestBeego", "Code[%d]\n%s", w.Code, w.Body.String())
    Convey("Subject: Test Station Endpoint\n", t, func() {
            Convey("Status Code Should Be 200", func() {
                    So(w.Code, ShouldEqual, 200)
            })
            Convey("The Result Should Not Be Empty", func() {
                    So(w.Body.Len(), ShouldBeGreaterThan, 0)
            })
    })
}

参考阅读

如何使用 GitHub Action 自动部署 MKDocs

如何使用 GitHub Action 自动部署 MKDocs

MKDocs 是一个基于 Python 写成的文档生成工具,在实际的使用过程中,我们可以借助 GitHub Action 来实现自动部署到 GitHub Pages 。

操作流程

首先,你需要先在本地生成一个 MKDocs 项目

生成后, 你可以在项目的根目录创建 GitHub Action 所需目录。

mkdir -p .github/workflows/

并创建一个配置文件 publish_docs.yml

name: Publish docs via GitHub Pages
on:
  push:
    branches:
      - main
jobs:
  build:
    name: Deploy docs
    runs-on: ubuntu-latest
    steps:
      - name: Checkout main
        uses: actions/checkout@v2
      - name: Deploy docs
        uses: mhausenblas/mkdocs-deploy-gh-pages@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          CONFIG_FILE: mkdocs.yml
          EXTRA_PACKAGES: build-base

创建完成后,将配置文件添加到版本控制中,并提交到 GitHub 上,就可以在你提交代码的时候,自动推送到 GitHub Pages 中。

需要注意的是,我使用的是 MKDocs 的 Material Design 主题,如果你使用的是其他主题(非自带的主题),则需要修改 EXTRA_PACKAGES 的配置。

代码解读

这个配置文件中主要是 on 和 steps 比较有学习的价值。

on:
  push:
    branches:
      - main

这段代码限制了,只有在 main 分支上,出现了 commit 的时候,才会触发这个 action 的执行,如果是其他的分支,则不会触发 action 的构建。

    steps:
      - name: Checkout main
        uses: actions/checkout@v2
      - name: Deploy docs
        uses: mhausenblas/mkdocs-deploy-gh-pages@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          CONFIG_FILE: mkdocs.yml
          EXTRA_PACKAGES: build-base

这里的两个 step, 第一个是 clone 出所有的代码, 第二个 step 就是我使用一个已经做好的 action mhausenblas/mkdocs-deploy-gh-pages@master,这个 action 的作用就是将 mkdocs 的文档生成并部署到 GitHub Pages 中。

这个 action 自带了 material design 的主题,执行后,会构建并推送到 GitHub Pages。如果你使用的也是这个主题就可以直接按照我的样式进行配置。如果你使用的不是这个主题,则需要将你的主题配置在 EXTRA_PACKAGES,从而让 action 在执行的时候安装相应的 package。

总结

GitHub Action 的 Marketplace 中有大量的现成 Action 可以供你使用,借助现成的 Action ,你可以非常简单的完成自己的 CI/CD 流程,非常方便。

失望的横店之旅

失望的横店之旅

很久没有出来玩,就飞了一趟杭州,见了老朋友妙正灰,就匆匆来到了横店,毕竟作为中国影视城的头把交椅,横店影视城还是让我比较期待的。

不过,实际来到横店后,却没有那么美好。

  1. 交通不便:横店全称应该是浙江省义乌市东阳市横店镇,没错。名满全国的横店只是一个镇。而且是一个离义务比较远的镇。我从义乌站出发,到横店我住的酒店大概花了一个小时多一点。着实不算近。除非你是自己开车来玩,不然确实体验一般。
  2. 基础设施一般:横店影视城固然声名远扬,但毕竟横店只是一个镇,在生活的各方面基础上还是不如我们所熟悉的大城市。吃的方面完全不如我们熟悉的大城市。如果你指望来横店吃点好的,可能是没有戏了。
  3. 影视城粗制滥造:横店影视城拍了很多电影,所以我以为会非常不错,但实际去了明清宫苑和香港街·广州街之后,我觉得他们在影视城的实际建设上可能并没有花费的太多心思,我只能感叹说,可能现在的影视剧集的滤镜给的太足了,我在电视中完全看不到这么粗制滥造的基础设施。

不过,横店还是有一些不错的:

  1. 艺人确实多:吃晚餐和吃早餐的时候,我各自碰到一组艺人,相比于你在其他城市(除北京外),可能确实会更容易碰到艺人。
  2. 酒店还不错:我这次来住的是双十一买的横店酒店 +门票套餐,住的是百老汇大厦,这个酒店虽然离市区稍微远了一些,但也更加安静。服务什么的也不错。作为一个度假酒店应该还是比较舒服的。

总结

总的来说,横店如果你有更好的选择,不值得去。不过这个地方蛮适合带小孩子来,一下子带小孩子们拍拍照,也不错。

LCTT 从Travis CI迁移到 GitHub Action 实践

LCTT 从Travis CI迁移到 GitHub Action 实践

LCTT 的 CI 已经在 Travis CI 上运转了多年,一致保持着良好的使用体验。自 2019 年 Github 推出了自家的 CI 工具 Github Action 后,我们就在考虑将 CI 从 Travis-CI 迁移到 Github,以降低维护和沟通的成本,并借助于 GitHub Action Marketplace 实现更强的功能。

项目首页
项目首页

最近,因为 TravisCI 屡屡部署出错,而我们的账户因为使用的较多,已经超出了免费使用的限制,以此为契机,将 CI 从 Travis CI 迁移到 GitHub Action。

Travis CI 的提醒
Travis CI 的提醒

项目介绍

Translate Project 是 LCTT 翻译组的主要协作项目,几百位译者通过 GitHub 进行围绕开源、Linux、软件工程等领域的文章翻译,从 2013 年来,累计了大量的 Commit,致使项目下有非常多的文件。

Transalte Project 借助于 CI 帮助译者进行基本的文章格式进行检查;并定时执行命令,以进行所有的文章检查,对于超时未完成翻译的工作进行回收;对于文章的状态进行标记,生成相应的 Badge。

生成 badge
生成 badge

迁移思路

Travis CI 和 Github Action 在使用方面,其实总体差异不会太大,都是基于 YAML 文件格式来编写配置文件。不过,和 Travis CI 不同的是,Github Action 支持多个不同的配置文件,因此,你可以根据不同的场景,设定不同的配置文件,降低单个配置的文件的复杂度。

此外,由于我们的脚本中依赖了一些 Travis CI 的环境变量,也需要将其替换为 Github Action 中的相应环境变量,从而确保脚本可以运转。

改造实践

1. 分析之前的 CI 流程

我们在 TravisCI 上的 CI 配置文件如图

配置文件
配置文件

总体可以分为三块:

  1. 命令区:说明了安装阶段和执行阶段的操作有哪些
  2. 条件区:指定了这个配置文件在哪些条件下会生效
  3. 部署区:写明了构建产物如何进行部署

在命令区中,有预置的安装过程和后续的执行过程。在安装过程中,安装了一些依赖,并将当前的 pages 资源克隆到本地,以继承上一次构建生成的资料。

在条件区则指明了仅作用于 master 分支

在部署区便是将前面命令区的执行结果进行部署。

基本流程
基本流程

在实际的执行过程中,还会根据环境变量不同,决定是否要执行特定的命令,这部分在后续的改造过程中,就可以调整部署,拆分到不同的文件中。

构建流程
构建流程

2. 直译配置文件

在完成了基本的分析后,就可以建立新的 Action 配置文件了。由于基本的语法很类似,对于其中的不少内容可以进行直译。

比如,我们的配置文件在直译后,结果如下

直译后的结果
直译后的结果

直译的文件已经可以直接运行,不过,这里有很多不满足需要的地方,所以需要做一些修改。

3. 恢复 Travis CI 的环境变量

由于我们使用的 Badge 等生成脚本并非我所编写,所以在这一次的迁移中,并不打算对齐进行调整,以避免出现故障。而脚本中依赖了一些变量,需要将其重新设置出来。

Github Action 提供了一些方法,可以让你手动设置环境变量。你可以在你的构建的 step 中,加入如下代码,从而在构建环境中设定 TRAVIS_BRANCH 和 TRAVIS_EVENT_TYPE 环境变量,确保你可以使用这个环境变量。

 - name: Set ENV variables
        run: |
          echo "::set-env name=TRAVIS_BRANCH::${TRAVIS_BRANCH:-$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')}"
          echo "::set-env name=TRAVIS_EVENT_TYPE::$(if [ "schedule" == "$" ]; then echo "cron"; else echo "$"; fi)"

此外,由于 set-env 这个方法相对比较危险,你还需要在环境变量中,开启危险函数的执行。

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      ACTIONS_ALLOW_UNSECURE_COMMANDS: true

4. 拆分配置文件

Github Action 和 TravisCI 不同的一点是你可以将你的 CI文件拆分成多个文件,从而降低每一个单独的配置文件的复杂度。

根据前面对于流程的分析,可以将我们的 CI 流程拆分成三个部分:

  1. 生成 badge 文件,应当跟随每一次 commit 进行
  2. 生成 status 文件,执行时间较长,可以定期执行
  3. 根据 Pull Request 内容进行整理,做核验

则将我们的配置文件拆分成三个不同的文件

也得益于拆分开,则在 checker 中就可以免于安装一些必要的依赖,从而精简 CI 流程,提升 CI 的执行时间。

5. 测试 CI 的运行情况

在完成了配置文件的编写和拆分后,就可以进行本地的执行测试。Github Action 写完了,难免要执行一下,确保整个流程是正常的。

这个时候你可以安装工具(https://github.com/nektos/act),来在本地执行 action ,从而确认你的代码执行是正确的。

如果你是 macOS ,只需要执行 brew install act 就可以安装 act 工具,来完成 act 的安装。

安装完成 act ,就可以通过执行 act 命令来在本地执行 action ,比如,执行 act pull_request来触发 GitHub 的 Pull Request 事件

通过本地测试后,再将你的配置文件推送到 GitHub 上,进行生产环境的测试即可。

6. 移除 Travis-CI

通过上述的一些步骤,我们完成了从 Travis CI 到 GitHub Action 的迁移,此时,就可以移除项目根目录中的 .travis.yml 文件,彻底关闭 travis-ci。

7. 修改 GitHub 的 Branch 保护条件

为了确保修改符合标准,我们限制了新的 Pull Request 必须通过 CI 检查,才能合并进入 master,因此,也需要修改相应的分支保护规则,确保设定相应的保护。

一些注意事项

1. 环境变量不同

如果你依赖了环境变量,则需要进行相应的修改。或者可以像我一样,先通过 set-env 来让本地拥有临时的环境变量,后续再逐步进行迁移。

2. Action 运行依赖要注意安全

Action 执行过程中会有两个部分。action 本身流程依赖于 master,但执行过程中调用的脚本是根据 source 决定的,因此,从安全角度来看,你应当尽可能将所有的流程放在 Action 中,而不是放在你的源码目录中。

总结

通过对 TravisCI 的流程整理、代码修改等流程,我们将之前的 Travis-CI 迁移至速度更快、性能更好的 GitHub Action ,一方面可以优化我们的工作流,另一方面,也让我们的代码更加简洁明了。

对于还在使用 Travis CI 的项目来说,也可以考虑迁移到 GitHub Action 中,来优化自己的工作流。

参考阅读

  • https://mauricius.dev/run-and-debug-github-actions-locally/
  • https://jeffrafter.com/working-with-github-actions/
  • https://developer.okta.com/blog/2020/05/18/travis-ci-to-github-actions
拯救老旧 Discuz 的 Flash 上传

拯救老旧 Discuz 的 Flash 上传

Discuz 目前依旧是一个非常重要的建站程序,不少老的站点依旧会使用 Discuz 上运转。
由于 Discuz 是一个多年的程序,所以在系统的设计上,有很多地方充满了对老旧系统的兼容。

比如,Discuz 的上传使用的是 Flash 上传,但在 2021 年,Flash 已经彻底停止使用了,这个时候你就需要使用自己的方式来进行上传。

这里我以 Linux 中国进行的相关改造为例来介绍。

Linux 中国的文章发布系统就是基于 Discuz 实现的,编辑器层面使用的是 Discuz 提供的 TinyMCE,

Discuz 提供了一个基于 Flash 的上传组件,但在2021 年,现在这个 Flash 按钮已经完全显示不出来了。

上传组件

这个时候,你就需要自己实现一套上传系统。

由于 Linux 中国的很多底层实现都是基于 Discuz 进行的,因此,此次改造希望继续沿用 Discuz 的系统。

实现路线

在对 Discuz 默认的 Flash 插件进行抓包后,很轻松的就找到了 Discuz 的 Flash 上传组件的接口:/misc.php?mod=swfupload&action=swfupload&operation=album

这个接口接受 Form 表单作为参数,并在表单中接受一个 Hash 作为身份校验,用来判断请求的合法性。

因此,只需要在 TinyMCE 自带的上传功能中加入相应的 Hash 和表单提交的能力,就可以将 Discuz 实现的上传功能改为用 TinyMCE 的原生组件实现。

而 Hash 可以通过分析得出,其算法为 md5(substr(md5($_G['config']['security']['authkey']), 8).$_G['uid'])

因此,需要做的便是,在页面中注入 Hash ,并在 TinyMCE 中调用此值,实现上传功能即可。

样例代码

html/template/default/portal/portalcp_article.htm 文件顶部加入如下代码,从而在文章发布页面注入 hash

<!--{eval$swf_hash =  md5(substr(md5($_G['config']['security']['authkey']), 8).$_G['uid']); }--><script type="text/javascript">var FORMHASH = "{$swf_hash}"</script>

html/static/js/editor_tinymce.js 中的 tinyMCE 配置中添加如下配置项目,即可调用 HASH 来上传文件。从而实现文件的上传。

        images_upload_url: "/misc.php?mod=swfupload&action=swfupload&operation=album",
        images_upload_credentials: true,
        images_upload_handler:function(blobInfo, success, failure, progress) {
            var xhr, formData;
            xhr = new XMLHttpRequest();
            xhr.withCredentials = true;
            xhr.open('POST', '/misc.php?mod=swfupload&action=swfupload&operation=album');
            xhr.upload.onprogress = function(e) {
                progress(e.loaded / e.total * 100);
            };
            xhr.onload = function() {
                var json;
                if (xhr.status === 403) {
                    failure('HTTP Error: ' + xhr.status, {
                        remove: true
                    });
                    return;
                }
                if (xhr.status < 200 || xhr.status >= 300) {
                    failure('HTTP Error: ' + xhr.status);
                    return;
                }
                json = JSON.parse(xhr.responseText);
                if (!json || typeof json.bigimg != 'string') {
                    failure('Invalid JSON: ' + xhr.responseText);
                    return;
                }
                success(json.bigimg);
            };
            xhr.onerror = function() {
                failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
            };
            filenameArray = blobInfo.filename().split(".");
            formData = new FormData();
            formData.append('Filedata', blobInfo.blob(), blobInfo.filename());
            formData.append('Filename',blobInfo.filename() );
            formData.append('type','image');
            formData.append('Upload','Submit Query');
            formData.append('uid',discuz_uid);
            formData.append('filetype',"." +filenameArray[filenameArray.length-1]);
            formData.append('hash',FORMHASH);
            xhr.send(formData);
        },
        file_picker_callback: function(cb, value, meta) {
            var input = document.createElement('input');
            input.setAttribute('type', 'file');
            input.setAttribute('accept', 'image/*');
            input.onchange = function() {
                var file = this.files[0];
                var reader = new FileReader();
                reader.onload = function() {
                    var id = 'blobid' + (new Date()).getTime();
                    var blobCache = tinymce.activeEditor.editorUpload.blobCache;
                    var base64 = reader.result.split(',')[1];
                    var blobInfo = blobCache.create(id, file, base64);
                    blobCache.add(blobInfo);
                    cb(blobInfo.blobUri(), {
                        title: file.name
                    });
                };
                reader.readAsDataURL(file);
            };
            input.click();
        },

总结

老旧系统的升级改造不可怕,只要你用心,从业务的底层抽丝剥茧,就能找到要解决的问题。剩下,不过是代码层间的问题罢了。

被 GitHub Action 坑了半天…

被 GitHub Action 坑了半天…

我这几天在忙着搞 LCTT 的 Travis-CI 迁移到 Github Action 。整体的 CI 的流程都已经迁移完成了,但是一个特定的检查脚本死活无法正常运行。

在这个过程中我尝试了多种办法,比如修改代码、调整里面的参数、打印其中的参数,似乎都是工作运行正常的。

将项目代码 clone 到本地后,发现代码在本地运转也是正常的。

我一直不知道问题出在哪里,百思不得其解。直到我在跑了几百次 Action 构建后,我发现,Github 默认的 checkout 插件是有问题的。

和标准的 git clone 不同, Github 默认的 Checkout 插件在实际 clone 项目是使用的不是 git clone 命令,而是采用先在本地 init 一个目录,并添加相应的 remote ,并 fetch 代码下来。

github action
GitHub Action 的 Clone

这样的好处是在处理的时候,只会 fetch 到特定的分支到本地,而不会将默认的其他分支一同 clone
到本地。但坏处就是你在执行的时候,只能针对特定的分支进行操作。

而检查脚本则是基于 git 本身的命令进行执行的,因此是需要比如 master 这样的分支的,这就导致在使用了默认的 checkout 插件的时候,检查脚本无法使用。

Travis-CI 的表现
Travis CI 的 Clone

与之对比的,是 Travis CI 在执行 Clone 的时候,采用的是全量 Clone ,再单独 Fetch 某个特定分支。从这个角度上来看,我可以理解 Github Action 为什么会 Clone 的更快一些。不过,这种 Clone 的方式确实给一些 CI 在 Check 时留下隐患。

总结

如果你在 Github 中使用默认的 Checkout 插件获取项目以后,执行 Git 操作出现了问题,很有可能是插件自己的问题,而不是你的问题。你可以选择自己构建 clone 命令,避免这个问题。

GTD 熔断系统

GTD 熔断系统

我目前用的清单是 Things ,很好用。

不过,当我有一些突发事项进入时,就需要放弃原有优先级来处理。这个时候我就需要一个方案来处理焦头烂额的各项事务。

我将这个方案称之为 —— GTD 熔断系统。

GTD 熔断系统是在我的任务系统崩溃之后,切换的新的任务方案。

新的任务方案很简单,基于纸笔进行,

我会将我现在需要做的最紧急的若干事项,摘抄到笔记本上,并根据当下的紧要程度进行排序,逐一完成相关的工作和任务。直到完成后,再重新打开 Things ,提取任务事项,摘抄并复制到笔记本上。

熔断系统对于我来说,最大的好处是

  1. 让我关注当下最紧要做的事情,从而尽快从熔断的状态中离开。
  2. 让我不需要被 Todo List 中长长的项目所困扰,而是更加关注我眼前的几个项目,从而减少自己的焦虑。

为什么不直接用 Things?

Things 目前要实现这样的功能,只能使用修改时间的方式,但修改时间会出现忙完会忘记,从而让不紧急的事情变得紧急,独立出来的新的系统则可以有效的避免这个问题。

要不要为了健康放弃爱好?

要不要为了健康放弃爱好?

我一直以来对于喝酒的态度都是:

酒是一种社交工具,如何你需要我陪你喝且我觉得我应该陪你喝,那我可以陪你喝。断片为止

我平日里喝的比较多的是咖啡,然后偶尔换为茶叶(因为我经常会因为咖啡喝的太多而失去了提神的效用)。对于酒来说,我基本上是能不喝酒就不喝酒。能以茶代酒就以茶代酒。

今天在群里大家在聊喝酒的问题,我就在想,如果知道喝酒不健康,你还会选择喝酒么?

那我觉得这个问题的一个 Point 是你在关注什么?

我们的一生中有很多关注的点,有些点重要,有些点不重要。我们可能会权衡其中的一些点。

那对于我来说,酒是一种工具,我不对酒有太多的想法,仅仅是一种饮料,一种工具。

对可能对于一些人来说,酒本身就是目标,因此,他们可能会在酒上面去花很多功夫。


群友精彩讨论

健康还是相对的

群友 Phoenix·HDR
在 macOS 下创建启动 U 盘

在 macOS 下创建启动 U 盘

因为要重装 Mac mini ,所以研究了一下怎么配置启动 U 盘。

依赖

想要给 U 盘制作一个 macOS 的启动盘,首先,你需要有一个 macOS 的系统,并且有相应的安装软件(Install macOS Catalina 之类的)。此外,还需要有相应的容量 U 盘。

根据 macOS 的系统大小,我比较建议你使用 8G 或 16G 以上的 U 盘。

获取安装软件

由于安装软件比较大,所以一般情况下我们也不会保留这个软件,但当我们需要的时候,就要去安装对应的软件了。

你可以访问 Apple 的官网,找到相应的软件下载地址

系统下载地址:https://support.apple.com/zh-cn/HT211683

如果你已经升级了 Big Sur ,却希望制作 Catalina 的启动盘,那么你需要看看 这篇文章

选择你需要使用的系统

会自动打开下载界面

你只需要点击其中的获取,就可以下载相应的系统镜像。等软件自动下载并安装完成后,就可以进行安装操作了。

查看 U 盘挂载路径

想要制作启动 U 盘,自然要说明对应的路径,这个时候你需要先找到你自己的 U 盘。

你可以在终端中执行 df -h ,在其中找到你自己的 U 盘,比如我这里的是 /Volumes/install

制作启动盘

准备好软件和U盘后,剩下的比较简单,直接执行命令即可。

以 Catalina 为例,只需要执行如下命令

sudo /Applications/Install\ macOS\ Catalina.app/Contents/Resources/createinstallmedia --volume /Volumes/MyVolume

其他版本的系统可以参考 https://support.apple.com/zh-cn/HT201372