motion-sparkle-sandbox 2.0.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +7 -0
  5. data/.rubocop_todo.yml +183 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +37 -0
  8. data/Gemfile +13 -3
  9. data/README.md +72 -72
  10. data/Rakefile +2 -7
  11. data/bin/bundle +114 -0
  12. data/bin/byebug +29 -0
  13. data/bin/coderay +29 -0
  14. data/bin/fuzzy_match +29 -0
  15. data/bin/htmldiff +29 -0
  16. data/bin/httpclient +29 -0
  17. data/bin/ldiff +29 -0
  18. data/bin/pod +29 -0
  19. data/bin/pry +29 -0
  20. data/bin/rake +29 -0
  21. data/bin/rspec +29 -0
  22. data/bin/rubocop +29 -0
  23. data/bin/ruby-parse +29 -0
  24. data/bin/ruby-rewrite +29 -0
  25. data/bin/sandbox-pod +29 -0
  26. data/bin/xcodeproj +29 -0
  27. data/lib/motion/project/appcast.rb +294 -111
  28. data/lib/motion/project/indent_string.rb +18 -0
  29. data/lib/motion/project/install.rb +22 -66
  30. data/lib/motion/project/package.rb +52 -36
  31. data/lib/motion/project/project.rb +42 -51
  32. data/lib/motion/project/rake_tasks.rb +38 -28
  33. data/lib/motion/project/setup.rb +67 -73
  34. data/lib/motion/project/sparkle.rb +317 -148
  35. data/lib/motion/project/templates.rb +24 -22
  36. data/lib/motion-sparkle-sandbox/version.rb +5 -0
  37. data/lib/motion-sparkle-sandbox.rb +19 -3
  38. data/motion-sparkle-sandbox.gemspec +26 -16
  39. data/sample-app/.gitignore +10 -0
  40. data/sample-app/Gemfile +8 -0
  41. data/sample-app/README.md +87 -0
  42. data/sample-app/Rakefile +47 -0
  43. data/sample-app/app/app_delegate.rb +15 -0
  44. data/sample-app/app/menu.rb +155 -0
  45. data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/1024x1024.png +0 -0
  46. data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Contents.json +68 -0
  47. data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_128x128.png +0 -0
  48. data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_128x128@2x.png +0 -0
  49. data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_16x16.png +0 -0
  50. data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_16x16@2x.png +0 -0
  51. data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_256x256.png +0 -0
  52. data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_256x256@2x.png +0 -0
  53. data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_32x32.png +0 -0
  54. data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_32x32@2x.png +0 -0
  55. data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_512x512.png +0 -0
  56. data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_512x512@2x.png +0 -0
  57. data/sample-app/resources/Assets.xcassets/Contents.json +6 -0
  58. data/sample-app/resources/Credits.rtf +29 -0
  59. data/sample-app/spec/main_spec.rb +11 -0
  60. data/spec/appcast_spec.rb +60 -0
  61. data/spec/setup_spec.rb +42 -0
  62. data/spec/sparkle_spec.rb +94 -73
  63. data/spec/spec_helper.rb +100 -27
  64. data/spec/spec_utils.rb +68 -0
  65. data/vendor/.git_keep +0 -0
  66. metadata +80 -14
  67. data/vendor/README.md +0 -34
  68. data/vendor/Sparkle.zip +0 -0
  69. data/vendor/codesign_embedded_executable +0 -46
  70. data/vendor/generate_appcast +0 -0
@@ -1,67 +1,58 @@
1
- module Motion::Project
1
+ # frozen_string_literal: true
2
2
 
3
- class Config
4
- variable :sparkle
3
+ require 'open3'
5
4
 
6
- def sparkle(&block)
7
- @sparkle ||= Motion::Project::Sparkle.new(self)
8
- if block
9
- @sparkle.instance_eval &block
10
- end
11
- @sparkle
12
- end
13
- end
5
+ module Motion
6
+ module Project
7
+ class Config
8
+ variable :sparkle
14
9
 
15
- class App
16
- class << self
17
- def build_with_sparkle(platform, opts = {})
18
- if App.config.sparkle.setup_ok?
19
- App.info "Sparkle", "Setup OK"
20
- else
21
- exit 1
22
- end
23
- build_without_sparkle(platform, opts)
10
+ def sparkle(&block)
11
+ @sparkle ||= Motion::Project::Sparkle.new(self)
12
+ @sparkle.instance_eval(&block) if block
13
+ @sparkle.after_initialize
14
+ @sparkle
24
15
  end
25
-
26
- alias_method "build_without_sparkle", "build"
27
- alias_method "build", "build_with_sparkle"
28
16
  end
29
- end
30
17
 
