Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release and publish scripts v2 #925

Merged
merged 2 commits into from
Dec 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 40 additions & 5 deletions script/publish
Original file line number Diff line number Diff line change
@@ -1,7 +1,42 @@
#!/usr/bin/env bash
#!/usr/bin/env ruby
# frozen_string_literal: true

# Publish gem
bundle exec rake release
require "thor"
require_relative "../lib/primer/view_components/version"

# Publish NPM
npm publish --access public
# Publishes `primer_view_components` gem and npm package, and creates a new GitHub release.
#
# Usage:
#
# script/publish
class PublishCLI < Thor::Group
include Thor::Actions

def release_gem
run("bundle exec release")
end

def release_npm
run("npm publish --access public")
end

def github_release
run("gh release create v#{version} -n \"#{release_notes}\"")
end

private

def release_notes
changelog.gsub(/.*## #{version}/m, "").gsub(/^## .*/m, "").strip
end

def version
Primer::ViewComponents::VERSION::STRING
end

def changelog
File.read("CHANGELOG.md")
end
end

PublishCLI.start(ARGV)
320 changes: 145 additions & 175 deletions script/release
Original file line number Diff line number Diff line change
@@ -1,176 +1,146 @@
#!/usr/bin/env bash

if [ $(uname -s) = "Darwin" ]; then
SED_ARGS="-i ''"
else
SED_ARGS="-i"
fi

fetch() {
git fetch --all
}

branch_name() {
git symbolic-ref --short HEAD
}

local_history_is_clean() {
history=$(git rev-list --count --right-only @{u}...HEAD)
[ "$history" == "0" ]
}

remote_history_is_clean() {
history=$(git rev-list --count --left-only @{u}...HEAD)
[ "$history" == "0" ]
}

tag_exists_on_remote() {
git rev-parse --quiet --verify refs/tags/v$1.$2.$3 > /dev/null
}

working_tree_is_clean() {
status=$(git status --porcelain)
[ "$status" == "" ]
}

create_release_branch() {
git switch -c release-v$1-$2-$3
}

update_readme() {
sed $SED_ARGS "/## main/ {a\
\\
\\
## $1.$2.$3
}" CHANGELOG.md
}

