Skip to content

Commit bd10c4b

Browse files
authored
chore: Update releaser to handle multiple static and generated gems (#2145)
1 parent be13e0c commit bd10c4b

File tree

7 files changed

+284
-36
lines changed

7 files changed

+284
-36
lines changed

.kokoro/release/all-generated.cfg

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Format: //devtools/kokoro/config/proto/build.proto
2+
3+
env_vars: {
4+
key: "PACKAGE"
5+
value: "ALL_GENERATED"
6+
}

.kokoro/release/common.cfg

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Format: //devtools/kokoro/config/proto/build.proto
2+
3+
# Build logs will be here
4+
action {
5+
define_artifacts {
6+
regex: "**/*sponge_log.xml"
7+
}
8+
}
9+
10+
# Fetch the token needed for reporting release status to GitHub
11+
before_action {
12+
fetch_keystore {
13+
keystore_resource {
14+
keystore_config_id: 73713
15+
keyname: "yoshi-automation-github-key"
16+
}
17+
}
18+
}
19+
20+
# Fetch magictoken to use with Magic Github Proxy
21+
before_action {
22+
fetch_keystore {
23+
keystore_resource {
24+
keystore_config_id: 73713
25+
keyname: "releasetool-magictoken"
26+
backend_type: FASTCONFIGPUSH
27+
}
28+
}
29+
}
30+
31+
# Fetch api key to use with Magic Github Proxy
32+
before_action {
33+
fetch_keystore {
34+
keystore_resource {
35+
keystore_config_id: 73713
36+
keyname: "magic-github-proxy-api-key"
37+
backend_type: FASTCONFIGPUSH
38+
}
39+
}
40+
}
41+
42+
before_action {
43+
fetch_keystore {
44+
keystore_resource {
45+
keystore_config_id: 73713
46+
keyname: "docuploader_service_account"
47+
}
48+
}
49+
}
50+
51+
# Download resources for system tests (service account key, etc.)
52+
gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-ruby"
53+
54+
# Download trampoline resources.
55+
gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
56+
57+
# Use the trampoline script to run in docker.
58+
build_file: "google-api-ruby-client/.kokoro/trampoline.sh"
59+
60+
# Configure the docker image for kokoro-trampoline.
61+
env_vars: {
62+
key: "TRAMPOLINE_IMAGE"
63+
value: "gcr.io/cloud-devrel-kokoro-resources/yoshi-ruby/release"
64+
}
65+
66+
env_vars: {
67+
key: "TRAMPOLINE_BUILD_FILE"
68+
value: "github/google-api-ruby-client/.kokoro/build.sh"
69+
}
70+
71+
env_vars: {
72+
key: "TRAMPOLINE_SCRIPT"
73+
value: "trampoline_v1.py"
74+
}
75+
76+
env_vars: {
77+
key: "JOB_TYPE"
78+
value: "release"
79+
}
80+
81+
env_vars: {
82+
key: "OS"
83+
value: "linux"
84+
}
85+
86+
env_vars: {
87+
key: "REPO_DIR"
88+
value: "github/google-api-ruby-client"
89+
}

.kokoro/release/core.cfg

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Format: //devtools/kokoro/config/proto/build.proto
2+
3+
env_vars: {
4+
key: "PACKAGE"
5+
value: "google-apis-core"
6+
}

.kokoro/release/generator.cfg

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Format: //devtools/kokoro/config/proto/build.proto
2+
3+
env_vars: {
4+
key: "PACKAGE"
5+
value: "google-apis-generator"
6+
}

.kokoro/release/umbrella.cfg

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Format: //devtools/kokoro/config/proto/build.proto
2+
3+
env_vars: {
4+
key: "PACKAGE"
5+
value: "google-api-client"
6+
}

Rakefile

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ namespace :kokoro do
55
load_env_vars
66
end
77

8+
task :dry_run do
9+
ENV["DRY_RUN"] = "true"
10+
end
11+
812
task :presubmit do
913
Rake::Task["kokoro:run_tests"].invoke
1014
end
@@ -26,8 +30,27 @@ namespace :kokoro do
2630
end
2731

2832
task :release do
29-
Rake::Task["kokoro:publish_gem"].invoke
30-
Rake::Task["kokoro:publish_docs"].invoke
33+
require_relative "rakelib/releaser.rb"
34+
35+
load_env_vars if ENV["KOKORO_GFILE_DIR"]
36+
package = ENV["PACKAGE"]
37+
raise "PACKAGE missing" unless package
38+
dry_run = ENV["DRY_RUN"]
39+
40+
if package == "ALL_GENERATED"
41+
Dir.glob("generated/google-apis-*") do |gem_dir|
42+
gem_name = File.basename(gem_dir)
43+
releaser = Releaser.new(gem_name, gem_dir, dry_run: dry_run)
44+
if releaser.needs_gem_publish?
45+
releaser.publish_gem
46+
releaser.publish_docs
47+
end
48+
end
49+
else
50+
releaser = Releaser.new(package, package, dry_run: dry_run)
51+
releaser.publish_gem if releaser.needs_gem_publish?
52+
releaser.publish_docs
53+
end
3154
end
3255

3356
task :run_tests do
@@ -42,40 +65,6 @@ namespace :kokoro do
4265
end
4366
end
4467
end
45-
46-
task :publish_gem do
47-
require "gems"
48-
49-
load_env_vars if ENV["KOKORO_GFILE_DIR"]
50-
api_token = ENV["RUBYGEMS_API_TOKEN"]
51-
if api_token
52-
::Gems.configure do |config|
53-
config.key = api_token
54-
end
55-
end
56-
57-
cd "google-api-client" do
58-
Bundler.with_clean_env do
59-
rm_rf "pkg"
60-
sh "bundle update"
61-
sh "bundle exec rake build"
62-
built_gem_path = Dir.glob("pkg/google-api-client-*.gem").last
63-
64-
response = ::Gems.push File.new built_gem_path
65-
puts response
66-
raise "Failed to release gem" unless response.include? "Successfully registered gem:"
67-
end
68-
end
69-
end
70-
71-
desc "Publish docs for the latest git tag"
72-
task :publish_docs do
73-
require_relative "rakelib/devsite/devsite_builder.rb"
74-
75-
cd "google-api-client" do
76-
DevsiteBuilder.new.publish ENV["DOCS_BUILD_TAG"]
77-
end
78-
end
7968
end
8069

8170
def load_env_vars

rakelib/releaser.rb

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
require "fileutils"
2+
require "gems"
3+
require "rubygems"
4+
5+
class Releaser
6+
def initialize gem_name, gem_dir,
7+
rubygems_api_token: nil,
8+
docs_staging_bucket: nil,
9+
docuploader_credentials: nil,
10+
dry_run: false
11+
@gem_name = gem_name
12+
@gem_dir = File.expand_path(gem_dir)
13+
@rubygems_api_token = rubygems_api_token || ENV["RUBYGEMS_API_TOKEN"]
14+
@docs_staging_bucket = docs_staging_bucket || ENV["STAGING_BUCKET"] || "docs-staging"
15+
@docuploader_credentials = docuploader_credentials
16+
if @docuploader_credentials.nil? && ENV["KOKORO_KEYSTORE_DIR"]
17+
@docuploader_credentials = File.join(ENV["KOKORO_KEYSTORE_DIR"], "73713_docuploader_service_account")
18+
end
19+
@dry_run = dry_run ? true : false
20+
@rubygems_api_token_configured = false
21+
@bundle_updated = false
22+
end
23+
24+
attr_reader :gem_name
25+
attr_reader :gem_dir
26+
attr_reader :rubygems_api_token
27+
attr_reader :docs_staging_bucket
28+
attr_reader :docuploader_credentials
29+
30+
def dry_run?
31+
@dry_run
32+
end
33+
34+
def needs_gem_publish?
35+
Gem::Version.new(gem_version) > Gem::Version.new(current_rubygems_version)
36+
end
37+
38+
def publish_gem
39+
configure_rubygems_api_token
40+
bundle_dir do
41+
FileUtils.rm_rf("pkg")
42+
execute "bundle exec rake build"
43+
built_gem_path = "pkg/#{gem_name}-#{gem_version}.gem"
44+
raise "Failed to build #{built_gem_path}" unless File.file?(built_gem_path)
45+
if dry_run?
46+
puts "**** In dry run mode. Skipping gem publish of #{gem_name}"
47+
return
48+
end
49+
response = gems_client.push(File.new(built_gem_path))
50+
puts response
51+
raise "Failed to publish gem" unless response.include? "Successfully registered gem:"
52+
end
53+
end
54+
55+
def publish_docs
56+
bundle_dir do
57+
FileUtils.rm_rf("doc")
58+
FileUtils.rm_rf(".yardoc")
59+
execute "bundle exec rake yard"
60+
Dir.chdir("doc") do
61+
execute "python3 -m docuploader create-metadata" \
62+
" --name #{gem_name}" \
63+
" --distribution-name #{gem_name}" \
64+
" --language ruby" \
65+
" --version v#{gem_version}"
66+
unless docuploader_credentials
67+
puts "**** No credentials available. Skipping doc upload of #{gem_name}"
68+
return
69+
end
70+
if dry_run?
71+
puts "**** In dry run mode. Skipping doc upload of #{gem_name}"
72+
return
73+
end
74+
execute "python3 -m docuploader upload ." \
75+
" --credentials=#{docuploader_credentials}" \
76+
" --staging-bucket=#{docs_staging_bucket}" \
77+
" --metadata-file=./docs.metadata"
78+
end
79+
end
80+
end
81+
82+
def current_rubygems_version
83+
@current_rubygems_version ||= begin
84+
gems_client.info(gem_name)["version"]
85+
rescue Gems::NotFound
86+
"0.0.0"
87+
end
88+
end
89+
90+
def gem_version
91+
@gem_version ||= begin
92+
version_content = File.read(version_file_path)
93+
match = /\s(?:GEM_)?VERSION = "([\d\.]+)"/.match(version_content)
94+
raise "Unable to find version constant in #{version_file_path}" unless match
95+
match[1]
96+
end
97+
end
98+
99+
def version_file_path
100+
@version_file_path ||= begin
101+
path = Dir.glob("#{gem_dir}/lib/google/apis/*/version.rb").first ||
102+
Dir.glob("#{gem_dir}/lib/google/apis/*/gem_version.rb").first ||
103+
Dir.glob("#{gem_dir}/lib/google/apis/version.rb").first
104+
raise "Unable to find version file in #{gem_dir}" unless path
105+
path
106+
end
107+
end
108+
109+
def gems_client
110+
@gems_client ||= Gems::Client.new
111+
end
112+
113+
def configure_rubygems_api_token
114+
return if @rubygems_api_token_configured
115+
@rubygems_api_token_configured = true
116+
if rubygems_api_token
117+
Gems.configure do |config|
118+
config.key = rubygems_api_token
119+
end
120+
end
121+
end
122+
123+
def bundle_dir
124+
block = proc do
125+
execute "bundle update" unless @bundle_updated
126+
@bundle_updated = true
127+
yield
128+
end
129+
Dir.chdir(gem_dir) do
130+
if defined?(Bundler)
131+
if Bundler.respond_to?(:with_unbundled_env)
132+
Bundler.with_unbundled_env(&block)
133+
else
134+
Bundler.with_clean_env(&block)
135+
end
136+
else
137+
block.call
138+
end
139+
end
140+
end
141+
142+
def execute(cmd)
143+
puts cmd
144+
raise "Error executing command" unless system(cmd)
145+
end
146+
end

0 commit comments

Comments
 (0)