motion-sparkle-sandbox 2.0.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
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