乐趣区

关于程序员:改进-Git-flow-来管理-Bitbucket-上的私有-TypeScript-依赖

在目前的工作中,Bitbucket 同时被咱们用作代码仓库和公有 NPM 仓库。通过 git+ssh 指定 tag 来装置依赖,对于纯 JavaScript 的我的项目非常不便。

随着局部依赖开始应用 TypeScript,基于现有应用形式,须要对这部分依赖采取上面的一种形式进行治理。

  1. 间接将编译后的 dist 文件提交到主分支上。
  2. postinstall 中进行编译。当依赖被装置后,就会主动编译。

但无论哪种形式,都会有一些瑕疵。

  • 间接将 dist 提交到主分支上,在做 Code review 时会额定多出许多文件烦扰,我的项目构造也不优雅。
  • 通过 postinstall 的形式对于纯 JavaScript 的我的项目就须要额定装置 typescript,同样不优雅。

出于人力以及迁徙仓库的老本思考(咱们有近 100 个依赖,且每个依赖有许多版本并且被不同的服务援用),对此只能通过改良 Git flow 来解决上述瑕疵。

指标

从新设计的 Git flow 须要满足以下指标。

  1. 开发分支上不须要编译后 dist 文件。
  2. 不须要通过 postinstall 的形式来编译。
  3. 援用的形式不产生扭转,还是通过 git+ssh 指定 tag 的形式装置依赖。
  4. 须要思考到 hotfix 的状况。

Git flow 改良

为了实现上述指标,上面是改良后的 Git flow。

对于失常的开发,当代码合并到 master 后,先推送 src tag 并批改 .gitignore 长期创立 build 分支。随后在 build 分支编译并且打上正式 tag,正式 tag 蕴含 dist 文件,能够被其余服务援用。

当须要进行 hotfix 时,就能够从对应的 src tag 上切出分支进行 fix,之后再以雷同的步骤合入 master 分支。

Pipeline 脚本设置

上述的 Git flow 在代码合并之后有打 tag、批改 .gitignore、编译再公布的步骤。即使有文档阐明,在实际操作上也很容易出错。因而非常有必要将这些步骤自动化。利用 Bitbucket Pipeline 在代码合入 master 分支时主动执行。

上面是示例代码。

  1. Pipeline 局部
branches:
  master: # 当合入主分支时才会触发
    - step:
        name: build
        deployment: Build # 以 Deployment 的形式执行,名字能够随便指定
        script:
          - git remote set-url origin ${BITBUCKET_GIT_SSH_ORIGIN}
          - ./scripts/build.sh # 理论执行的脚本 
  1. 打 tag 以及编译脚本。

pipeline 中的 build.sh,整个 Git flow 的外围。实现打 src tag、编译以及推送编译后的正式 tag。

tag 的版本遵循 semver 规定,以后 tag 为 package.json 中的 version。下一个版本则来源于分支名的前缀,比方分支名为 major/xxxx 即下一个版本升级主版本号;如果是 feature/xxx 则为 minor。利用 npm version 命令降级标签。

#!/usr/bin/env bash

set -e
# Create tags in the bitbucket pipline, env from bitbucket pipeline
source_branch=$(git log --format=%B -n 1 $BITBUCKET_COMMIT | awk '{print $3}')

if [[-n $source_branch]]; then
  # PART 1: Get the next tag
  echo "Triggered by pull request ${source_branch}"

  if [[${source_branch} == feature/* ]]; then
    level=minor
  elif [[${source_branch} == bugfix/* ]]; then
    level=patch
  elif [[${source_branch} == hotfix/* ]]; then
    level=prerelease
  elif [[${source_branch} == major/* ]]; then
    level=major
  else
    echo "Nothing happen on branch: ${BITBUCKET_BRANCH}"
    echo "Source branch: ${source_branch}"
  fi

  if [[! -z ${level} ]]; then
    # PART 2: Create src-tag and push back
    current_version=$(node -e "console.log(require('./package.json').version)") && echo "Current version - ${current_version}"
    echo "Crated version on branch: ${BITBUCKET_BRANCH}. Tag: ${current_version}"

    next_version=$(npx semver ${current_version} -i ${level})
    source_tag=v${next_version}-src

    echo "Build source tag: ${source_tag} on branch: ${BITBUCKET_BRANCH}"
    # Create the source tag and push back
    npm version ${next_version} --no-git-tag-version # This will not create a git tag just update the version in the package.json

    git add --all
    git commit -m "[skip ci] ${current_version} --> ${next_version}" # [skip ci] Will not trigger this pipeline again
    git tag -am "[skip ci] source tag: ${source_tag}" ${source_tag}
    git push origin ${BITBUCKET_BRANCH} ${source_tag}

    # PART 3: Add the dist folder and create release tag
    # Add the dist folder
    sed -i 's/dist//g' .gitignore

    # build ts
    npm run build

    # push to tag
    git add --all
    git commit -m "[skip ci] Build release tag: ${next_version} on branch: ${BITBUCKET_BRANCH}"
    git tag -am "[skip ci] release tag: ${next_version}" ${next_version} # only push the tag
    git push origin refs/tags/${next_version}
  fi
fi

Shell 脚本最好放在 Deployment 中执行。因为 Deployment 是阻塞队列,能够保障同一时间只有一个脚本在运行,从而防止 tag 反复抵触的问题。

同时对于开发分支的命名也须要做肯定的限度。比方能够应用 husky 等工具。

拓展

这一套 Git flow 能够在任何的代码托管工具应用,即使没有相似 Pipeline/GitAction 的触发形式同样也能够通过跑脚本的形式实现。同时能够实现主动打 tag 的性能。

尽管没有完满的 Git flow,但一套适合的 Git flow 也能够让咱们的工作更加标准,进步工作的效率。

本文由 mdnice 多平台公布

退出移动版