Developer Guide
Prerequisites
- Go 1.20+
- Git
- Make
Clone the Repository
Once you have the basic tools installed, fork the repository on GitHub and clone it locally:
MY_GITHUB_NAME="my-name"
git clone git@github.com:${MY_GITHUB_NAME}/oras.git
cd oras
Building the Binary
To compile and run the tests, just run the make
command.
Use make build
to build all platform binaries to the bin/
directory.
Mac:
# builds to
# - bin/darwin/amd64/oras
# - bin/darwin/arm64/oras
make build-mac
# builds to bin/darwin/amd64/oras
make build-mac-amd64
# builds to bin/darwin/arm64/oras
make build-mac-arm64
Linux:
# builds to
# - bin/linux/arm64/oras
# - bin/linux/amd64/ora
# - bin/linux/arm/v7/orass
make build-linux
# builds to bin/linux/arm64/oras
make build-linux-arm64
# builds to bin/linux/amd64/oras
make build-linux-amd64
# builds to bin/linux/arm/v7/oras
make build-linux-arm-v7
Windows:
# builds to bin/windows/amd64/oras.exe
make build-windows
Cleaning Your Workspace
To remove all files not manged by git, run make clean
(be careful!)
Managing Dependencies
Using Go Modules to manage dependencies.
To update or add new dependencies, run go get <package name>
.
Release Checklist
This section needs a lot of love and automation 🙂
Prerequisites
- Make sure your GPG is available on GitHub at
https://github.com/<username>.gpg
. This can be added at https://github.com/settings/keys.- If you haven't already, open a PR to add your GPG key to the
KEYS
file (see file for instructions).
- If you haven't already, open a PR to add your GPG key to the
- Open a bump PR to build with the latest golang: replace go version of the binary and image to match the latest stable version. Skippable if the latest version is already used.
- (patch-release-only) Cherry-pick or backport the fix commits to the patch release branch. Make sure applicable critical and high CVE patches are on the release branch.
Request to vote
- Open a PR to update the
oras
version: replace the current version with the upcoming release version.- The target branch is:
main
if releasing a new version.release-<major>.<minor>
if releasing a patch.
- The title should be
bump: tag and release ORAS CLI v<major>.<minor>.<patch>[-<pre-release>]
. - The description must reference the digest of version bump up commit for voting.
- The target branch is:
- Send a message to the ORAS slack channel to call for a vote on the release PR. If the vote PR has a super-majority of approval from ORAS maintainers, then the PR could be merged into the target branch.
- The target commit should be the SHA digest of the last commit in the release PR
- Make sure that
- the PR is merged with
Create a merge commit
option. - signoff info is added to the merge commit.
- the PR is merged with
- (optional) Cut off a release branch named
release-<major>.<minor>
on the tagged commit ONLY when releasing a new minor version.
Release
Make a fresh clone of the repo after all above steps are completed. Create a new tag for the version prefixed with "v" and push the tag directly to the repo. The tag should be created on the voted commit, NOT the merge commit.
version=1.0.0
digest=b58e7b910ca556973d111e9bd734a71baef03db2 # replace with the digest of the voted commit
git tag v${version} $digestAfter validating the tag is created on the voted commit, push the created tag:
git push origin v${version}
Wait for GitHub Actions to complete successfully for both the
release-ghcr
andrelease-github
pipelines.Download all of the artifacts uploaded to the new GitHub release locally (
*checksums.txt
,*darwin_amd64.tar.gz
,*linux_armv7.tar.gz
,*linux_arm64.tar.gz
,*linux_amd64.tar.gz
,*windows_amd64.zip
).Verify the checksum of the file, downloaded platform should pass the check:
shasum -c oras_${version}_checksums.txt
Run
oras version
command and make sure that version number and git commit digest is the expected value (same as the commit used to create the tag). Example:mkdir -p oras-bin/
tar -zxf oras_${version}_linux_amd64.tar.gz -C oras-bin
./oras-bin/oras versionCreate armored GPG signatures(
.asc
) using the key in theKEYS
file.for file in `ls`; do
gpg --armor --detach-sign $file
doneValidate the signatures. Note that the
KEYS
file should be imported withgpg --import KEYS
. Run some form of the following (adapted from Linux project):for file in `ls *.asc`; do
gpg --verify $file
doneClick the "Edit release" button on the release, and add the
.asc
files created in the previous step. Edit the release description to include change logs and a note indicating the releaser's GPG key used to sign the artifacts. See an example:## Notes
This release was signed with `BE6F A8DD A48D 4C23 0091 A0A9 276D 8A72 4CE1 C704` (@qweeah's GPG key) which can be found [here](https://github.com/qweeah.gpg).The uploaded signatures and GPG key will be used for binary validation.
Click "Publish Release" button to save. Double-check that the release contains a corresponding
.asc
file for each release artifact.Consume beverage of choice.. you're done! Thanks for moving the project forward.
Oh yea, tell people about it in the
#oras
slack channel.
Some Comments
There is a large number of steps here, mostly manual. Here are some comments and/or thoughts on it.
- Step 3: Editing files for stable version. I can see that in one place, say,
README.md
. But do we really have to edit the code? Could we not use build-time flags as ingo build -ldflags="-X main.Version=foo"
or similar? - Step 6: This is the heart of the release. Adding a tag triggers a github release and an image build pushed to GHCR.
- Steps 7-13: These are all signing and verifying. Of course, it is possible that GH Actions built and released something other than what we thought, but we cannot counter every single possible risk. It still would be nice if we could automate this somehow.
- Step 15: 🍺
From a documentation perspective, I would break this down into sections:
- Prepare the release.
- Cut the release.
- Verify the release (hopefully automated).
- Sign the release.
- Make available elsewhere (hopefully automated).
Once ready, this should be a doc in the project itself.
Library vs Utility
oras actually serves 2 purposes: library and utility. All of the above steps, except for the tag, are entirely about the utility.
For better or for worse, semver is tied up with both. As an example, the current issue with the go modules solely affects its inclusion as a library, but it is immediate. It can be fixed by cutting v1.0.0, and the downstream problems go away. yet cutting a release also means all of the above, which are far more complicated.