Skip to content

Instantly share code, notes, and snippets.

@csexton
Created November 5, 2016 15:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save csexton/1ae0ae1b3e10ae382b8101eb2bb78efa to your computer and use it in GitHub Desktop.
Save csexton/1ae0ae1b3e10ae382b8101eb2bb78efa to your computer and use it in GitHub Desktop.
Deploy to Chrome Webstore
#!/usr/bin/env ruby
require "net/http"
require "net/https"
require "uri"
require "json"
require "optparse"
require "ostruct"
### What is going on here?
#
# Hacky script to upload to the google play webstore. There are a couple of
# "TODOs in the code below for thing that need to be updated.
#
# The goal was:
#
# - Automate uploads and publishing
# - Run no dependencies other than curl and ruby
# - Work on travis
### Usage
#
#
# Usage: publish-to-chrome-web-store [options]
# -e, --env [NAME] Select environment (staging, production)
# -a, --app-id [ID] Chrome Store App ID (bcdedldcbikpjmjbllhobfaohpajojli)
# -p, --publish Publish to the public
### Settings
#
# The refresh token below was created by visiting the follow url in a browser
# and authenticating with the right google account:
#
# https://accounts.google.com/o/oauth2/auth?response_type=code&scope=https://www.googleapis.com/auth/chromewebstore&client_id=$CLIENT_ID&redirect_uri=urn:ietf:wg:oauth:2.0:oob
$options = OpenStruct.new({
client_id: ENV.fetch("CLIENT_ID"),
client_secret: ENV.fetch("CLIENT_SECRET"),
refresh_token: ENV.fetch("REFRESH_TOKEN"),
environment: "staging",
})
### Helper Methods
def post(url, params)
uri = URI.parse(url)
end
def access_token
@access_token ||= begin
uri = URI.parse("https://www.googleapis.com/oauth2/v4/token")
params = {
client_id: $options.client_id,
client_secret: $options.client_secret,
refresh_token: $options.refresh_token,
grant_type: "refresh_token",
}
response = Net::HTTP.post_form(uri, params)
JSON.parse(response.body)["access_token"]
end
end
def post_upload
# Multipart upload with net/http is not included in the stdlib :-(
cmd = <<-END
curl -s \
-H "Authorization: Bearer #{access_token}" \
-H "x-goog-api-version: 2" \
-X PUT \
-T #{zip_file} \
https://www.googleapis.com/upload/chromewebstore/v1.1/items/#{$options.app_id}
END
output = `#{cmd}`
json = JSON.parse(output)
if json["uploadState"] == "SUCCESS"
puts "Uploaded #{zip_file} #{$options.app_id} to the webstore"
else
raise "Error Uploading to #{$options.app_id} to the webstore: \n#{json}"
end
end
def post_publish
http = Net::HTTP.new("www.googleapis.com", 443)
http.use_ssl = true
path = "/chromewebstore/v1.1/items/#{$options.app_id}/publish"
headers = {
"Content-Length" => "0",
"Content-Type" => "application/x-www-form-urlencoded",
"x-goog-api-version" => "2",
"Authorization" => "Bearer #{access_token}",
}
response = http.post(path, "", headers)
json = JSON.parse(response.body)
if json["status"].first == "OK"
puts "Published #{$options.app_id} to the webstore"
else
raise "Error Publishing to #{$options.app_id} to the webstore: \n#{json}"
end
end
def zip_file
version = open("VERSION").read.chomp
if ENV["TRAVIS_BUILD_NUMBER"]
version = "#{version}.#{ENV["TRAVIS_BUILD_NUMBER"]}"
end
raise "TODO: have this method return a path to your zip file"
end
### Option Parsing
OptionParser.new do |opts|
opts.banner = "Usage: publish-to-chrome-web-store [options]"
opts.on("-e", "--env [NAME]", "Select environment (staging, production)") do |e|
$options.environment = e
end
opts.on("-a", "--app-id [ID]", "Chrome Store App ID (#{$options.app_id})") do |i|
$options.app_id = i
end
opts.on("-p", "--publish", "Publish to the public") do |p|
$options.should_publish = p
end
end.parse!
### Script
#### Step 1) Build the App
raise "TODO: this is the point where you want to build/zip your app"
#### Step 2) Upload the App
post_upload
#### Step 3) Publish the App
post_publish if $options.should_publish
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment