summaryrefslogtreecommitdiff
path: root/scripts/release.sh
blob: 320f12e632fc7c4b351cbc6a271b82b14842d0fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
#!/bin/bash

# George Miller
# 05-17-2022
# If you do not have permission to run, try: chmod u+x release.sh

# A utility function for prompting the user Y/N
# This takes in a string prompt for the input
# This returns 1 for yes/true or 0 for no/false
prompt_user() {
    user_input="g"
    echo
    echo $1" (Y/N)?"
    read user_input
    while [[ ! $user_input == [YyNn] ]]; do
        echo $1" (Y/N)?"
        read user_input
    done
    if [[ ! $user_input == [Nn] ]]; then
        return 1
    else
        return 0
    fi
}

# Script start
echo 
echo "Starting SDL release script..."

# If we are running from the scripts directory, we want to pop back to the project root to do everything.
if [[ $PWD == *"scripts" ]]; then
    cd ..
fi
# If, for some reason, we are not now in the correct working directory, exit
if [[ $PWD != *"sdl_ios" ]]; then
    echo "Please run this from the sdl_ios project root or the sdl_ios/scripts directory"
    exit 0
fi

# Setup branch variables
develop_branch="develop"
main_branch="master"

# Checkout develop - so we can update versions.
# We need to checkout the branch before we start modifying files.
current_branch=$(git branch --show-current)
if [ $current_branch == $develop_branch ]; then
    echo
    echo "$develop_branch is already checked out."
else
    echo
    echo "Checkout of $develop_branch is required for some steps"
    prompt_user "Would you like to automatically checkout $develop_branch"
    if [[ $? == 1 ]]; then

        # Stash any local changes to avoid errors during checkout
        changes=$(git diff-files)
        if [ ! -z "$changes" ]; then   
            echo "There are unstaged changes in these files"
            echo $changes
            prompt_user "Would you like to stash these local changes before checkout of $develop_branch"
            if [[ $? == 1 ]]; then
                # Stash local changes to prevent issues with checkout
                git stash
                echo "Local changes have been stashed."
                echo "Use \"git stash pop\" when this script is complete to restore your changes"
            else
                # Dump local changes to prevent issues with checkout.  Reset cleans up any uncommitted changes to the index.  Clean takes care of non-indexed files.
                echo "Local changes were not stashed."
                git reset --hard
                git clean -fxd
            fi
        fi
        
        # Do a pull to make sure we are up to date.
        git pull --ff
        
        # Now do the checkout
        git checkout $develop_branch
        
        # check if the checkout was successful
        current_branch=$(git branch --show-current)
        if [ $current_branch == $develop_branch ]; then
            develop_checked_out=1
        else
            echo "Automatic checkout has failed. Abort."
            exit 0
        fi
    fi
fi

# Fix any header files that are in the wrong location according to the project file
prompt_user "Would you like to run the project file header fixer"
if [[ $? == 1 ]]; then
    chmod u+x ./scripts/project_file_header_fix.sh
    ./scripts/project_file_header_fix.sh
fi

# Bump version in projectFile
echo
echo "Updating the version"

# Get the current version and build from the podspec file
project_file="./SmartDeviceLink-iOS.xcodeproj/project.pbxproj"
new_file="./SmartDeviceLink-iOS.xcodeproj/new.pbxproj"
current_version_number=$(sed -n '/MARKETING_VERSION/{s/MARKETING_VERSION = //;s/;//;s/^[[:space:]]*//;p;q;}' $project_file)
echo "Current Version: "$current_version_number

# Prompt user for new version
echo "Enter the new version number (semantic versioning x.x.x format) or blank to skip: "
read new_version_number

# If blank or the same, then skip. Otherwise change the version number
if [ -z $new_version_number ]; then
    echo "No version number entered. Skipping..."
    new_version_number=$current_version_number
else
    if [ $current_version_number != $new_version_number ]; then
        echo "Changing Version Number in $project_file"
        # Swap new version in to file
        sed '/MARKETING_VERSION/{s/'$current_version_number'/'$new_version_number'/;}' $project_file > $new_file
        mv -f $new_file $project_file
    else
        echo "No project file change needed for version"
    fi
