GIT OPS

Git Ops Framework facilitating (semi) automated flows:

  • Publish my branch

Dev Environment - Setup

Expression

Description

Example

Idea

alias git-tag="${PWD}/scripts/git-tag.sh"

Tag HEAD, local and remote

git-tag auto-release

Facilitates Git-Ops, given input tag

function git-tag { git tag -d "$1"; git tag "$1" && git tag push origin -d "$1"; git push origin "$1"; }

Tag HEAD, local and remote

git-tag auto-release

Facilitates Git-Ops, given input tag

function parse-version { grep -E -o '^version\s*=\s*\".*\"' pyproject.toml | cut -d'"' -f2; }

Parse Version from pyproject.toml

parse-version

Query Single Source of Truth

Github - setup

There multiple phases of the porcess where we want to achieve behaviour such as:

  • Merge Branch A to Branch B, after its corresponding PR’s Required Checks Pass.

We leverage Github Branch Protection Rules, while timely enabling Auto Merge on github PRs, to achieve such behaviour.

We expect Protection Rules to be in place for below Branches:

  • master

  • release-train

  • test-distro

  • test-docs

  • test-distro-docs

How-to: enable Auto Merge for your github repo

  1. Navigate to the General Repo settings on github.com Go to https://github.com/boromir674/cookiecutter-python-package/settings and enable checkbox Allow auto-merge, as shown in the sample github screenshot, below:
    Alt text

Publish my Branch - Flow

Here you can find the definition of Publish my Branch Flow and How-to guides.

Definition of Publish my Branch Flow

The Publish my Branch Flow is a process, where the User changes are shipped / released to production.

Assumptions:

  • the User / Developer made all their changes on a User Br branch

  • there is a dedicated main / master branch, for tagged production commits (public API)

Thus, a starting git state should look like below:

%%{init: { 'logLevel': 'debug', 'gitGraph': {'showBranches': true, 'showCommitLabel':true,'mainBranchName': 'main / master'}} }%% gitGraph commit id: "[NEW] Gen 1.2.0" type: HIGHLIGHT tag: "v1.2.0" commit id: "[NEW] Gen 1.2.1" type: HIGHLIGHT tag: "v1.2.1" commit id: "[NEW] Gen 1.3.0" type: HIGHLIGHT tag: "v1.3.0" branch "User Br" commit commit id: "new feat"

How-to: initiate the Publish my Branch Flow

Assuming Github and Dev Environment, are properly setup.

  1. Run in terminal

    git push
    git-tag board-request
    

    This should Automatically Trigger the pr-to-boarding Workflow, which:

    1. Opens PR from User Branch to boarding-auto

    2. Labels PR, based on files changed

    3. Labels PR, for Auto Merge into Train

    4. Merges PR User Branch –> boarding-auto

    5. Opens PR boarding-auto –> release-train, and merge if PR OK

    6. Opens PR release-train –> release, and merge if PR OK

      %%{init: { 'logLevel': 'debug', 'theme': 'default', 'gitGraph': {'rotateCommitLabel': false, 'showBranches': true, 'showCommitLabel':true, 'mainBranchName': 'main / master'}} }%% gitGraph commit id: "1.2.0" type: HIGHLIGHT tag: "v1.2.0" commit id: "1.2.1" type: HIGHLIGHT tag: "v1.2.1" commit id: "1.3.0" type: HIGHLIGHT tag: "v1.3.0" branch release branch release-train branch "Protected Branch" branch boarding-auto branch "User Br" commit commit id: "new feat" checkout boarding-auto merge "User Br" id: "Classify Type of Changes" checkout "Protected Branch" merge "boarding-auto" id: "Accept User changes" checkout release-train merge "Protected Branch" id: "Integrate into Train" checkout release merge release-train id: "Start Release"

    So now, the release branch is updated on the remote,

  2. Now, sync your release local branch, by running:

    git fetch && (git checkout release || git branch --track release origin/release) && git pull origin release
    
  3. Run interactive script

    NOTE: This assumes a Prod Release ie from 1.2.3 to 1.2.4 and NOT a Dev, ie 1.2.4-dev

    ./scripts/auto-release.sh
    

    This should:

    1. Ask for new Release Sem Ver

    2. Ask user to Update Changelog themselves

    3. Trigger Distro Release CI Tests, with Job Matrix

    4. PR ‘release’ –> ‘master’, and merge if PR OK

      %%{init: { 'logLevel': 'debug', 'theme': 'default', 'gitGraph': {'showBranches': true, 'showCommitLabel':true, 'mainBranchName': 'main / master'}} }%% gitGraph commit id: "1.2.0" type: HIGHLIGHT tag: "v1.2.0" commit id: "1.2.1" type: HIGHLIGHT tag: "v1.2.1" commit id: "1.3.0" type: HIGHLIGHT tag: "v1.3.0" branch release branch release-train branch "Protected Branch" branch boarding-auto branch "User Br" commit commit id: "new feat" checkout boarding-auto merge "User Br" id: "Classify Changes" type: HIGHLIGHT checkout "Protected Branch" merge "boarding-auto" id: "Accept User changes" type: HIGHLIGHT checkout release-train merge "Protected Branch" id: "Integration Tests" type: HIGHLIGHT checkout release merge release-train id: "Start Release" type: HIGHLIGHT commit id: "Sem Ver PROD" commit id: "Changelog update" commit id: "Sem Ver RC" tag: "v1.4.0-rc" type: HIGHLIGHT commit id: "Revert HEAD" type: REVERSE checkout "main / master" merge release id: "[NEW] v1.4.0" type: HIGHLIGHT tag: "v1.4.0"
  4. Code Review PR on Github

    Go to PRs to ‘master’:
    https://github.com/boromir674/cookiecutter-python-package/pulls?q=is%3Apr+is%3Aopen+base%3Amaster

  5. Revert RC Sem Ver commit

    export GIT_BR='release'
    git fetch
    # if local release does not exist, track remote with a new local release
    git branch --track release "origin/${GIT_BR}" || echo "Local '${GIT_BR}' branch already exists."
    # if local release exists, ensure it tracks remote counterpart
    git branch --set-upstream-to="origin/${GIT_BR}" "${GIT_BR}"
    if [ $? -ne 0 ]; then        
        echo "[ERROR] Remote ${GIT_BR} does not exists"
        echo "The assumption is that there is a PR 'release' --> 'master', requires a 'release' branch"
        echo "[FATAL] Exiting .."
    else   
        git checkout release
        git pull
        git revert HEAD
        git push
    fi
    
  6. Merge PR ‘release’ –> ‘master’ Sample Commit

  • Subject [NEW] Py Pkg Gen v2.0.0

  • Body

–> !! DONE !! <–

Now, a new Release should be issued:

git checkout master && git pull && git push

function parse-version { grep -E -o '^version\s*=\s*\".*\"' pyproject.toml | cut -d'"' -f2; }

export tt="v$(parse-version)"

git tag -d "$tt"; git push origin -d "$tt"
git tag "$tt" && git push origin "$tt" && gh release create "$tt"
  • master branch

  • pypi

  • dockerhub

  • readthedocs

Clean Git with:

git checkout release && git rebase master && git push && git push origin --delete release-train
for bra in test-distro test-docs test-distro-docs boarding-auto; do git push origin -d "$bra"; done