Class: Everywhere::Commands::UpdatesKeygen

Inherits:
Dry::CLI::Command
  • Object
show all
Defined in:
lib/everywhere/commands/updates_keygen.rb

Overview

Mint the minisign-compatible keypair that signs this app's updates. Secret key lands in ~/.rubyeverywhere/keys/<bundle_id>.key (never in the app repo); the public key goes into everywhere.yml's updates.public_key, where the build bakes it into the shell for verification.

Instance Method Summary collapse

Instance Method Details

#call(root: ".", force: false, passphrase: false) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/everywhere/commands/updates_keygen.rb', line 21

def call(root: ".", force: false, passphrase: false, **)
  config = Everywhere::Config.load(File.expand_path(root))
  bundle_id = config.bundle_id
  keys_dir = File.join(Paths.cache_dir, "keys")
  sk_path = File.join(keys_dir, "#{bundle_id}.key")
  pub_path = File.join(keys_dir, "#{bundle_id}.pub")

  if File.exist?(sk_path) && !force
    UI.die!("a signing key for #{bundle_id} already exists at #{UI.short_path(sk_path)}" \
            "pass --force to overwrite it (shipped apps signed with the old key will REFUSE updates signed with a new one)")
  end

  UI.phase("Generating update signing key for #{bundle_id}")
  pair = Minisign.keygen(passphrase: passphrase ? prompt_passphrase : "")

  require "fileutils"
  FileUtils.mkdir_p(keys_dir, mode: 0o700)
  File.write(sk_path, pair.secret_key, perm: 0o600)
  File.write(pub_path, pair.public_key, perm: 0o644)

  UI.ok("secret key #{UI.short_path(sk_path)} #{UI.dim("(key id #{pair.key_id_hex})")}")
  UI.ok("public key #{UI.short_path(pub_path)}")

  UI.phase("Add the public key to config/everywhere.yml")
  puts <<~YAML

    updates:
      url: https://your-bucket-or-cdn.example.com/#{config.name.downcase.gsub(/[^a-z0-9]+/, "-")}
      public_key: "#{Minisign.public_key_base64(pair.public_key)}"

  YAML
  UI.substep("back up the secret key somewhere safe — losing it strands every shipped app on its current version")
end