fi

# Get the current version from the podspec file
pod_spec_file="SmartDeviceLink-iOS.podspec"
pod_spec_new_file="NewFile.podspec"
current_version=$(sed -n '/s.version/{s/s.version//;s/=//;s/[\"]//g;s/^[[:space:]]*//g;p;q;}' $pod_spec_file)

# Use new version number from above. If new version is different from current, change it.
if [ $current_version != $new_version_number ]; then
    echo "changing version in $pod_spec_file to $new_version_number"
    # Swap new version in to file
    sed '/s.version/{s/'$current_version'/'$new_version_number'/;}' $pod_spec_file > $pod_spec_new_file
    mv -f $pod_spec_new_file $pod_spec_file
fi

# Update RPC and protocol versions in /SmartDeviceLink/private/SDLGlobals.m
echo 
echo "Checking SDLGlobals.m for RPC and Protocol versions"
file="SmartDeviceLink/private/SDLGlobals.m"
current_rpc_version=$(sed -n '/SDLMaxProxyRPCVersion/{s/^.*@//;s/[\;]//;s/[\"]//g;p;q;}' $file)
current_protocol_version=$(sed -n '/SDLMaxProxyProtocolVersion/{s/^.*@//;s/[\;]//;s/[\"]//g;p;q;}' $file)
echo "Current RPC Version: "$current_rpc_version
echo "Current Protocol Version: "$current_protocol_version
echo "If these are not correct, please update versions in /SmartDeviceLink/private/SDLGlobals.m. Then press enter..."
read user_input

# Update to the newest BSON submodule. Update Package.swift and CocoaPods dependency files to point to latest if necessary.
# Extract version and link from Package.swift
package_file="Package.swift"
package_dependency_info="$(sed -n '/.package/{s/let package = Package(//;s/.package(//;s/)//;s/^[[:space:]]*//g;p;}' $package_file)"
if [ ! -z "$submodule_info" ]; then
    # Loop through the dependencies 
    while IFS= read -r dependency_record ;
    do
        # If the dependency_record in the dependancies is not empty (the first one usually is due to string interpretation of a list)
        if [ ! -z "$dependency_record" ]; then
            # Identify the fields of the record
            record_info="$(sed 's/,/\n/g' <<< $dependency_record)"
            record_name=$(sed -n '/name:/{s/name://g;s/^[[:space:]]*//g;s/"//g;p;}' <<< "$record_info")
            record_url=$(sed -n '/url:/{s/url://g;s/^[[:space:]]*//g;s/"//g;p;}' <<< "$record_info")
            record_version=$(sed -n '/from:/{s/from://g;s/^[[:space:]]*//g;s/"//g;p;}' <<< "$record_info")
            echo
            echo "Current version of $record_name: "$record_version
        fi
    done <<< "$submodule_info"
    echo
    echo "Please update the dependencies in Package.swift, SmartDeviceLink.podspec, and SmartDeviceLink-iOS.podspec appropriately, then press enter..."
    read user_input 
fi

# Update changelog
# TODO - we could insert a template into the changelog that includes the version the users have selected above.
echo 
echo "Please update CHANGELOG.md, then return here and press enter..."
read user_input
# TODO - check modified info before and after so we can detect if the user updated the file.

# Generate documentation
prompt_user "Would you like to automatically generate documentation with Jazzy"
if [[ $? == 1 ]]; then
    # Check if Jazzy is already installed, and if not then install jazzy
    if [ -z "$(mdfind -name 'Jazzy')" ]; then
        echo "Jazzy is not installed, attempting to install (may require your password)..."
        sudo gem install jazzy
    fi

    # This runs Jazzy to generate the documentation.
    echo "Running Jazzy to generate documentation..."
    # generate-documentation.sh throws an error if we are not in the correct directory when we run it.
    cd scripts
    chmod u+x ./generate-documentation.sh
    if [ $(uname -m) == "x86_64" ]; then
        ./generate-documentation.sh
    else
        arch -x86_64 /bin/bash ./generate-documentation.sh
    fi
    cd ..