31
- class Builder
32
- # if we're using the sandboxed version of Sparkle, then we need to copy the
33
- # xpc services to the proper folder and sign them. This has to be done
34
- # before we sign the app itself
35
- #------------------------------------------------------------------------------
36
- def codesign_with_sparkle(config, platform)
37
- if App.config.embedded_frameworks.any? {|item| item.to_s.include?('Sparkle.framework')}
38
- bundle_path = App.config.app_bundle('MacOSX')
18
+ class App
19
+ class << self
20
+ def build_with_sparkle(platform, opts = {})
21
+ App.fail 'Sparkle not setup correctly' unless App.config.sparkle.setup_ok?
39
22
 
40
- if File.directory?(App.config.sparkle.sparkle_xpc_path)
41
- App.info 'Sparkle', 'Removing unnecessary executables...'
42
- sparkle_path = File.join(bundle_path, "Frameworks/Sparkle.framework")
43
- ['Resources/Autoupdate', 'Resources/Updater.app'].each do |item|
44
- bundle = File.join(sparkle_path, item)
45
- FileUtils.rm_r(bundle) if File.exist?(bundle)
46
- end
23
+ App.info 'Sparkle', 'Setup OK'
47
24
 
48
- xpc_path = File.join(bundle_path, "XPCServices")
49
- App.info 'Sparkle', "Copying XPCServices to #{xpc_path}"
25
+ build_without_sparkle(platform, opts)
26
+ end
50
27
 
51
- FileUtils.mkdir_p(xpc_path)
52
- `cp -R #{App.config.sparkle.sparkle_xpc_path}/*.xpc "#{xpc_path}"`
28
+ alias_method 'build_without_sparkle', 'build'
29
+ alias_method 'build', 'build_with_sparkle'
30
+ end
31
+ end
53
32
 
54
- Dir.glob("#{xpc_path}/*.xpc").each do |path|
55
- App.info 'Codesign', path
56
- results = `#{App.config.sparkle.sparkle_vendor_path}/codesign_embedded_executable "#{App.config.codesign_certificate}" "#{File.expand_path(path)}" 2>&1`
57
- end
33
+ class Builder
34
+ # The XPC services are already residing in the Sparkle package. But we need
35
+ # to re-sign the entire package to ensure all executables have the hardened
36
+ # runtime and correct certificate.
37
+ #------------------------------------------------------------------------------
38
+ def codesign_with_sparkle(config, platform)
39
+ if App.config.embedded_frameworks.any? { |item| item.to_s.include?('Sparkle.framework') }
40
+ bundle_path = App.config.app_bundle('MacOSX')
41
+ sparkle_path = File.join(bundle_path, 'Frameworks', 'Sparkle.framework')
42
+
43
+ `/usr/bin/codesign -f -s "#{config.codesign_certificate}" -o runtime "#{sparkle_path}/Versions/B/Autoupdate"`
44
+ `/usr/bin/codesign -f -s "#{config.codesign_certificate}" -o runtime "#{sparkle_path}/Versions/B/Updater.app"`
45
+ `/usr/bin/codesign -f -s "#{config.codesign_certificate}" -o runtime "#{sparkle_path}/Versions/B/XPCServices/org.sparkle-project.InstallerLauncher.xpc"`
46
+ `/usr/bin/codesign -f -s "#{config.codesign_certificate}" -o runtime --entitlements "./vendor/Pods/Sparkle/Entitlements/org.sparkle-project.Downloader.entitlements" "#{sparkle_path}/Versions/B/XPCServices/org.sparkle-project.Downloader.xpc"` # rubocop:disable Layout/LineLength
47
+
48
+ `/usr/bin/codesign -f -s "#{config.codesign_certificate}" -o runtime "#{sparkle_path}"`
58
49
  end
50
+
51
+ codesign_without_sparkle(config, platform)
59
52
  end
60
53
 
61
- codesign_without_sparkle(config, platform)
54
+ alias_method 'codesign_without_sparkle', 'codesign'
55
+ alias_method 'codesign', 'codesign_with_sparkle'
62
56
  end
63
-
64
- alias_method "codesign_without_sparkle", "codesign"
65
- alias_method "codesign", "codesign_with_sparkle"
66
57
  end
67
58
  end
@@ -1,18 +1,33 @@
1
- # Rake tasks
1
+ # frozen_string_literal: true
2
+
3
+ # Sparkle specific rake tasks
4
+ # rubocop:disable Metrics/BlockLength
2
5
  namespace :sparkle do
6
+ desc 'Sparkle Help'
7
+ task :help do
8
+ puts <<~HELP
3
9
 
4
- task :install do
5
- sparkle = App.config.sparkle
6
- sparkle.install
10
+
11
+ During initial Sparkle setup, run these rake tasks:
12
+
13
+ 1. `rake sparkle:setup_certificates`
14
+ 2. `rake sparkle:setup`
15
+
16
+ Then after running `rake build:release`, you can run
17
+
18
+ 3. `rake sparkle:package` create the zipped package and release notes
19
+ 4. `rake sparkle:copy_to_release` copy package/notes into release folder
20
+ 5. `rake sparkle:generate_appcast` generate the appcast
21
+ HELP
7
22
  end
