Skip to content

Commit 363b235

Browse files
author
Graham Paye
authoredNov 5, 2019
chore: add release and continuous/post kokoro jobs (googleapis#836)

File tree

10 files changed

+425
-5
lines changed

10 files changed

+425
-5
lines changed
 

‎.kokoro/continuous/linux.cfg

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
build_file: "google-api-ruby-client/.kokoro/trampoline.sh"
44

55
# Configure the docker image for kokoro-trampoline.
6-
# Dockerfile is maintained at https://github.com/googleapis/google-cloud-ruby/tree/master/.kokoro/docker/ruby-multi
6+
# Dockerfile is maintained at https://github.com/googleapis/google-cloud-ruby/tree/master/.kokoro/docker/multi
77
env_vars: {
88
key: "TRAMPOLINE_IMAGE"
9-
value: "gcr.io/cloud-devrel-kokoro-resources/yoshi-ruby/ruby-multi"
9+
value: "gcr.io/cloud-devrel-kokoro-resources/yoshi-ruby/multi"
1010
}
1111

1212
env_vars: {

‎.kokoro/presubmit/linux.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ build_file: "google-api-ruby-client/.kokoro/trampoline.sh"
55
# Configure the docker image for kokoro-trampoline.
66
env_vars: {
77
key: "TRAMPOLINE_IMAGE"
8-
value: "gcr.io/cloud-devrel-kokoro-resources/yoshi-ruby/ruby-multi"
8+
value: "gcr.io/cloud-devrel-kokoro-resources/yoshi-ruby/multi"
99
}
1010

1111
env_vars: {

‎.kokoro/release.cfg

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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+
}
90+
91+
env_vars: {
92+
key: "PACKAGE"
93+
value: "google-api-client"
94+
}

‎.repo-metadata.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "google-api-client",
3+
"language": "ruby",
4+
"distribution-name": "google-api-client"
5+
}

‎.rubocop.yml

+5
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,8 @@ Metrics/LineLength:
55

66
Style/FormatString:
77
EnforcedStyle: sprintf
8+
9+
AllCops:
10+
Exclude:
11+
- "Rakefile"
12+
- "rakelib/**/*"

‎Gemfile

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ group :development do
2222
gem 'redis', '~> 3.2'
2323
gem 'logging', '~> 2.2'
2424
gem 'opencensus', '~> 0.4'
25+
gem 'httparty'
2526
end
2627

2728
platforms :jruby do

‎Rakefile

+71-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,51 @@
11
require "bundler/gem_tasks"
2+
require "json"
3+
4+
task :release_gem, :tag do |_t, args|
5+
tag = args[:tag]
6+
raise "You must provide a tag to release." if tag.nil?
7+
8+
# Verify the tag format "vVERSION"
9+
m = tag.match(/v(?<version>\S*)/)
10+
raise "Tag #{tag} does not match the expected format." if m.nil?
11+
12+
version = m[:version]
13+
raise "You must provide a version." if version.nil?
14+
15+
api_token = ENV["RUBYGEMS_API_TOKEN"]
16+
17+
require "gems"
18+
if api_token
19+
::Gems.configure do |config|
20+
config.key = api_token
21+
end
22+
end
23+
24+
Bundler.with_clean_env do
25+
sh "rm -rf pkg"
26+
sh "bundle update"
27+
sh "bundle exec rake build"
28+
end
29+
30+
path_to_be_pushed = "pkg/google-api-client-#{version}.gem"
31+
gem_was_published = nil
32+
if File.file? path_to_be_pushed
33+
begin
34+
response = ::Gems.push File.new(path_to_be_pushed)
35+
puts response
36+
raise unless response.include? "Successfully registered gem:"
37+
gem_was_published = true
38+
puts "Successfully built and pushed google-api-client for version #{version}"
39+
rescue StandardError => e
40+
gem_was_published = false
41+
puts "Error while releasing google-api-client version #{version}: #{e.message}"
42+
end
43+
else
44+
raise "Cannot build google-api-client for version #{version}"
45+
end
46+
47+
Rake::Task["kokoro:publish_docs"].invoke if gem_was_published
48+
end
249

350
task default: :spec
451

@@ -22,13 +69,35 @@ namespace :kokoro do
2269
task :nightly do
2370
Rake::Task["spec"].invoke
2471
end
72+
73+
task :post do
74+
require_relative "rakelib/link_checker.rb"
75+
76+
link_checker = LinkChecker.new
77+
link_checker.run
78+
exit link_checker.exit_status
79+
end
80+
81+
task :release do
82+
# Until code generation process is updated and release-please is set up, just publish docs
83+
require_relative "rakelib/devsite/devsite_builder.rb"
84+
85+
DevsiteBuilder.new.publish_if_missing ENV["DOCS_BUILD_TAG"]
86+
end
87+
88+
desc "Publish docs for the latest git tag"
89+
task :publish_docs do
90+
require_relative "rakelib/devsite/devsite_builder.rb"
91+
92+
DevsiteBuilder.new.publish ENV["DOCS_BUILD_TAG"]
93+
end
2594
end
2695

2796
def header str, token = "#"
2897
line_length = str.length + 8
29-
puts ""
98+
puts
3099
puts token * line_length
31100
puts "#{token * 3} #{str} #{token * 3}"
32101
puts token * line_length
33-
puts ""
102+
puts
34103
end

‎rakelib/devsite/devsite_builder.rb

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
require "pathname"
2+
require "tmpdir"
3+
4+
require_relative "repo_metadata.rb"
5+
6+
class DevsiteBuilder
7+
def initialize build_tag = nil
8+
@build_tag = build_tag || latest_tag
9+
@output_dir = "doc"
10+
end
11+
12+
def build tag
13+
checkout_tag tag
14+
doc_path = tmp_dir + @output_dir
15+
FileUtils.remove_dir doc_path if Dir.exist? doc_path
16+
markup = "--markup markdown --markup-provider redcarpet"
17+
18+
Dir.chdir tmp_dir do
19+
cmds = ["-o #{@output_dir}", markup]
20+
cmd "yard --verbose #{cmds.join ' '}"
21+
end
22+
metadata.build doc_path
23+
end
24+
25+
def upload
26+
Dir.chdir tmp_dir + @output_dir do
27+
opts = [
28+
"--credentials=#{ENV['KOKORO_KEYSTORE_DIR']}/73713_docuploader_service_account",
29+
"--staging-bucket=#{ENV.fetch 'STAGING_BUCKET', 'docs-staging'}",
30+
"--metadata-file=./docs.metadata"
31+
]
32+
cmd "python3 -m docuploader upload . #{opts.join ' '}"
33+
end
34+
end
35+
36+
def publish tag = nil
37+
build(tag || @build_tag)
38+
upload
39+
end
40+
41+
def publish_if_missing tag = nil
42+
tag ||= @build_tag
43+
puts tag
44+
puts missing? tag
45+
publish tag if missing? tag
46+
end
47+
48+
def missing? tag
49+
require "httparty"
50+
51+
url = "https://googleapis.dev/ruby/google-api-client/v#{version tag}/index.html"
52+
response = HTTParty.get url
53+
response.code != 200
54+
rescue StandardError
55+
true
56+
end
57+
58+
def cmd line
59+
puts line
60+
output = `#{line}`
61+
puts output
62+
output
63+
end
64+
65+
def metadata
66+
return @metadata if @metadata
67+
68+
metadata_json = "#{tmp_dir}/.repo-metadata.json"
69+
@metadata = RepoMetadata.from_source metadata_json if File.file? metadata_json
70+
@metadata ||= RepoMetadata.from_source "name" => "google-api-client",
71+
"distribution-name" => "google-api-client",
72+
"language" => "ruby"
73+
@metadata["version"] = version @build_tag
74+
@metadata
75+
end
76+
77+
def checkout_tag git_tag
78+
Dir.chdir tmp_dir do
79+
`git checkout tags/#{git_tag} -b v#{version git_tag}`
80+
end
81+
end
82+
83+
def version git_tag
84+
m = git_tag.match(/(\d+\.\d+\.\d+)/)
85+
return m if m.nil?
86+
m[0]
87+
end
88+
89+
def versions
90+
Dir.chdir tmp_dir do
91+
tags.map { |t| version t }.reject(&:nil?).sort_by { |v| Gem::Version.new v }.reverse
92+
end
93+
end
94+
95+
def tags
96+
Dir.chdir tmp_dir do
97+
`git tag`.split "\n"
98+
end
99+
end
100+
101+
def latest_version
102+
@latest_version ||= versions.first
103+
end
104+
105+
def latest_tag
106+
@latest_tag ||= tags.select { |t| t.include? latest_version }.min_by(&:size)
107+
end
108+
109+
def tmp_dir
110+
return @tmp_dir if @tmp_dir
111+
112+
tmp = Dir.tmpdir
113+
dir_name = "google-api-ruby-client"
114+
@tmp_dir = Pathname.new(tmp) + dir_name
115+
FileUtils.remove_dir @tmp_dir if Dir.exist? @tmp_dir
116+
117+
Dir.chdir tmp do
118+
`git clone https://github.com/googleapis/google-api-ruby-client.git`
119+
end
120+
Dir.chdir @tmp_dir do
121+
`git fetch`
122+
end
123+
124+
@tmp_dir
125+
end
126+
end

‎rakelib/devsite/link_checker.rb

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
require "open3"
2+
3+
class LinkChecker
4+
def initialize
5+
@failed = false
6+
end
7+
8+
def run
9+
job_info
10+
git_commit = ENV.fetch "KOKORO_GITHUB_COMMIT", "master"
11+
12+
markdown_files = Dir.glob "**/*.md"
13+
broken_markdown_links = check_links(markdown_files,
14+
"https://github.com/googleapis/google-api-ruby-client/tree/#{git_commit}",
15+
" --skip '^(?!(\\Wruby.*google|.*google.*\\Wruby|.*cloud\\.google\\.com))'")
16+
17+
broken_devsite_links = check_links(["google-api-client"],
18+
"https://googleapis.dev/ruby",
19+
"/latest/ --recurse --skip https:.*github.*")
20+
21+
puts_broken_links broken_markdown_links
22+
puts_broken_links broken_devsite_links
23+
end
24+
25+
def check_links location_list, base, tail
26+
broken_links = Hash.new { |h, k| h[k] = [] }
27+
location_list.each do |location|
28+
out, err, st = Open3.capture3 "npx linkinator #{base}/#{location}#{tail}"
29+
puts out
30+
unless st.to_i.zero?
31+
@failed = true
32+
puts err
33+
end
34+
checked_links = out.split "\n"
35+
checked_links.select! { |link| link =~ /\[\d+\]/ && !link.include?("[200]") }
36+
unless checked_links.empty?
37+
@failed = true
38+
broken_links[location] += checked_links
39+
end
40+
end
41+
broken_links
42+
end
43+
44+
def puts_broken_links link_hash
45+
link_hash.each do |location, links|
46+
puts "#{location} contains the following broken links:"
47+
links.each { |link| puts " #{link}" }
48+
puts ""
49+
end
50+
end
51+
52+
def job_info
53+
line_length = "Using Ruby - #{RUBY_VERSION}".length + 8
54+
puts
55+
puts "#" * line_length
56+
puts "### Using Ruby - #{RUBY_VERSION} ###"
57+
puts "#" * line_length
58+
puts
59+
end
60+
61+
def exit_status
62+
@failed ? 1 : 0
63+
end
64+
end

‎rakelib/devsite/repo_metadata.rb

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
require "json"
2+
3+
class RepoMetadata
4+
attr_accessor :data
5+
6+
def initialize data
7+
@data = data
8+
normalize_data!
9+
end
10+
11+
def allowed_fields
12+
[
13+
"name", "version", "language", "distribution-name",
14+
"product-page", "github-repository", "issue-tracker"
15+
]
16+
end
17+
18+
def build output_directory
19+
fields = @data.to_a.map { |kv| "--#{kv[0]} #{kv[1]}" }
20+
Dir.chdir output_directory do
21+
cmd "python3 -m docuploader create-metadata #{fields.join ' '}"
22+
end
23+
end
24+
25+
def normalize_data!
26+
@data.delete_if { |k, _| !allowed_fields.include?(k) }
27+
end
28+
29+
def [] key
30+
data[key]
31+
end
32+
33+
def []= key, value
34+
@data[key] = value
35+
end
36+
37+
def cmd line
38+
puts line
39+
output = `#{line}`
40+
puts output
41+
output
42+
end
43+
44+
def self.from_source source
45+
if source.is_a? RepoMetadata
46+
data = source.data
47+
elsif source.is_a? Hash
48+
data = source
49+
elsif File.file? source
50+
data = JSON.parse File.read(source)
51+
else
52+
raise "Source must be a path, hash, or RepoMetadata instance"
53+
end
54+
RepoMetadata.new data
55+
end
56+
end

0 commit comments

Comments
 (0)
Please sign in to comment.