Skip to content

Commit

Permalink
feat: golang release (#23)
Browse files Browse the repository at this point in the history
Publishes a directory that is expected to be the output of `jsii-pacmak` (i.e `dist/go`) to the appropriate GitHub repo.
  • Loading branch information
iliapolo authored Jan 31, 2021
1 parent ec64e67 commit b36b8f9
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 3 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2020 Amazon Web Services
Copyright 2021 Amazon Web Services

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
33 changes: 31 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ structure is compatible with `jsii-pacmak`:
- `dist/python/*.whl` - Python wheels
- `dist/nuget/*.nupkg` - Nuget packages
- `dist/java/**` - Maven artifacts in local repository structure
- `dist/go/**/go.mod` - Go modules. Each subdirectory should have its own go.mod file.

Each publisher needs a set of environment variables with credentials as
described below (`NPM_TOKEN`, `TWINE_PASSWORD` etc).
Expand All @@ -43,6 +44,7 @@ You can also execute individual publishers:
* `jsii-release-nuget`
* `jsii-release-npm`
* `jsii-release-pypi`
* `jsii-release-golang`

## npm

Expand Down Expand Up @@ -115,7 +117,7 @@ $ gpg -a --export-secret-keys <fingerprint> > private.pem
```

Now, either set `MAVEN_GPG_PRIVATE_KEY_FILE` to point to `private.pem` or
export the private key to a single line where newlines are encoded as `\n`
export the private key to a single line where newlines are encoded as `\n`
and then assign it to `MAVEN_GPG_PRIVATE_KEY`:

```console
Expand Down Expand Up @@ -158,7 +160,7 @@ npx jsii-release-nuget [DIR]

* Set `NUGET_SERVER` to `https://nuget.pkg.github.com/(`org or user`).
* Set `NUGET_API_KEY` to a token with write packages permissions.
* Make sure the repository url in the project file matches the org or user used for the server
* Make sure the repository url in the project file matches the org or user used for the server

## PyPI

Expand All @@ -181,6 +183,33 @@ npx jsii-release-pypi [DIR]
|`TWINE_REPOSITORY_URL`|Optional|The registry URL (defaults to Twine default)|


## Golang

Pushes a directory of golang modules to a GitHub repository.

**Usage:**

```shell
npx jsii-release-golang [DIR]
```

`DIR` is a directory where the golang modules are located (default is `dist/go`). Each subdirectory inside it
must be a go module and contain a go.mod file. This directory is pushed as is to the repository root, overriding existing files.

**Options (environment variables):**

|Option|Required|Description|
|------|--------|-----------|
|`GITHUB_TOKEN`|Required|[GitHub personal access token.](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token)|
|`VERSION`|Optional|Module version. Defaults to the value in the 'version' file of the module directory. Fails if it doesn't exist.|
|`GITHUB_REPO`|Optional|GitHub repository to push to. Default is derived from the module name.|
|`GIT_BRANCH`|Optional|Branch to push to. Defaults to 'main'.|
|`GIT_USER_NAME`|Optional|Username to perform the commit with. Defaults to the global git user.name config. Fails it it doesn't exist.|
|`GIT_USER_EMAIL`|Optional|Email to perform the commit with. Defaults to the global git user.email config. Fails it it doesn't exist.|
|`GIT_COMMIT_MESSAGE`|Optional|The commit message. Defaults to 'chore(release): $VERSION'.|
|`DRYRUN`|Set to "true" for a dry run.|


## Roadmap

- [X] GitHub Support: Maven
Expand Down
1 change: 1 addition & 0 deletions bin/jsii-release
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ release maven java
release nuget dotnet
release npm js
release pypi python
release golang go
154 changes: 154 additions & 0 deletions bin/jsii-release-golang
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#!/bin/bash
set -eu

###
#
# Pushes a directory of golang modules to a GitHub repository.
#
# Usage: ./jsii-release-golang [DIR]
#
# DIR is a directory where the golang modules are located (default is `dist/go`). Each subdirectory inside it must be a
# go module and contain a go.mod file. This directory is pushed as is to the repository root, overriding existing files.
#
# GITHUB_TOKEN (required): Authentication token that allows to push and tag the repository.
# VERSION (optional): Module version. Defaults to the value in the 'version' file of the module directory. Fails if it doesn't exist.
# GITHUB_REPO (optional): GitHub repository to push to. Default is derived from the module name.
# GIT_BRANCH (optional): Branch to push to. Defaults to 'main'.
# GIT_USER_NAME (optional): Username to perform the commit with. Defaults to the global git user.name config. Fails it it doesn't exist.
# GIT_USER_EMAIL (optional): Email to perform the commit with. Defaults to the global git user.email config. Fails it it doesn't exist.
# GIT_COMMIT_MESSAGE (optional): The commit message. Defaults to 'chore(release): $VERSION'.
# DRYRUN (optional): Set to "true" for a dry run
###

dir=${1:-dist/go}
GIT_BRANCH=${GIT_BRANCH:-main}

# remember the full path since we might be changing dirs later on
dir="$(pwd)/${dir}"

error() { echo "$@"; exit 1; }

if ! command -v git &> /dev/null; then
error "git must be available to run this script"
fi

if [ -z "${GIT_USER_NAME:-}" ]; then
GIT_USER_NAME=$(git config user.name) || error "Unable to detect username. either configure a global git user.name or pass GIT_USER_NAME env variable"
fi

if [ -z "${GIT_USER_EMAIL:-}" ]; then
GIT_USER_EMAIL=$(git config user.email) || error "Unable to detect user email. either configure a global git user.email or pass GIT_USER_EMAIL env variable"
fi

dry_run=false
if [[ ${DRYRUN:-"false"} = "true" ]]; then
echo "==========================================="
echo " 🏜️ DRY-RUN MODE 🏜️"
echo "==========================================="
dry_run=true
fi

if [ ! -d ${dir} ]; then
error "${dir} either doesnt exist or is not a directory"
fi

if [ -z "${GITHUB_TOKEN:-}" ]; then
error "GITHUB_TOKEN env variable is required"
fi

go_mod=""
versions=("")

# make sure each directory has a go.mod file
for subdir in $(find ${dir} -mindepth 1 -maxdepth 1 -type d)
do
if [ ! -f ${subdir}/go.mod ]; then
error "expected to find go.mod in ${subdir}. make sure you specify the root directory of all your modules."
fi
# pick one mod file to derive repository
go_mod=${subdir}/go.mod

# collect versions if they exist. used both for validation and for default value.
if [ -f ${subdir}/version ]; then
version=$(cat ${subdir}/version)
versions=(${versions[@]} ${version})
fi

done

if [ ${go_mod} = "" ]; then
error "No go modules found in ${dir}"
fi

unique_versions=($(echo "${versions[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))
count_unique_version=$(echo "${#unique_versions[@]}")

if [ ${count_unique_version} -gt 1 ]; then
error "multiple versions are not supported. please use a single version across all your modules."
fi

if [ -z "${VERSION:-}" ]; then

if [ ${count_unique_version} -eq 0 ]; then
error "No version files found. Please supply a version using the VERSION env variable."
fi

# must be a single element at this point
VERSION=${unique_versions[0]}
fi

GIT_COMMIT_MESSAGE=${GIT_COMMIT_MESSAGE:-"chore(release): ${VERSION}"}

module_name=$(grep module ${go_mod} | cut -d ' ' -f 2)
domain=$(echo ${module_name} | cut -d '/' -f 1)

if [ ${domain} != "github.com" ]; then
# the way we clone the repo with the token is a GitHub thing.
error "'${domain}' domain is not supported. Only GitHub repositories are allowed"
fi

if [ -z "${GITHUB_REPO:-}" ]; then
owner=$(echo ${module_name} | cut -d '/' -f 2)
repo=$(echo ${module_name} | cut -d '/' -f 3)
GITHUB_REPO=${owner}/${repo}
fi

target_repo_dir=$(mktemp -d)/repo

echo "Cloning target repository ${GITHUB_REPO}"
git clone https://${GITHUB_TOKEN}@github.com/${GITHUB_REPO}.git ${target_repo_dir}

pushd ${target_repo_dir}
git config user.name ${GIT_USER_NAME}
git config user.email ${GIT_USER_EMAIL}

# checkout or create
git checkout ${GIT_BRANCH} || git checkout -b ${GIT_BRANCH}

for subdir in $(find $(pwd) -mindepth 1 -maxdepth 1 -type d)
do
if [ -f ${subdir}/go.mod ]; then
# remove to account for deleted files or entire modules
echo "Removing ${subdir}"
rm -r ${subdir}
fi
done

echo "Copying go modules to repository root"
cp -r ${dir}/* .

git add .
git commit -m "${GIT_COMMIT_MESSAGE}"

tag_name=v${VERSION}
git tag -a ${tag_name} -m $VERSION

if $dry_run; then
echo "Will create a tag: ${tag_name}"
echo "Will push to branch: ${GIT_BRANCH}"
else
git push origin ${tag_name}
git push origin ${GIT_BRANCH}
fi

popd
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
},
"bin": {
"jsii-release": "bin/jsii-release",
"jsii-release-golang": "bin/jsii-release-golang",
"jsii-release-maven": "bin/jsii-release-maven",
"jsii-release-npm": "bin/jsii-release-npm",
"jsii-release-nuget": "bin/jsii-release-nuget",
Expand Down

0 comments on commit b36b8f9

Please sign in to comment.