fi

# Ensure that the RPC_SPEC has released to the master branch and update the submodule to point to the new release tag (or to the HEAD of master, if no release of the RPC_SPEC is occurring).
echo 
echo "Please check if there is a new release of the RPC_SPEC on https://www.github.com/smartdevicelink/rpc_spec"
echo "If there is, please update the rpc_spec submodule to point to the newest commit on the master branch. Press enter to continue..."
read user_input

# Git commands
# Check to make sure the correct branch is checked out.
current_branch=$(git branch --show-current)
if [ $current_branch == $develop_branch ]; then
    echo
    echo "$develop_branch has already been checked out for you."

    prompt_user "Would you like to walk through the git commands for this release"
    if [[ $? == 1 ]]; then
        prompt_user "Would you like to commit and push the changes made so far to the develop branch"
        if [[ $? == 1 ]]; then
            # Add, commit, and push changes to develop
            git add -A
            git commit -m "Update for release $new_version_number"
            git push --set-upstream origin $develop_branch
        else
            echo "Aborting script!"
            exit 0
        fi


        # Merge release to master (update master from develop)
        prompt_user "Would you like to merge this release from develop to master? (This will not push to master)"
        if [[ $? == 1 ]]; then
            # Checkout master
            git checkout $main_branch

            # Merge develop with master.
            # This updates the checked out master with the contents of develop
            git merge $develop_branch $main_branch

            echo "Please check that everything is correct."
        
            # Tag it
            prompt_user "Would you like to tag this release with $new_version_number? (This will not push the tag)"
            if [[ $? == 1 ]]; then
                git tag $new_version_number
            fi
            
            echo "If these changes are correct, please commit them manually and then push them to master..."
            read user_input
            # TODO - here are the commands if we decide to automate this.
            # git commit -m "commit message here "
            # git push --set-upstream origin $main_branch
        else
            echo "Aborting script!"
            exit 0
        fi

        # Merge master back to develop
        prompt_user "Would you like to merge master back into develop (You will need to push manually)"
        if [[ $? == 1 ]]; then
            git checkout $develop_branch
            git merge $main_branch $develop_branch
        else
            echo "Aborting script!"
            exit 0
        fi
    fi

else
    echo "You do not have $develop_branch currently checked out."
fi

# TODO - can we provide templates for the release based on the changelog?
# TODO - can we open directories for drag and drop to the release?
# Create new release for tag
prompt_user "Would you like to open to the Github releases page to create a release"
if [[ $? == 1 ]]; then
    open "https://github.com/smartdevicelink/sdl_ios/releases"
fi

# Push new release to primary and secondary cocoapod using command line:
prompt_user "Would you like to push the release to CocoaPods"
if [[ $? == 1 ]]; then
    pod trunk push SmartDeviceLink.podspec --allow-warnings
    pod trunk push SmartDeviceLink-iOS.podspec --allow-warnings
fi

prompt_user "Would you like to create a binary xcframework for adding to a Github release"
if [[ $? == 1 ]]; then
    # Create framework
    # We pass in the version so that the framework script does not need to ask
    # Give the user permissions to the framework script, then run the script.
    chmod u+x ./scripts/create_framework.sh
    if [ $(uname -m) == "x86_64" ]; then
        ./scripts/create_framework.sh $new_version_number
    else
        arch -x86_64 /bin/bash ./scripts/create_framework.sh $new_version_number
    fi
    
    echo 
    zip_file_name="SmartDeviceLink-$new_version_number.xcframework.zip"
    echo "Please add the framework at $zip_file_name to the Github release, then press enter..."
    read user_input
fi

# Rename the docset and pack it
prompt_user "Would you like to create the documentation docset for adding to a Github release"
if [[ $? == 1 ]]; then
    docset_directory="docs/docsets/"
    docset_tar_file_name="SmartDeviceLink-$new_version_number-docset.tgz"
    tar -czf $docset_tar_file_name $docset_directory

    echo 
    echo "Please add the docset at $docset_tar_file_name to the Github release, then press enter..."
    read user_input
fi
echo
echo "Release complete."