8
23
 
9
- desc "Setup Sparkle configuration"
24
+ desc 'Setup Sparkle configuration'
10
25
  task :setup do
11
26
  sparkle = App.config.sparkle
12
27
  sparkle.setup
13
28
  end
14
29
 
15
- desc "Create a ZIP file with you application .app release build"
30
+ desc 'Create a ZIP file with your application .app release build'
16
31
  task :package do
17
32
  App.config_without_setup.build_mode = :release
18
33
  sparkle = App.config.sparkle
@@ -24,50 +39,44 @@ namespace :sparkle do
24
39
  sparkle.generate_keys
25
40
  end
26
41
 
27
- desc "Sign the ZIP file with appropriate certificates"
42
+ desc 'Generate the EdDSA signature for a package'
28
43
  task :sign do
29
44
  App.config_without_setup.build_mode = :release
30
45
  sparkle = App.config.sparkle
31
46
  sparkle.sign_package
32
47
  end
33
48
 
34
- task :recreate_public_key do
35
- sparkle = App.config.sparkle
36
- sparkle.generate_public_key
37
- end
38
-
39
- task :copy_release_notes_templates do
49
+ desc 'Copy the release notes and zip archive to the release folder'
50
+ task :copy_to_release do
40
51
  App.config_without_setup.build_mode = :release
41
52
  sparkle = App.config.sparkle
42
- sparkle.copy_templates(force = true)
53
+ sparkle.copy_to_release
43
54
  end
44
55
 
45
- desc "Generate the appcast xml feed"
46
- task :feed do
56
+ desc "Generate the appcast xml feed using Sparkle's `generate_appcast`"
57
+ task :generate_appcast do
47
58
  App.config_without_setup.build_mode = :release
48
59
  sparkle = App.config.sparkle
49
- sparkle.create_appcast
60
+ sparkle.generate_appcast
50
61
  end
51
62
 
52
- desc "Generate the appcast using Sparkle's `generate_appcast`"
53
- task :generate_appcast do
54
- App.config_without_setup.build_mode = :release
55
- sparkle = App.config.sparkle
56
- results = `#{sparkle.sparkle_vendor_path}/generate_appcast "#{sparkle.private_key_path}" "#{sparkle.archive_folder}"`
63
+ namespace :generate_appcast do
64
+ desc "Show help for Sparkle's `generate_appcast`"
65
+ task :help do
66
+ App.config_without_setup.build_mode = :release
67
+ sparkle = App.config.sparkle
68
+ sparkle.generate_appcast_help
69
+ end
57
70
  end
58
71
 
59
- desc "Update the release notes of this build"
72
+ desc 'Update the release notes of this build'
60
73
  task :release_notes do
61
74
  App.config_without_setup.build_mode = :release
62
75
  sparkle = App.config.sparkle
63
76
  sparkle.create_release_notes
64
77
  end
65
78
 
66
- desc "Upload to configured location"
67
- task :upload do
68
- end
69
-
70
- desc "Clean the Sparkle release folder"
79
+ desc 'Clean the Sparkle release folder'
71
80
  task :clean do
72
81
  dir = Motion::Project::Sparkle::RELEASE_PATH
73
82
  if File.exist?("./#{dir}")
@@ -87,3 +96,4 @@ namespace :clean do
87
96
  end
88
97
  end
89
98
  end
99
+ # rubocop:enable Metrics/BlockLength
@@ -1,96 +1,90 @@
1
- module Motion::Project
2
- class Sparkle
1
+ # frozen_string_literal: true
3
2
 
4
- def setup_ok?
5
- config_ok?
6
- certificates_ok?
7
- end
3
+ module Motion
4
+ module Project
5
+ class Sparkle
6
+ def setup_ok?
7
+ config_ok?
8
+ certificates_ok?
9
+ end
8
10
 
9
- def config_ok?
10
- check_base_url
11
- check_feed_url
12
- check_public_key
13
- end
11
+ def config_ok?
12
+ check_base_url
13
+ check_feed_url
14
+ check_public_key
15
+ end
16
+
17
+ def check_base_url
18
+ return true if appcast.base_url.present?
14
19
 
15
- def check_base_url
16
- base_url_check = appcast.base_url.to_s
17
- if base_url_check.nil? or base_url_check.empty?
18
20
  App.fail "Sparkle :base_url missing. Use `release :base_url, 'http://example.com/your_app_folder'` in your Rakefile's `app.sparkle` block"
19
21
  end
20
- true
21
- end
22
22
 
23
- def check_feed_url
24
- feed_url_check = @config.info_plist['SUFeedURL']
25
- feed_filename_check = appcast.feed_filename
26
- if feed_url_check.nil? or feed_url_check.empty? or feed_filename_check.nil? or feed_filename_check.empty?
27
- App.fail "Sparkle :feed_filename is nil or blank. Please check your Rakefile."
23
+ def check_feed_url
24
+ return true if feed_url.present? && appcast.feed_filename.present?
25
+
26
+ App.fail 'Sparkle :feed_filename is nil or blank. Please check your Rakefile.'
28
27
  end
29
- true
30
- end
31
28
 
32
- def check_public_key
33
- public_key_check = @config.info_plist['SUPublicDSAKeyFile'].to_s
34
- if public_key_check.nil? or public_key_check.empty?
35
- App.fail "Sparkle :public_key is nil or blank. Please check your Rakefile."
29
+ def check_public_key
30
+ return true if public_ed_dsa_key.present?
31
+
32
+ App.fail 'Sparkle :public_key is nil or blank. Please check your Rakefile.'
36
33
  end
37
- true
38
- end
39
34
 
40
- def certificates_ok?(silence=false)
41
- unless File.exist?("./#{Sparkle::CONFIG_PATH}")
42
- if silence
43
- return false
44
- else
45
- App.fail "Missing `#{Sparkle::CONFIG_PATH}`. Run `rake sparkle:setup` to get started"
35
+ def certificates_ok?(silence = false)
36
+ unless File.exist?("./#{Sparkle::CONFIG_PATH}")
37
+ return false if silence
38
+
39
+ App.fail "Missing `#{Sparkle::CONFIG_PATH}`. Run `rake sparkle:setup` to get started"
46
40
  end
47
- end
48
- unless File.exist?(private_key_path)
49
- if silence
50
- return false
51
- else
41
+
42
+ if appcast.use_exported_private_key && !File.exist?(private_key_path)
43
+ return false if silence
44
+
52
45
  App.fail "Missing `#{private_key_path}`. Please run `rake sparkle:setup_certificates` or check the docs to know where to put them."
53
46
  end
54
- end
55
- unless File.exist?(public_key_path)
56
- if silence
57
- return false
58
- else
47
+
48
+ unless public_ed_dsa_key.present?
49
+ return false if silence
50
+
59
51
  App.fail "Missing `#{public_key_path}`. Did you configure `release :public_key` correctly in the Rakefile? Advanced: recreate your public key with `rake sparkle:recreate_public_key`"
60
52
  end
53
+
54
+ true
61
55
  end
62
- true
63
- end
64
56
 
65
- def setup
66
- verify_installation
67
- create_sparkle_folder
68
- add_to_gitignore
69
- copy_templates
57
+ def setup
58
+ verify_installation
59
+ create_sparkle_folder
60
+ add_to_gitignore
61
+ copy_templates
70
62
 
71
- if config_ok?
72
- App.info "Sparkle", "Config found"
73
- else
74
- return false
75
- end
63
+ return false unless config_ok?
64
+
65
+ App.info 'Sparkle', 'Config found'
76
66
 
77
- silence = true
78
- if certificates_ok?(silence)
79
- App.info "Sparkle", "Certificates found"
80
- else
81
- App.info "Sparkle", "Certificates not found
82
- Please generate your private and public keys with
83
- `rake sparkle:setup_certificates`
84
- If you already have your certificates and only need to include them in the project, follow these steps:
85
- 1. Rename your private key to `./#{private_key_path}`
86
- 2. Place your public key in `./#{public_key_path}`
87
- 3. If you wish to use a different name or location for your public key within the resources dir,
88
- make sure you add `publish :public_key, 'folder/new_name.pem'` to the sparkle config in your Rakefile
89
- "
90
- return false
67
+ silence = true
68
+ unless certificates_ok?(silence)
69
+ App.info 'Sparkle', <<~CERTIFICATES
70
+ Certificates not found
71
+
72
+ Please generate your private and public keys with
73
+ `rake sparkle:setup_certificates`
74
+
75
+ If you already have your certificates and only need to include them in the project, follow these steps:
76
+ 1. Rename your private key to `./#{private_key_path}`
77
+ and make sure you've added it to your `.gitignore` file - it should NEVER be
78
+ stored in your repository
79
+ 2. Add `publish :public_key, 'PUBLIC_KEY'` to the Sparkle config in your Rakefile
80
+ CERTIFICATES
81
+
82
+ return false
83
+ end
84
+
85
+ App.info 'Sparkle', 'Certificates found'
86
+ App.info 'Sparkle', 'Setup OK. After `rake build:release`, you can now run `rake sparkle:package`.'
91
87
  end
92
- App.info "Sparkle", "Setup OK. After `rake build:release`, you can now run `rake sparkle:package`."
93
88
  end
94
-
95
89
  end
96
90
  end