66# #
77# author: Craig Williams #
88# created: 2009-01-09 #
9+ # half rewritten by Charlie Stigler from 2009-present :) #
910# #
1011#################################################################################
1112# #
2526#################################################################################
2627
2728class AppCast
28- require 'rubygems'
2929 require 'yaml'
30- require 'tmpdir'
31- require 'fileutils'
32- require 'openssl'
33- require 'nokogiri'
34- require 'base64'
30+ require 'plist'
3531
3632 MESSAGE_HEADER = 'RUN SCRIPT DURING BUILD MESSAGE'
3733 YAML_FOLDER_PATH = "#{ ENV [ 'HOME' ] } /dev/selfcontrol/"
34+ SRCROOT = ENV [ 'SRCROOT' ] . chomp
3835
3936 def initialize
4037 @signature = ''
4138 require_release_build
39+ parse_project_settings
4240 project_setup
4341 load_config
4442
45- # the build_now setting in the config.yml file
46- # determines whether you want to perform this script
47- # set to 'NO' until you are ready to publish
48- exit_unless_build
49- base_folder
5043 appcast_setup
5144 end
5245
5346 def execute!
5447 create_appcast_folder_and_files
5548 remove_old_zip_create_new_zip
5649 file_stats
57- create_appcast_xml
58- puts "created appcast xml"
59- copy_archive_to_appcast_path
60- puts "copied archive to appcast path"
50+ create_appcast_xml_snippet
6151 end
6252
6353 # Only works for Release builds
@@ -78,91 +68,72 @@ def load_config
7868 end
7969 @config = YAML . load_file ( config_file_path )
8070 end
81-
82- def exit_unless_build
83- unless @config [ 'build_now' ] == 'YES'
84- log_message ( "The 'build_now' setting in 'config.yml' set to 'NO'\n If you are wanting to include this script in\n the build process change this setting to 'YES'" )
85- exit
86- end
71+
72+ def parse_project_settings
73+ plist = Plist . parse_xml ( "#{ SRCROOT } /Info.plist" )
74+
75+ @version = plist [ 'CFBundleShortVersionString' ]
8776 end
88-
77+
8978 def project_setup
9079 @proj_dir = ENV [ 'BUILT_PRODUCTS_DIR' ]
9180 @proj_name = ENV [ 'PROJECT_NAME' ]
92- @version = "2.3.2"
93- @build_number = "2.3.2"
9481 @archive_filename = "#{ @proj_name } -#{ @version . chomp } .zip" # underline character added
95- @archive_path = "#{ @proj_dir } / #{ @archive_filename } "
82+ @archive_path = "#{ SRCROOT } /release/ #{ @archive_filename } " . chomp
9683 end
97-
84+
9885 def appcast_setup
9986 @appcast_xml_name = @config [ 'appcast_xml_name' ] . chomp
100- @appcast_proj_folder = "#{ @config [ 'appcast_basefolder' ] } / #{ @proj_name } - #{ @version } " . chomp
101- @appcast_xml_path = "#{ @appcast_proj_folder } /#{ @appcast_xml_name } "
102- @min_system_version = @config [ 'min_system_version ']
87+ @appcast_release_folder = "#{ SRCROOT } /release " . chomp
88+ @appcast_xml_path = "#{ @appcast_release_folder } /#{ @appcast_xml_name } "
89+ @min_system_version = ENV [ 'MACOSX_DEPLOYMENT_TARGET ']
10390 @download_base_url = @config [ 'download_base_url' ]
10491 @web_base_url = @config [ 'web_base_url' ]
105- @css_file_name = @config [ 'css_file_name' ]
10692 @releasenotes_url = "#{ @web_base_url } /releasenotes.html#collapse-#{ @version . chomp . gsub ( '.' , '-' ) } "
10793 @download_url = "#{ @download_base_url } #{ @archive_filename } "
10894 @appcast_download_url = "#{ @web_base_url } #{ @appcast_xml_name } "
10995 end
110-
111- def base_folder
112- @appcast_basefolder = @config [ 'appcast_basefolder' ] . chomp
113- File . expand_path ( @appcast_basefolder ) if @appcast_basefolder . start_with? ( "~" )
114- end
115-
96+
11697 def remove_old_zip_create_new_zip
11798 puts @proj_dir
11899 Dir . chdir ( @proj_dir )
119100 `rm -f #{ @proj_name } *.zip`
120- `ditto -ck --keepParent --rsrc --sequesterRsrc "#{ @proj_name } .app" "#{ @archive_filename } "`
121- end
122-
123- def copy_archive_to_appcast_path
124- begin
125- FileUtils . cp ( @archive_path , @appcast_proj_folder )
126- rescue
127- log_message ( "There was an error coplogying the zip file to appcast folder\n Error: #{ $!} " )
128- end
101+ `ditto -ck --keepParent --rsrc --sequesterRsrc "#{ @proj_name } .app" "#{ @archive_path } "`
129102 end
130-
103+
131104 def file_stats
132- @size = File . size ( @archive_filename )
133105 @pubdate = `date +"%a, %d %b %G %T %z"`
134106 end
135107
136- def get_signature
137- puts "Generating signature for archive at path #{ @archive_path } "
138- puts "Command: /usr/local/bin/sparkle/sign_update \" #{ @archive_path } \" /Volumes/SelfControl\ Keys\ and\ Secrets/Sparkle\ Signing\ Keys/dsa_priv.pem"
139- return `/usr/local/bin/sparkle/sign_update \" #{ @archive_path } \" \" /Volumes/SelfControl\ Keys\ and\ Secrets/Sparkle\ Signing\ Keys/dsa_priv.pem\" ` . chomp
108+ def get_dsa_signature
109+ puts "Generating DSA signature for archive at path #{ @archive_path } "
110+ puts "Command: #{ SRCROOT } /Pods/Sparkle/bin/old_dsa_scripts/sign_update \" #{ @archive_path } \" /Volumes/SelfControl\ Keys\ and\ Secrets/Sparkle\ Signing\ Keys/dsa_priv.pem"
111+ return `#{ SRCROOT } /Pods/Sparkle/bin/old_dsa_scripts/sign_update \" #{ @archive_path } \" \" /Volumes/SelfControl\ Keys\ and\ Secrets/Sparkle\ Signing\ Keys/dsa_priv.pem\" ` . chomp
112+ end
113+
114+ def get_eddsa_signature_and_length_parameters
115+ puts "Generating edDSA signature parameters for archive at path #{ @archive_path } "
116+ puts "Command: #{ SRCROOT } /Pods/Sparkle/bin/sign_update \" #{ @archive_path } \" "
117+ return `#{ SRCROOT } /Pods/Sparkle/bin/sign_update \" #{ @archive_path } \" ` . chomp
140118 end
141119
142- def create_appcast_xml
120+ def create_appcast_xml_snippet
143121 appcast_xml =
144- "<?xml version=\" 1.0\" encoding=\" utf-8\" ?>
145- <rss version=\" 2.0\" xmlns:sparkle=\" http://www.andymatuschak.org/xml-namespaces/sparkle\" xmlns:dc=\" http://purl.org/dc/elements/1.1/\" >
146- <title>#{ @proj_name } </title>
147- <link>#{ @appcast_download_url } </link>
148- <description>Most recent changes with links to updates.</description>
149- <language>en</language>
150- <item>
122+ " <item>
151123 <title>Version #{ @version . chomp } </title>
152124 <sparkle:releaseNotesLink>
153125 #{ @releasenotes_url }
154126 </sparkle:releaseNotesLink>
155127 <pubDate>#{ @pubdate . chomp } </pubDate>
156128 <enclosure url=\" #{ @download_url . chomp } \"
157- length=\" #{ @size } \"
158129 sparkle:version=\" #{ @version . chomp } \"
159130 sparkle:shortVersionString=\" #{ @version . chomp } \"
160- sparkle:dsaSignature=\" #{ get_signature } \"
131+ sparkle:dsaSignature=\" #{ get_dsa_signature } \"
132+ #{ get_eddsa_signature_and_length_parameters }
161133 type=\" application/octet-stream\"
162134 />
163135 <sparkle:minimumSystemVersion>#{ @min_system_version } </sparkle:minimumSystemVersion>
164- </item>
165- </rss>"
136+ </item>"
166137
167138 File . open ( @appcast_xml_path , 'w' ) { |f | f . puts appcast_xml }
168139 end
@@ -171,19 +142,14 @@ def create_appcast_xml
171142 # or is accidently moved or deleted
172143 # Creates an html file with generic note template if it does not exist
173144 # This way the notes file is named correctly as well
174- # Creates a css file named from yml file with default css
175145 def create_appcast_folder_and_files
176- base_folder = @appcast_basefolder
177- project_folder = @appcast_proj_folder
146+ project_folder = @appcast_release_folder
178147
179- notes_file = "#{ project_folder } /#{ File . basename ( @releasenotes_url . chomp ) } "
180- css_file_path = "#{ project_folder } /#{ @css_file_name } "
148+ notes_file = "#{ project_folder } /releasenotes-#{ @version } .html"
181149
182- Dir . mkdir ( base_folder ) unless File . exist? ( base_folder )
183150 Dir . mkdir ( project_folder ) unless File . exist? ( project_folder )
184-
185- File . open ( notes_file , 'w' ) { |f | f . puts release_notes_generic_text } unless File . exist? ( notes_file )
186- File . open ( css_file_path , 'w' ) { |f | f . puts decompressed_css } unless File . exist? ( css_file_path )
151+
152+ File . open ( notes_file , 'w' ) { |f | f . puts release_notes_html_snippet } unless File . exist? ( notes_file )
187153 end
188154
189155 def log_message ( msg )
@@ -192,83 +158,29 @@ def log_message(msg)
192158 puts msg
193159 puts "----------------------------------------------\n \n "
194160 end
195-
196- def decompressed_css
197- return css_text . gsub ( /\{ \s +/ , "{\n \t " ) . gsub ( /;/ , ";\n \t " ) . gsub ( /^\s +\} / , "}" ) . gsub ( /^\s +/ , "\t " )
198- end
199-
200- def release_notes_generic_text
201- return "
202- <html>
203- <head>
204- <meta http-equiv=\" content-type\" content=\" text/html;charset=utf-8\" >
205- <title>What's new in #{ @proj_name } ?</title>
206- <meta name=\" robots\" content=\" anchors\" >
207- <link href=\" rnotes.css\" type=\" text/css\" rel=\" stylesheet\" media=\" all\" >
208- </head>
209161
210- <body>
211- <br />
212- <table class=\" dots\" width=\" 100%\" border=\" 0\" cellspacing=\" 0\" cellpadding=\" 0\" summary=\" Two column table with heading\" >
213- <tr>
214- <td class=\" blue\" colspan=\" 2\" >
215- <h3>#{ @proj_name } #{ @version . chomp } Release Notes</h3>
216- </td>
217- </tr>
218- <tr>
219- <td valign=\" top\" >
220- <p>
221- <ul>
222- <li>DESCRIPTION</li>
223- </ul>
224- </p>
225- </td>
226- </tr>
227- </table>
228- <br>
229- </body>
230-
231- </html>"
232- end
233-
234- # This css will be expanded to a normal, easily editable form when written to file
235- def css_text
162+ def release_notes_html_snippet
163+ @releasenotes_url = "#{ @web_base_url } /releasenotes.html#collapse-#{ @version . chomp . gsub ( '.' , '-' ) } "
164+ url_friendly_version = @version . chomp . gsub ( '.' , '-' )
165+
236166 return "
237- body { margin: 2px 12px 12px; }
238- h1 h2 h3 p ol ul a a:hover { font-family: \" Lucida Grande\" , Arial, sans-serif; }
239- h1 { font-size: 11pt; margin-bottom: 0; }
240- h2 { font-size: 9pt; margin-top: 0; margin-bottom: -10px; }
241- h3 { font-size: 9pt; font-weight: bold; margin-top: -4px; margin-bottom: -4px; }
242- p { font-size: 9pt; line-height: 12pt; text-decoration: none; }
243- ol { font-size: 9pt; line-height: 12pt; list-style-position: outside; margin-top: 12px; margin-bottom: 12px; margin-left: -18px; padding-left: 40px; }
244- ol li { margin-top: 6px; margin-bottom: 6px; }
245- ol p { margin-top: 6px; margin-bottom: 6px; }
246- ul { font-size: 9pt; line-height: 12pt; list-style-type: square; list-style-position: outside; margin-top: 12px; margin-bottom: 12px; margin-left: -24px; padding-left: 40px; }
247- ul li { margin-top: 6px; margin-bottom: 6px; }
248- ul p { margin-top: 6px; margin-bottom: 6px; }
249- a { color: #00f; font-size: 9pt; line-height: 12pt; text-decoration: none; }
250- a:hover { color: #00f; text-decoration: underline; }
251- hr { text-decoration: none; border: solid 1px #bfbfbf; }
252- td { padding: 6px; }
253- #banner { background-color: #f2f2f2; background-repeat: no-repeat; padding: -2px 6px 0; position: fixed; top: 0; left: 0; width: 100%; height: 1.2em; float: left; border: solid 1px #bfbfbf; }
254- #caticon { margin-top: 3px; margin-bottom: -3px; margin-right: 5px; float: left; }
255- #pagetitle { margin-top: 12px; margin-bottom: 0px; margin-left: 40px; width: 88%; border: solid 1px #fff; }
256- #mainbox { margin-top: 2349px; padding-right: 6px; }
257- #taskbox { background-color: #e6edff; list-style-type: decimal; list-style-position: outside; margin: 12px 0; padding: 2px 12px; border: solid 1px #bfbfbf; }
258- #taskbox h2 { margin-top: 8; margin-bottom: -4px; }
259- #machelp { position: absolute; top: 2px; left: 10px ; }
260- #index { background-color: #f2f2f2; padding-right: 25px; top: 2px; right: 12px; width: auto; float: right; }
261- #next { position: absolute; top: 49px; left: 88%; }
262- #asindent { margin-left: 22px; font-size: 9pt; font-family: Verdana, Courier, sans-serif; }
263- .bread { color: #00f; font-size: 8pt; margin: -9px 0 -6px; }
264- .leftborder { color: #00f; font-size: 8pt; margin: -9px 0 -6px; padding-top: 2px; padding-bottom: 3px; padding-left: 8px; border-left: 1px solid #bfbfbf; }
265- .mult { margin-top: -8px; }
266- .blue { background-color: #e6edff; margin-top: -3px; margin-bottom: -3px; padding-top: -3px; padding-bottom: -3px; }
267- .rightfloater { float: right; margin-left: 15px; }
268- .rules { border-bottom: 1px dotted #ccc; }
269- .dots { border: dotted 1px #ccc; }
270- .seealso { margin-top: 4px; margin-bottom: 4px; }
271- code { color: black; font-size: 9pt; font-family: Verdana, Courier, sans-serif; }"
167+ <div class=\" accordion-group\" >
168+ <div class=\" accordion-heading\" >
169+ <a href=\" #collapse-#{ url_friendly_version } \" class=\" accordion-toggle\" data-toggle=\" collapse\" data-parent=\" #releasesAccordion\" >
170+ <h1 id=\" version-#{ url_friendly_version } \" >Version #{ @version } </h1>
171+ </a>
172+ </div>
173+ <div id=\" collapse-#{ url_friendly_version } \" class=\" accordion-body collapse\" >
174+ <div class=\" accordion-inner\" >
175+ <h3>For Mac OS X #{ @min_system_version } + only. Please don't upgrade while a block is running.</h3>
176+ <h3>Improvements</h3>
177+ <ul>
178+ <li>First great feature</li>
179+ <li>Second great feature</li>
180+ </ul>
181+ </div>
182+ </div>
183+ </div>"
272184 end
273185end
274186
0 commit comments