Skip to main content
Version: 1.5.X

Development Workflow

This document covers the development workflow for contributing to the Magma project.

General workflow​

Magma follows the standard "fork and pull-request" development workflow. For more information on this workflow, consider the following

See the opinionated workflow section below for a low-friction version of these workflows.

Guidelines​

Required: commits must be signed off. You must sign-off all commits on the originating branch for a PR, using the --signoff flag in Git. There is a CI check that will fail if any commit in your branch has an unsigned commit. If you've forgotten to sign-off a commit, you can git commit --amend --signoff, or git rebase --signoff to sign-off an entire branch at once.

Required: label backward-breaking pull requests. Use the breaking change label. All breaking changes and their mitigation steps will be aggregated in the subsequent release notes. A breaking change fits one or more of the following criteria

  1. Will require a manual intervention on the next upgrade (e.g. data migration script)
  2. Will break the southbound interfaces between AGW and Orchestrator in a way that will require both components to upgrade in a coordinated way.

Desired: convincing test plan. For non-trivial PRs, codeowners will require you to include a test plan detailing any manual verification steps you took.

Desired: use imperative mood for pull request title and description. A simple way to check this is to mentally prepend the phrase "This commit will ..." to the title and each bullet point of your description.

Productivity tools​

Opinionated workflow​

The references above should be sufficient to get started. This section provides an opinionated view on how to efficiently manage this workflow, assuming the following

  • up-to-date version of Git
  • hub wrapper command installed (see above)

Workflow​

This opinionated workflow simplifies the complexities of dealing with Git directly.

It does this by keeping both your_dev_branch and your_dev_branch_base branches, allowing a straightforward mechanism for rebasing commit stacks.

# Note: see below for the aliases used in this code block

###############
# Get started #
###############

# Fork the Magma repo
# ...

# Clone your forked Magma repo
git clone git@github.com:YOUR_USERNAME/magma.git && cd magma

# Set upstream
git remote add upstream git@github.com:magma/magma.git

###########
# Open PR #
###########

# Checkout master and fast-forward to match upstream
git_update

# Create new dev branch on top of latest master
git_update YOUR_NEW_DEV_BRANCH

# Make changes, and package as a *single* commit on your dev branch
# ...

# Open pull request
git open_pr

# Make requested changes, without committing anything
# ...

# Amend the single commit and force-push to update the PR
git amend_pr

# [optional] Rebase PR onto master
git_rebase

# [optional] Rebase PR onto another PR
git_rebase TARGET_BRANCH

# [note] If there's a merge commit during git_rebase, after completing the
# merge, you need to finish updating the reference branches
git_rebase_finish

###############
# Look around #
###############

# Full commit graph -- super helpful for figuring out what's going on
git graph_all

# Diff between PR and trunk
git diff_base

# Diff between local dev branch and origin dev branch
git diff_origin

############
# Clean up #
############

# When you have no open PRs, you can clear all local branches to clean up
# your git commit graph
git delete_local_branches

Necessary aliases​

# ~/.gitconfig

[alias]
delete_local_branches = !git branch | grep --invert-match master | xargs git branch --delete
commit_amend = commit --signoff --amend --no-edit
diff_base = !git diff $(git branch --show-current)_base
diff_origin = !git diff origin/$(git branch --show-current)
graph = graph_all --max-count=30
graph_all = log --graph --all --format=format:'%C(auto)%h%C(reset) %C(cyan)(%cr)%C(reset)%C(auto)%d%C(reset) %s %C(dim white)- %an%C(reset)'
amend_pr = !git add --all && git commit --signoff --amend --no-edit && git push --force
open_pr = !git push_branch && git pull-request --browse
push_branch = push --set-upstream origin HEAD
# shell rc file

# git_update updates master with upstream changes, and optionally creates a feature branch.
function git_update() {
git checkout master && git pull upstream master && git push origin master

local br=${1}
if [[ $br != "" ]]; then
local br_base=${br}_base
git branch ${br_base}
git checkout -b ${br}
fi
}

# git_rebase rebases current branch on master, or the specified target.
# $1 target
# $2+ args passed to rebase command
#
# Note: if there's a merge conflict, after handling the merge conflict,
# you need to finish by running git_rebase_finish.
function git_rebase() {
local to=${1:-master}
local args=${@:2}
local br=$(git branch --show-current)
local br_base=${br}_base

# Save values to file in case rebase fails
echo "${to} ${br} ${br_base}" > ~/.gitrebase

git rebase --onto ${to} ${br_base} ${br} ${args} && git checkout ${br_base} && git reset --hard ${to} && git checkout ${br}
}

# git_rebase_finish completes the rebase started by git_rebase.
function git_rebase_finish() {
local vals
read -r -a vals < ~/.gitrebase
local to=${vals[0]}
local br=${vals[1]}
local br_base=${vals[2]}
git checkout ${br_base} && git reset --hard ${to} && git checkout ${br}
}