update_ruby_version() {
# Update version file
sed -E $SED_ARGS \
-e "s/MAJOR = [0-9]+/MAJOR = $1/g" \
-e "s/MINOR = [0-9]+/MINOR = $2/g" \
-e "s/PATCH = [0-9]+/PATCH = $3/g" \
#!/usr/bin/env ruby
# frozen_string_literal: true

require "thor"
require_relative "../lib/primer/view_components/version"

# Prepares a release PR for `primer_view_components`.
#
# Usage:
#
# script/release for a patch release
# script/release --major for a major release
# script/release --minor for a minor release
class ReleaseCLI < Thor::Group
include Thor::Actions

class_option :major, type: :boolean, desc: "Use this option to bump a major version."
class_option :minor, type: :boolean, desc: "Use this option to bump a minor version."
class_option :patch, type: :boolean, desc: "Use this option to bump a patch version."

def self.exit_on_failure?
false
end

def working_tree_is_clean
tree_status = run("git status --porcelain", capture: true).strip
raise "Tree is not clean" unless tree_status.empty?
end

def must_be_in_main
raise "Must be in the main branch to release" unless current_branch == "main"
end

def git_fetch
run("git fetch --all")
end

def remote_history_is_clean
remote_history = run("git rev-list --count --left-only @{u}...HEAD", capture: true).strip
raise "Changes exist on origin not pulled into this branch. Please pull" unless remote_history == "0"
end

def local_history_is_clean
remote_history = run("git rev-list --count --right-only @{u}...HEAD", capture: true).strip
raise "Changes exist that haven't been pushed to origin. Please pull" unless remote_history == "0"
end

def tag_exists_on_remote
raise "Tag exists on remote" unless run("git rev-parse --quiet --verify refs/tags/v#{new_version}", capture: true).strip.empty?
end

def create_release_branch
run("git switch -c #{release_branch}")
end

def update_readme
gsub_file("CHANGELOG.md", "## main", "## main\n\n## #{new_version}")
end

def update_ruby_version
major, minor, patch = new_version.split(".")

gsub_file("lib/primer/view_components/version.rb", /MAJOR = [0-9]+/, "MAJOR = #{major}")
gsub_file("lib/primer/view_components/version.rb", /MINOR = [0-9]+/, "MINOR = #{minor}")
gsub_file("lib/primer/view_components/version.rb", /PATCH = [0-9]+/, "PATCH = #{patch}")
end

def update_gemfiles
run("bundle")
run("pushd demo")
run("bundle")
run("popd")
end

def update_npm
run("npm version --no-git-tag-version \"#{new_version}\"")
run("yarn")
end

def add_changed_files
files_to_add = %w[
CHANGELOG.md
Gemfile.lock
demo/Gemfile.lock
lib/primer/view_components/version.rb
}

update_gemfiles() {
# Update Gemfile.lock
bundle
pushd demo
bundle
popd
}


update_npm() {
npm version --no-git-tag-version "$1.$2.$3"
yarn
}

add_changed_files() {
git add \
CHANGELOG.md \
Gemfile.lock \
demo/Gemfile.lock \
lib/primer/view_components/version.rb \
app/assets/javascripts \
package.json \
yarn.lock
}

commit() {
git commit -m "release $1.$2.$3"
}

push() {
git push origin release-v$1-$2-$3
}

main() {
version=$(ruby ./lib/primer/view_components/version.rb)
version=(${version//./ })
major=${version[0]}
minor=${version[1]}
patch=${version[2]}

echo "==================="
echo "Prerequisite Checks"
echo "==================="

if ! working_tree_is_clean; then
echo "Error: unclean working tree"
exit 1
fi

if [[ "$(branch_name)" != "main" ]]; then
echo "Error: can only make a release on the main branch"
exit 1
fi

fetch
if ! remote_history_is_clean; then
echo "Error: changes exist on origin not pulled into this branch. Please pull"
exit 1
fi

if ! local_history_is_clean; then
echo "Error: changes exist that haven't been pushed to origin. Please pull"
exit 1
fi

echo "Type the number of an option to bump, or pick Manual to enter a version number"
select bump in Major Minor Patch Manual
do
if [ "$bump" == "Major" ]; then
major=$((major + 1))
minor=0
patch=0
elif [ "$bump" == "Minor" ]; then
minor=$((minor + 1))
patch=0
elif [ "$bump" == "Patch" ]; then
patch=$((patch + 1))
else
read -p "What version? (Currently $major.$minor.$patch): " new_version
if [ "$new_version" == "$major.$minor.$patch" ]; then
echo "Error: Cannot be the same version"
exit 1
fi

new_version=(${new_version//./ })

major=${new_version[0]}
minor=${new_version[1]}
patch=${new_version[2]}
fi

if tag_exists_on_remote $major $minor $patch; then
echo "Error: tag exists on remote"
exit 1
fi

echo "==============================="
echo "Creating release for $major.$minor.$patch"
echo "==============================="

create_release_branch $major $minor $patch
update_readme $major $minor $patch
update_ruby_version $major $minor $patch
update_gemfiles $major $minor $patch
update_npm $major $minor $patch
add_changed_files $major $minor $patch
commit $major $minor $patch
push $major $minor $patch

echo "####################################################"
echo "Now, open a PR with this branch and merge it to main."
echo "When the PR has been merged, run script/publish to publish the gem."
echo "Finally, create a GitHub release https://github.com/primer/view_components/releases/new with the changes from CHANGELOG"
echo "####################################################"

break
done
}

main
app/assets/javascripts
package.json
yarn.lock
]

run("git add #{files_to_add.join(' ')}")
end

def commit_files
run("git commit -m \"release #{new_version}\"")
end

def push_files
run("git push origin #{release_branch}")
end

def create_pull_request
@pr_url = run("gh pr create -b "" -t \"Release v#{new_version}\"", capture: true)
end

def final_message
puts "####################################################"
puts "PR link: #{@pr_url}"
puts "When the PR has been merged, run script/publish to publish the gem."
puts "####################################################"
end

private

def current_branch
@current_branch ||= run("git symbolic-ref --short HEAD", capture: true).strip
end

def current_version
Primer::ViewComponents::VERSION::STRING
end

def new_version
@new_version ||= case bump
when :major
"#{Primer::ViewComponents::VERSION::MAJOR + 1}.0.0"
when :minor
"#{Primer::ViewComponents::VERSION::MAJOR}.#{Primer::ViewComponents::VERSION::MINOR + 1}.0"
else
"#{Primer::ViewComponents::VERSION::MAJOR}.#{Primer::ViewComponents::VERSION::MINOR}.#{Primer::ViewComponents::VERSION::PATCH + 1}"
end
end

def bump
return :major if options[:major]
return :minor if options[:minor]

:patch
end

def release_branch
"release-v#{new_version}"
end
end

ReleaseCLI.start(ARGV)