├── .github └── workflows │ ├── build.yml │ └── list-apple-teams.yml ├── .gitignore ├── LICENSE.md ├── Project ├── AndroidResources │ └── res │ │ ├── mipmap-anydpi-v26 │ │ └── ic_launcher.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_foreground.png │ │ └── values │ │ └── values.xml ├── Icon.png ├── Images.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-1024.png │ │ ├── Icon-120.png │ │ ├── Icon-152.png │ │ ├── Icon-167.png │ │ ├── Icon-180.png │ │ ├── Icon-40.png │ │ ├── Icon-58.png │ │ ├── Icon-76.png │ │ ├── Icon-80.png │ │ └── Icon-87.png │ ├── AppIconTV.brandassets │ │ ├── App Icon - Large.imagestack │ │ │ ├── Back.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-tvOS-Large-Background.png │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── Front.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-tvOS-Large-LogoA.png │ │ │ │ └── Contents.json │ │ │ └── Middle.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-tvOS-Large-LogoB.png │ │ │ │ └── Contents.json │ │ ├── App Icon - Small.imagestack │ │ │ ├── Back.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── Icon-tvOS-Small-Bg.png │ │ │ │ │ └── Icon-tvOS-Small-Bg@2x.png │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── Front.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── Icon-tvOS-Small-LogoA.png │ │ │ │ │ └── Icon-tvOS-Small-LogoA@2x.png │ │ │ │ └── Contents.json │ │ │ └── Middle.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── Icon-tvOS-Small-LogoB.png │ │ │ │ └── Icon-tvOS-Small-LogoB@2x.png │ │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── Top Shelf Image Wide.imageset │ │ │ ├── Contents.json │ │ │ ├── Icon-tvOS-TopShelfWide.png │ │ │ └── Icon-tvOS-TopShelfWide@2x.png │ │ └── Top Shelf Image.imageset │ │ │ ├── Contents.json │ │ │ ├── Icon-tvOS-TopShelf.png │ │ │ └── Icon-tvOS-TopShelf@2x.png │ ├── Contents.json │ └── LaunchImageTV.launchimage │ │ ├── Contents.json │ │ ├── Icon-tvOS-Launch.png │ │ └── Icon-tvOS-Launch@2x.png ├── LaunchScreen.storyboardc │ ├── 01J-lp-oVM-view-Ze5-6b-2t3.nib │ ├── Info.plist │ ├── UIViewController-01J-lp-oVM.nib │ └── designable.storyboard ├── ReadMe.txt ├── build.settings ├── config.lua ├── main.lua └── sampleUI │ ├── back-darkgrey.png │ ├── back-darkgrey@2x.png │ ├── back-darkgrey@4x.png │ ├── infobutton.png │ ├── infobutton@2x.png │ ├── infobutton@4x.png │ └── sampleUI.lua ├── README.md ├── README.ru.md └── Util ├── build.sh ├── deliver.sh ├── distribution.mobileprovision ├── distribution.p12 └── recipe.lua /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and Deliver 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | AppVersion: 7 | description: 'Version Name' 8 | required: true 9 | default: '1.0' 10 | Solar2DBuild: 11 | description: 'Solar2D Build Number' 12 | required: true 13 | default: '2024.3706' 14 | Xcode: 15 | description: 'Xcode Version' 16 | required: true 17 | default: '15.2' 18 | 19 | 20 | env: 21 | DEVELOPER_DIR: /Applications/Xcode_${{ github.event.inputs.Xcode }}.app/Contents/Developer # this forces Xcode version 22 | APP_VERSION: ${{ github.event.inputs.AppVersion }} 23 | S2D_BUILD_NAME: ${{ github.event.inputs.Solar2DBuild }} 24 | 25 | 26 | jobs: 27 | build: 28 | runs-on: macos-14 29 | steps: 30 | - uses: actions/checkout@v4 31 | - name: Build 32 | run: bash Util/build.sh 33 | env: 34 | CERT_PASSWORD: ${{ secrets.CertPassword }} 35 | APPLE_USERNAME: ${{ secrets.AppleUser }} 36 | APPLE_PASSWORD: ${{ secrets.ApplePassword }} 37 | APPLE_TEAM_ID: ${{ secrets.AppleTeamId }} 38 | - uses: actions/upload-artifact@v4 39 | with: 40 | name: IPA 41 | path: Util/*.ipa 42 | - name: Deliver 43 | run: bash Util/deliver.sh 44 | env: 45 | APPLE_USERNAME: ${{ secrets.AppleUser }} 46 | APPLE_PASSWORD: ${{ secrets.ApplePassword }} 47 | APPLE_TEAM_ID: ${{ secrets.AppleTeamId }} 48 | -------------------------------------------------------------------------------- /.github/workflows/list-apple-teams.yml: -------------------------------------------------------------------------------- 1 | name: List Apple Teams 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | list: 8 | runs-on: macos-12 9 | steps: 10 | - name: List Teams 11 | run: | 12 | set -e 13 | function err { 14 | echo "$1" 1>&2 15 | return 1 16 | } 17 | [ "${APPLE_USERNAME}" ] || err "AppleUser secret is required" 18 | [ "${APPLE_PASSWORD}" ] || err "ApplePassword secret is required" 19 | xcrun altool --list-providers -u "${APPLE_USERNAME}" -p "${APPLE_PASSWORD}" 20 | env: 21 | APPLE_USERNAME: ${{ secrets.AppleUser }} 22 | APPLE_PASSWORD: ${{ secrets.ApplePassword }} 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /Util/S2D/ 2 | *.dmg 3 | *.ipa 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Solar2D. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Project/AndroidResources/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Project/AndroidResources/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/AndroidResources/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /Project/AndroidResources/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/AndroidResources/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /Project/AndroidResources/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/AndroidResources/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /Project/AndroidResources/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/AndroidResources/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /Project/AndroidResources/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/AndroidResources/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Project/AndroidResources/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/AndroidResources/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /Project/AndroidResources/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/AndroidResources/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Project/AndroidResources/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/AndroidResources/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /Project/AndroidResources/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/AndroidResources/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Project/AndroidResources/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/AndroidResources/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /Project/AndroidResources/res/values/values.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #15073e 4 | 5 | -------------------------------------------------------------------------------- /Project/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Icon.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-40.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "idiom" : "iphone", 11 | "size" : "20x20", 12 | "scale" : "3x" 13 | }, 14 | { 15 | "size" : "29x29", 16 | "idiom" : "iphone", 17 | "filename" : "Icon-58.png", 18 | "scale" : "2x" 19 | }, 20 | { 21 | "size" : "29x29", 22 | "idiom" : "iphone", 23 | "filename" : "Icon-87.png", 24 | "scale" : "3x" 25 | }, 26 | { 27 | "size" : "40x40", 28 | "idiom" : "iphone", 29 | "filename" : "Icon-80.png", 30 | "scale" : "2x" 31 | }, 32 | { 33 | "idiom" : "iphone", 34 | "size" : "40x40", 35 | "scale" : "3x" 36 | }, 37 | { 38 | "size" : "60x60", 39 | "idiom" : "iphone", 40 | "filename" : "Icon-120.png", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "size" : "60x60", 45 | "idiom" : "iphone", 46 | "filename" : "Icon-180.png", 47 | "scale" : "3x" 48 | }, 49 | { 50 | "idiom" : "ipad", 51 | "size" : "20x20", 52 | "scale" : "1x" 53 | }, 54 | { 55 | "idiom" : "ipad", 56 | "size" : "20x20", 57 | "scale" : "2x" 58 | }, 59 | { 60 | "idiom" : "ipad", 61 | "size" : "29x29", 62 | "scale" : "1x" 63 | }, 64 | { 65 | "idiom" : "ipad", 66 | "size" : "29x29", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "idiom" : "ipad", 71 | "size" : "40x40", 72 | "scale" : "1x" 73 | }, 74 | { 75 | "idiom" : "ipad", 76 | "size" : "40x40", 77 | "scale" : "2x" 78 | }, 79 | { 80 | "size" : "76x76", 81 | "idiom" : "ipad", 82 | "filename" : "Icon-76.png", 83 | "scale" : "1x" 84 | }, 85 | { 86 | "size" : "76x76", 87 | "idiom" : "ipad", 88 | "filename" : "Icon-152.png", 89 | "scale" : "2x" 90 | }, 91 | { 92 | "size" : "83.5x83.5", 93 | "idiom" : "ipad", 94 | "filename" : "Icon-167.png", 95 | "scale" : "2x" 96 | }, 97 | { 98 | "size" : "1024x1024", 99 | "idiom" : "ios-marketing", 100 | "filename" : "Icon-1024.png", 101 | "scale" : "1x" 102 | } 103 | ], 104 | "info" : { 105 | "version" : 1, 106 | "author" : "xcode" 107 | } 108 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIcon.appiconset/Icon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIcon.appiconset/Icon-1024.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIcon.appiconset/Icon-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIcon.appiconset/Icon-120.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIcon.appiconset/Icon-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIcon.appiconset/Icon-152.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIcon.appiconset/Icon-167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIcon.appiconset/Icon-167.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIcon.appiconset/Icon-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIcon.appiconset/Icon-180.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIcon.appiconset/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIcon.appiconset/Icon-40.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIcon.appiconset/Icon-58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIcon.appiconset/Icon-58.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIcon.appiconset/Icon-80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIcon.appiconset/Icon-80.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIcon.appiconset/Icon-87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIcon.appiconset/Icon-87.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "filename" : "Icon-tvOS-Large-Background.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "tv", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Icon-tvOS-Large-Background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIconTV.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Icon-tvOS-Large-Background.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Large.imagestack/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "layers" : [ 3 | { 4 | "filename" : "Front.imagestacklayer" 5 | }, 6 | { 7 | "filename" : "Middle.imagestacklayer" 8 | }, 9 | { 10 | "filename" : "Back.imagestacklayer" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "filename" : "Icon-tvOS-Large-LogoA.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "tv", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Icon-tvOS-Large-LogoA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIconTV.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Icon-tvOS-Large-LogoA.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "filename" : "Icon-tvOS-Large-LogoB.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "tv", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Icon-tvOS-Large-LogoB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIconTV.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Icon-tvOS-Large-LogoB.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "filename" : "Icon-tvOS-Small-Bg.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "tv", 10 | "filename" : "Icon-tvOS-Small-Bg@2x.png", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Icon-tvOS-Small-Bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Icon-tvOS-Small-Bg.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Icon-tvOS-Small-Bg@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Icon-tvOS-Small-Bg@2x.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "layers" : [ 3 | { 4 | "filename" : "Front.imagestacklayer" 5 | }, 6 | { 7 | "filename" : "Middle.imagestacklayer" 8 | }, 9 | { 10 | "filename" : "Back.imagestacklayer" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "filename" : "Icon-tvOS-Small-LogoA.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "tv", 10 | "filename" : "Icon-tvOS-Small-LogoA@2x.png", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Icon-tvOS-Small-LogoA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Icon-tvOS-Small-LogoA.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Icon-tvOS-Small-LogoA@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Icon-tvOS-Small-LogoA@2x.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "filename" : "Icon-tvOS-Small-LogoB.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "tv", 10 | "filename" : "Icon-tvOS-Small-LogoB@2x.png", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Icon-tvOS-Small-LogoB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Icon-tvOS-Small-LogoB.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Icon-tvOS-Small-LogoB@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Icon-tvOS-Small-LogoB@2x.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "assets" : [ 3 | { 4 | "size" : "1280x768", 5 | "idiom" : "tv", 6 | "filename" : "App Icon - Large.imagestack", 7 | "role" : "primary-app-icon" 8 | }, 9 | { 10 | "size" : "400x240", 11 | "idiom" : "tv", 12 | "filename" : "App Icon - Small.imagestack", 13 | "role" : "primary-app-icon" 14 | }, 15 | { 16 | "size" : "2320x720", 17 | "idiom" : "tv", 18 | "filename" : "Top Shelf Image Wide.imageset", 19 | "role" : "top-shelf-image-wide" 20 | }, 21 | { 22 | "size" : "1920x720", 23 | "idiom" : "tv", 24 | "filename" : "Top Shelf Image.imageset", 25 | "role" : "top-shelf-image" 26 | } 27 | ], 28 | "info" : { 29 | "version" : 1, 30 | "author" : "xcode" 31 | } 32 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/Top Shelf Image Wide.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "filename" : "Icon-tvOS-TopShelfWide.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "tv", 10 | "filename" : "Icon-tvOS-TopShelfWide@2x.png", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/Top Shelf Image Wide.imageset/Icon-tvOS-TopShelfWide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIconTV.brandassets/Top Shelf Image Wide.imageset/Icon-tvOS-TopShelfWide.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/Top Shelf Image Wide.imageset/Icon-tvOS-TopShelfWide@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIconTV.brandassets/Top Shelf Image Wide.imageset/Icon-tvOS-TopShelfWide@2x.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/Top Shelf Image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "filename" : "Icon-tvOS-TopShelf.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "tv", 10 | "filename" : "Icon-tvOS-TopShelf@2x.png", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/Top Shelf Image.imageset/Icon-tvOS-TopShelf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIconTV.brandassets/Top Shelf Image.imageset/Icon-tvOS-TopShelf.png -------------------------------------------------------------------------------- /Project/Images.xcassets/AppIconTV.brandassets/Top Shelf Image.imageset/Icon-tvOS-TopShelf@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/AppIconTV.brandassets/Top Shelf Image.imageset/Icon-tvOS-TopShelf@2x.png -------------------------------------------------------------------------------- /Project/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/LaunchImageTV.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "landscape", 5 | "idiom" : "tv", 6 | "filename" : "Icon-tvOS-Launch@2x.png", 7 | "extent" : "full-screen", 8 | "minimum-system-version" : "11.0", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "orientation" : "landscape", 13 | "idiom" : "tv", 14 | "filename" : "Icon-tvOS-Launch.png", 15 | "extent" : "full-screen", 16 | "minimum-system-version" : "9.0", 17 | "scale" : "1x" 18 | } 19 | ], 20 | "info" : { 21 | "version" : 1, 22 | "author" : "xcode" 23 | } 24 | } -------------------------------------------------------------------------------- /Project/Images.xcassets/LaunchImageTV.launchimage/Icon-tvOS-Launch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/LaunchImageTV.launchimage/Icon-tvOS-Launch.png -------------------------------------------------------------------------------- /Project/Images.xcassets/LaunchImageTV.launchimage/Icon-tvOS-Launch@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/Images.xcassets/LaunchImageTV.launchimage/Icon-tvOS-Launch@2x.png -------------------------------------------------------------------------------- /Project/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib -------------------------------------------------------------------------------- /Project/LaunchScreen.storyboardc/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/LaunchScreen.storyboardc/Info.plist -------------------------------------------------------------------------------- /Project/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib -------------------------------------------------------------------------------- /Project/LaunchScreen.storyboardc/designable.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /Project/ReadMe.txt: -------------------------------------------------------------------------------- 1 | This sample project demonstrates polygonal body constructors and tilt-based gravity effects for Android, iOS, and tvOS. 2 | 3 | Turn the device around (orientation) to see how the objects tumble around as if contained in a tumbler. 4 | 5 | RELATED GUIDES 6 | [Basic Interactivity and Event Detection](https://docs.coronalabs.com/guide/events/detectEvents/index.html) 7 | [Physics Bodies](https://docs.coronalabs.com/guide/physics/physicsBodies/index.html) 8 | -------------------------------------------------------------------------------- /Project/build.settings: -------------------------------------------------------------------------------- 1 | -- 2 | -- For more information on build.settings, see the Project Build Settings guide at: 3 | -- https://docs.coronalabs.com/guide/distribution/buildSettings 4 | -- 5 | 6 | settings = 7 | { 8 | orientation = 9 | { 10 | -- Supported values for orientation: 11 | -- portrait, portraitUpsideDown, landscapeLeft, landscapeRight 12 | default = "landscapeRight", 13 | supported = { "landscapeRight" } 14 | }, 15 | 16 | iphone = 17 | { 18 | xcassets = "Images.xcassets", 19 | plist = 20 | { 21 | UILaunchStoryboardName = "LaunchScreen", 22 | ITSAppUsesNonExemptEncryption = false, -- This sample doesn't use custom encryption 23 | }, 24 | }, 25 | 26 | tvos = 27 | { 28 | xcassets = "Images.xcassets", 29 | plist = 30 | { 31 | ITSAppUsesNonExemptEncryption = false, -- This sample doesn't use custom encryption 32 | }, 33 | }, 34 | 35 | window = 36 | { 37 | titleText = 38 | { 39 | default = "Shape Tumbler", 40 | }, 41 | }, 42 | } 43 | -------------------------------------------------------------------------------- /Project/config.lua: -------------------------------------------------------------------------------- 1 | 2 | application = 3 | { 4 | content = 5 | { 6 | fps = 60, 7 | width = 320, 8 | height = 480, 9 | scale = "letterbox", 10 | xAlign = "center", 11 | yAlign = "center", 12 | 13 | imageSuffix = 14 | { 15 | ["@2x"] = 2.000, 16 | ["@4x"] = 4.000 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Project/main.lua: -------------------------------------------------------------------------------- 1 | 2 | -- Abstract: Shape Tumbler 3 | -- Version: 1.1 4 | -- Sample code is MIT licensed; see https://solar2d.com/LICENSE.txt 5 | --------------------------------------------------------------------------------------- 6 | 7 | display.setStatusBar( display.HiddenStatusBar ) 8 | math.randomseed( os.time() ) 9 | 10 | ------------------------------ 11 | -- RENDER THE SAMPLE CODE UI 12 | ------------------------------ 13 | local sampleUI = require( "sampleUI.sampleUI" ) 14 | sampleUI:newUI( { theme="darkgrey", title="Shape Tumbler", showBuildNum=false } ) 15 | 16 | ------------------------------ 17 | -- CONFIGURE STAGE 18 | ------------------------------ 19 | display.getCurrentStage():insert( sampleUI.backGroup ) 20 | local worldGroup = display.newGroup() 21 | display.getCurrentStage():insert( sampleUI.frontGroup ) 22 | 23 | ---------------------- 24 | -- BEGIN SAMPLE CODE 25 | ---------------------- 26 | 27 | -- Set up physics engine 28 | local physics = require( "physics" ) 29 | physics.start( true ) -- Pass "true" as first parameter to prevent bodies from sleeping 30 | physics.setGravity( 0, 9.8 ) -- Initial gravity points downwards 31 | physics.setScale( 60 ) 32 | 33 | -- Declare initial variables 34 | local letterboxWidth = math.abs(display.screenOriginX) 35 | local letterboxHeight = math.abs(display.screenOriginY) 36 | 37 | -- Create "walls" around screen 38 | local wallL = display.newRect( worldGroup, 0-letterboxWidth, display.contentCenterY, 20, display.actualContentHeight ) 39 | wallL.anchorX = 1 40 | physics.addBody( wallL, "static", { bounce=1, friction=0.1 } ) 41 | 42 | local wallR = display.newRect( worldGroup, 480+letterboxWidth, display.contentCenterY, 20, display.actualContentHeight ) 43 | wallR.anchorX = 0 44 | physics.addBody( wallR, "static", { bounce=1, friction=0.1 } ) 45 | 46 | local wallT = display.newRect( worldGroup, display.contentCenterX, 0-letterboxHeight, display.actualContentWidth, 20 ) 47 | wallT.anchorY = 1 48 | physics.addBody( wallT, "static", { bounce=0, friction=0 } ) 49 | 50 | local wallB = display.newRect( worldGroup, display.contentCenterX, 320+letterboxHeight, display.actualContentWidth, 20 ) 51 | wallB.anchorY = 0 52 | physics.addBody( wallB, "static", { bounce=0.4, friction=0.6 } ) 53 | 54 | -- Create triangle function 55 | local function createTriangle() 56 | local triangleShape = { 0,-32, 37,32, -37,32 } 57 | local triangle = display.newPolygon( worldGroup, 0, 0, triangleShape ) 58 | physics.addBody( triangle, { friction=0.5, bounce=0.3, shape=triangleShape } ) 59 | return triangle 60 | end 61 | 62 | -- Create hexagon function 63 | local function createHexagon() 64 | local hexagonShape = { 0,-38, 33,-19, 33,19, 0,38, -33,19, -33,-19 } 65 | local hexagon = display.newPolygon( worldGroup, 0, 0, hexagonShape ) 66 | physics.addBody( hexagon, { friction=0.5, bounce=0.4, shape=hexagonShape } ) 67 | return hexagon 68 | end 69 | 70 | -- Create small box function 71 | local function createBoxSmall() 72 | local boxSmall = display.newRect( worldGroup, 0, 0, 50, 50 ) 73 | physics.addBody( boxSmall, { friction=0.5, bounce=0.4 } ) 74 | return boxSmall 75 | end 76 | 77 | -- Create large box function 78 | local function createBoxLarge() 79 | local boxLarge = display.newRect( worldGroup, 0, 0, 75, 75 ) 80 | physics.addBody( boxLarge, { friction=0.5, bounce=0.4 } ) 81 | return boxLarge 82 | end 83 | 84 | -- Create cell function 85 | local function createCell() 86 | local cellShape = { -30,-10, -25,-15, 25,-15, 30,-10, 30,10, 25,15, -25,15, -30,10 } 87 | local cell = display.newPolygon( worldGroup, 0, 0, cellShape ) 88 | physics.addBody( cell, { friction=0.5, bounce=0.4, shape=cellShape } ) 89 | return cell 90 | end 91 | 92 | -- Create ball function 93 | local function createBall() 94 | local ball = display.newCircle( worldGroup, 0, 0, 30 ) 95 | physics.addBody( ball, { friction=0.5, bounce=0.7, radius=30 } ) 96 | return ball 97 | end 98 | 99 | -- Create random object function 100 | local function createRandomObject() 101 | local r = math.random( 1, 6 ) 102 | local object 103 | 104 | if ( r == 1 ) then 105 | object = createTriangle() 106 | elseif ( r == 2 ) then 107 | object = createHexagon() 108 | elseif ( r == 3 ) then 109 | object = createBoxSmall() 110 | elseif ( r == 4 ) then 111 | object = createBoxLarge() 112 | elseif ( r == 5 ) then 113 | object = createCell() 114 | elseif ( r == 6 ) then 115 | object = createBall() 116 | end 117 | 118 | return object 119 | end 120 | 121 | -- Fill the content area with some objects 122 | local function spawnObjects() 123 | local xIndex = 0 124 | local yPos = 100 125 | 126 | for i = 1, 8 do 127 | local object = createRandomObject() 128 | object:setFillColor( ( math.random( 4, 8 ) / 10 ), ( math.random( 0, 2 ) / 10 ), ( math.random( 4, 10 ) / 10 ) ) 129 | 130 | if ( xIndex == 4 ) then 131 | xIndex = 0 132 | yPos = 220 133 | end 134 | 135 | object.y = yPos + ( math.random( -1, 1 ) * 15 ) 136 | object.x = ( xIndex * 120 ) + 60 + ( math.random( -1, 1 ) * 15 ) 137 | xIndex = xIndex + 1 138 | end 139 | end 140 | 141 | -- Function to adjust gravity based on accelerometer response 142 | local function onTilt( event ) 143 | -- Gravity is in portrait orientation on Android, iOS, and Windows Phone 144 | -- On tvOS, gravity is in the orientation of the device attached to the event 145 | if ( event.device ) then 146 | physics.setGravity( ( 9.8 * event.xGravity ), ( -9.8 * event.yGravity ) ) 147 | else 148 | physics.setGravity( ( -9.8 * event.yGravity ), ( -9.8 * event.xGravity ) ) 149 | end 150 | end 151 | 152 | -- Detect if accelerometer is supported 153 | if ( system.hasEventSource( "accelerometer" ) ) then 154 | -- Set accelerometer to maximum responsiveness 155 | system.setAccelerometerInterval( 100 ) 156 | -- Start listening for accelerometer events 157 | Runtime:addEventListener( "accelerometer", onTilt ) 158 | -- Spawn some objects 159 | spawnObjects() 160 | else 161 | local shade = display.newRect( worldGroup, display.contentCenterX, display.contentHeight-display.screenOriginY-18, display.actualContentWidth, 36 ) 162 | shade:setFillColor( 0, 0, 0, 0.7 ) 163 | local msg = display.newText( worldGroup, "Accelerometer not supported on this platform", display.contentCenterX, shade.y, appFont, 13 ) 164 | msg:setFillColor( 1, 0, 0.2 ) 165 | end 166 | -------------------------------------------------------------------------------- /Project/sampleUI/back-darkgrey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/sampleUI/back-darkgrey.png -------------------------------------------------------------------------------- /Project/sampleUI/back-darkgrey@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/sampleUI/back-darkgrey@2x.png -------------------------------------------------------------------------------- /Project/sampleUI/back-darkgrey@4x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/sampleUI/back-darkgrey@4x.png -------------------------------------------------------------------------------- /Project/sampleUI/infobutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/sampleUI/infobutton.png -------------------------------------------------------------------------------- /Project/sampleUI/infobutton@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/sampleUI/infobutton@2x.png -------------------------------------------------------------------------------- /Project/sampleUI/infobutton@4x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Project/sampleUI/infobutton@4x.png -------------------------------------------------------------------------------- /Project/sampleUI/sampleUI.lua: -------------------------------------------------------------------------------- 1 | 2 | -- Version: 1.3 3 | --------------------------------------------------------------------------------------- 4 | 5 | local widget = require( "widget" ) 6 | 7 | local M = {} 8 | 9 | local infoShowing = false 10 | 11 | function M:newUI( options ) 12 | 13 | local backGroup = display.newGroup() 14 | local frontGroup = display.newGroup() 15 | local textGroupContainer = display.newContainer( 288, 240 ) ; frontGroup:insert( textGroupContainer ) 16 | local barContainer = display.newContainer( display.actualContentWidth, 30 ) 17 | frontGroup:insert( barContainer ) 18 | barContainer.anchorX = 0 19 | barContainer.anchorY = 0 20 | barContainer.anchorChildren = false 21 | barContainer.x = display.screenOriginX 22 | barContainer.y = display.screenOriginY 23 | 24 | local scrollBounds 25 | local infoBoxState = "canOpen" 26 | local transComplete 27 | local themeName = options.theme or "darkgrey" 28 | local sampleCodeTitle = options.title or "Sample" 29 | local buildNum 30 | 31 | -- Read from the ReadMe.txt file 32 | local readMeText = "" 33 | local readMeFilePath = system.pathForFile( "ReadMe.txt", system.ResourceDirectory ) 34 | if readMeFilePath then 35 | local readMeFile = io.open( readMeFilePath ) 36 | local rt = readMeFile:read( "*a" ) 37 | if string.len( rt ) > 0 then readMeText = rt end 38 | io.close( readMeFile ) ; readMeFile = nil ; rt = nil 39 | end 40 | 41 | -- Create background image by theme value 42 | local background = display.newImageRect( backGroup, "sampleUI/back-" .. themeName .. ".png", 360, 640 ) 43 | background.x, background.y = display.contentCenterX, display.contentCenterY 44 | 45 | local topBarBack = display.newRect( barContainer, 0, 0, barContainer.contentWidth, barContainer.contentHeight ) 46 | topBarBack.anchorX = 0 47 | topBarBack.anchorY = 0 48 | topBarBack:setFillColor( 0,0,0,0.2 ) 49 | local topBarOver = display.newRect( barContainer, 0, 0, barContainer.contentWidth, barContainer.contentHeight - 2 ) 50 | topBarOver.anchorX = 0 51 | topBarOver.anchorY = 0 52 | topBarOver:setFillColor( { type="gradient", color1={ 0.144 }, color2={ 0.158 } } ) 53 | textGroupContainer:toBack() 54 | 55 | -- Check system for font selection 56 | local useFont 57 | if ( "android" == system.getInfo( "platform" ) or "win32" == system.getInfo( "platform" ) ) then 58 | useFont = native.systemFont 59 | else 60 | useFont = "HelveticaNeue-Light" 61 | end 62 | self.appFont = useFont 63 | 64 | -- Place Solar2D title 65 | local siteLink = display.newText( barContainer, "Solar2D", 8, topBarOver.contentHeight / 2, useFont, 14 ) 66 | siteLink.anchorX = 0 67 | siteLink:setFillColor( 0.961, 0.494, 0.125 ) 68 | if system.canOpenURL( "https://www.solar2d.com" ) then 69 | siteLink:addEventListener( "touch", 70 | function( event ) 71 | if event.phase == "began" then 72 | system.openURL( "https://www.solar2d.com" ) 73 | end 74 | return true 75 | end ) 76 | end 77 | 78 | -- Place sample app title 79 | local title = display.newText( barContainer, sampleCodeTitle, barContainer.contentWidth - 28, topBarOver.contentHeight / 2, useFont, 14 ) 80 | title.anchorX = 1 81 | 82 | if options.showBuildNum == true then 83 | buildNum = display.newText( frontGroup, "Build " .. tonumber( system.getInfo( "build" ):sub(-4) ), 0, 0, useFont, 10 ) 84 | buildNum.anchorX = 1 85 | buildNum.anchorY = 1 86 | if ( themeName == "darkgrey" or themeName == "mediumgrey" ) then buildNum:setFillColor( 0.8 ) else buildNum:setFillColor( 0.2 ) end 87 | end 88 | 89 | -- Create shade rectangle 90 | local screenShade = display.newRect( frontGroup, 0, 0, display.actualContentWidth, display.actualContentHeight ) 91 | screenShade:setFillColor( 0,0,0 ) ; screenShade.alpha = 0 92 | screenShade.x, screenShade.y = display.contentCenterX, display.contentCenterY 93 | screenShade.isHitTestable = false ; screenShade:toBack() 94 | 95 | -- Create info button (initially invisible) 96 | local infoButton = display.newImageRect( barContainer, "sampleUI/infobutton.png", 25, 25 ) 97 | infoButton.anchorX = 1 98 | infoButton.x = barContainer.contentWidth - 3 99 | infoButton.y = topBarOver.contentHeight / 2 100 | infoButton.isVisible = false 101 | infoButton.id = "infoButton" 102 | 103 | -- Create table for initial object positions 104 | local objPos = { infoBoxOffY=0, infoBoxDestY=0 } 105 | 106 | -- Resize change handler 107 | local function onResize( event ) 108 | 109 | if display.contentHeight >= display.contentWidth then 110 | background.x, background.y, background.rotation = display.contentCenterX, display.contentCenterY, 0 111 | else 112 | background.x, background.y, background.rotation = display.contentCenterX, display.contentCenterY, 90 113 | end 114 | 115 | barContainer.x = display.screenOriginX 116 | barContainer.y = display.screenOriginY 117 | barContainer.width = display.actualContentWidth 118 | topBarBack.width = barContainer.width 119 | topBarOver.width = barContainer.width 120 | title.x = barContainer.contentWidth - 28 121 | infoButton.x = barContainer.contentWidth - 3 122 | screenShade.x = display.contentCenterX 123 | screenShade.y = display.contentCenterY 124 | screenShade.width = display.actualContentWidth 125 | screenShade.height = display.actualContentHeight 126 | textGroupContainer.x = display.contentCenterX 127 | if buildNum then 128 | buildNum.x = display.contentCenterX + (display.actualContentWidth / 2) - 7 129 | buildNum.y = display.contentCenterY + (display.actualContentHeight / 2) - 8 130 | end 131 | 132 | -- If info box is opening or already open, snap it entirely on screen 133 | objPos["infoBoxOffY"] = display.screenOriginY - 130 134 | objPos["infoBoxDestY"] = (barContainer.y + barContainer.contentHeight + 130) 135 | if ( infoBoxState == "opening" or infoBoxState == "canClose" ) then 136 | transition.cancel( "infoBox" ) 137 | textGroupContainer.xScale, textGroupContainer.yScale = 1,1 138 | textGroupContainer.y = objPos["infoBoxDestY"] 139 | if scrollBounds then 140 | scrollBounds.x, scrollBounds.y = display.contentCenterX, objPos["infoBoxDestY"] 141 | end 142 | transComplete() 143 | -- If info box is closing or already closed, snap it entirely off screen 144 | elseif ( infoBoxState == "closing" or infoBoxState == "canOpen" ) then 145 | transition.cancel( "infoBox" ) 146 | textGroupContainer.y = objPos["infoBoxOffY"] 147 | if scrollBounds then 148 | scrollBounds.x, scrollBounds.y = display.contentCenterX, objPos["infoBoxOffY"] 149 | end 150 | transComplete() 151 | end 152 | end 153 | Runtime:addEventListener( "resize", onResize ) 154 | 155 | -- If there is ReadMe.txt content, create needed elements 156 | if readMeText ~= "" then 157 | 158 | -- Create the info box scrollview 159 | scrollBounds = widget.newScrollView 160 | { 161 | x = 160, 162 | y = objPos["infoBoxDestY"], 163 | width = 288, 164 | height = 240, 165 | horizontalScrollDisabled = true, 166 | hideBackground = true, 167 | hideScrollBar = true, 168 | topPadding = 0, 169 | bottomPadding = 0 170 | } 171 | scrollBounds:setIsLocked( true, "vertical" ) 172 | scrollBounds.x, scrollBounds.y = display.contentCenterX, objPos["infoBoxOffY"] 173 | frontGroup:insert( scrollBounds ) 174 | 175 | local infoBoxBack = display.newRect( 0, 0, 288, 240 ) 176 | if themeName == "whiteorange" then infoBoxBack:setFillColor( 0.88 ) 177 | elseif themeName == "lightgrey" then infoBoxBack:setFillColor( 0.98 ) 178 | else infoBoxBack:setFillColor( 0.78 ) end 179 | textGroupContainer:insert( infoBoxBack ) 180 | 181 | -- Create the info text group 182 | local infoTextGroup = display.newGroup() 183 | textGroupContainer:insert( infoTextGroup ) 184 | 185 | -- Find and then sub out documentation links 186 | local docLinks = {} 187 | for linkTitle, linkURL in string.gmatch( readMeText, "%[([%w\%s\%p\%—]-)%]%(([%w\%p]-)%)" ) do 188 | docLinks[#docLinks+1] = { linkTitle, linkURL } 189 | end 190 | readMeText = string.gsub( readMeText, "%[([%w\%s\%p\%—]-)%]%(([%w\%p]-)%)", "" ) 191 | 192 | -- Create the info text and anchoring box 193 | local infoText = display.newText( infoTextGroup, "", 0, 0, 260, 0, useFont, 12 ) 194 | infoText:setFillColor( 0 ) 195 | local function trimString( s ) 196 | return string.match( s, "^()%s*$" ) and "" or string.match( s, "^%s*(.*%S)" ) 197 | end 198 | readMeText = trimString( readMeText ) 199 | infoText.text = "\n" .. readMeText 200 | infoText.anchorX = 0 201 | infoText.anchorY = 0 202 | infoText.x = -130 203 | 204 | -- Add documentation links as additional clickable text objects below main text 205 | if #docLinks > 0 then 206 | for i = 1,#docLinks do 207 | local docLink = display.newText( docLinks[i][1], 0, 0, useFont, 12 ) 208 | docLink:setFillColor( 0.9, 0.1, 0.2 ) 209 | docLink.anchorX = 0 210 | docLink.anchorY = 0 211 | docLink.x = -130 212 | docLink.y = infoTextGroup.contentBounds.yMax + 5 213 | infoTextGroup:insert( docLink ) 214 | if system.canOpenURL( docLinks[i][2] ) then 215 | docLink:addEventListener( "tap", 216 | function( event ) 217 | system.openURL( docLinks[i][2] ) 218 | return true 219 | end ) 220 | end 221 | end 222 | end 223 | local spacer = display.newRect( infoTextGroup, 0, infoTextGroup.contentBounds.yMax, 10, 15 ) 224 | spacer.anchorY = 0 ; spacer.isVisible = false 225 | 226 | local infoTextAnchorBox = display.newRect( infoTextGroup, 0, 0, 288, math.max( 240, infoTextGroup.height ) ) 227 | infoTextAnchorBox.anchorY = 0 228 | infoTextAnchorBox.isVisible = false 229 | 230 | -- Set anchor point on info text group 231 | local anc = infoTextGroup.height/120 232 | infoTextGroup.anchorChildren = true 233 | infoTextGroup.anchorY = 1/anc 234 | 235 | -- Initially set info objects to invisible 236 | infoTextGroup.isVisible = false 237 | textGroupContainer.isVisible = false 238 | 239 | transComplete = function() 240 | 241 | if infoBoxState == "opening" then 242 | scrollBounds:insert( infoTextGroup ) 243 | infoTextGroup.x = 144 ; infoTextGroup.y = 120 244 | scrollBounds:setIsLocked( false, "vertical" ) 245 | scrollBounds.x, scrollBounds.y = display.contentCenterX, objPos["infoBoxDestY"] 246 | infoBoxState = "canClose" 247 | infoShowing = true 248 | if self.onInfoEvent then 249 | self.onInfoEvent( { action="show", phase="did" } ) 250 | end 251 | elseif infoBoxState == "closing" then 252 | infoTextGroup.isVisible = false 253 | textGroupContainer.isVisible = false 254 | scrollBounds.x, scrollBounds.y = display.contentCenterX, objPos["infoBoxOffY"] 255 | screenShade.isHitTestable = false 256 | infoBoxState = "canOpen" 257 | infoShowing = false 258 | if self.onInfoEvent then 259 | self.onInfoEvent( { action="hide", phase="did" } ) 260 | end 261 | end 262 | end 263 | 264 | local function controlInfoBox( event ) 265 | if event.phase == "began" then 266 | if infoBoxState == "canOpen" then 267 | infoBoxState = "opening" 268 | infoShowing = true 269 | if self.onInfoEvent then 270 | self.onInfoEvent( { action="show", phase="will" } ) 271 | end 272 | textGroupContainer.x = display.contentCenterX 273 | textGroupContainer.y = objPos["infoBoxOffY"] 274 | textGroupContainer:insert( infoTextGroup ) 275 | infoTextGroup.isVisible = true 276 | textGroupContainer.isVisible = true 277 | textGroupContainer.xScale = 0.96 ; textGroupContainer.yScale = 0.96 278 | screenShade.isHitTestable = true 279 | transition.cancel( "infoBox" ) 280 | transition.to( screenShade, { time=400, tag="infoBox", alpha=0.75, transition=easing.outQuad } ) 281 | transition.to( textGroupContainer, { time=900, tag="infoBox", y=objPos["infoBoxDestY"], transition=easing.outCubic } ) 282 | transition.to( textGroupContainer, { time=400, tag="infoBox", delay=750, xScale=1, yScale=1, transition=easing.outQuad, onComplete=transComplete } ) 283 | 284 | elseif infoBoxState == "canClose" then 285 | infoBoxState = "closing" 286 | infoShowing = false 287 | if self.onInfoEvent then 288 | self.onInfoEvent( { action="hide", phase="will" } ) 289 | end 290 | textGroupContainer:insert( infoTextGroup ) 291 | local scrollX, scrollY = scrollBounds:getContentPosition() 292 | infoTextGroup.x = 0 ; infoTextGroup.y = scrollY 293 | scrollBounds:setIsLocked( true, "vertical" ) 294 | transition.cancel( "infoBox" ) 295 | transition.to( screenShade, { time=400, tag="infoBox", alpha=0, transition=easing.outQuad } ) 296 | transition.to( textGroupContainer, { time=400, tag="infoBox", xScale=0.96, yScale=0.96, transition=easing.outQuad } ) 297 | transition.to( textGroupContainer, { time=700, tag="infoBox", delay=200, y=objPos["infoBoxOffY"], transition=easing.inCubic, onComplete=transComplete } ) 298 | end 299 | end 300 | return true 301 | end 302 | 303 | -- Set info button tap listener 304 | infoButton.isVisible = true 305 | infoButton:addEventListener( "touch", controlInfoBox ) 306 | infoButton.listener = controlInfoBox 307 | screenShade:addEventListener( "touch", controlInfoBox ) 308 | end 309 | 310 | self.infoButton = infoButton 311 | self.titleBarBottom = barContainer.y + barContainer.contentHeight - 2 312 | backGroup:toBack() ; self.backGroup = backGroup 313 | frontGroup:toFront() ; self.frontGroup = frontGroup 314 | onResize() 315 | end 316 | 317 | function M:isInfoShowing() 318 | return infoShowing 319 | end 320 | 321 | return M 322 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Solar2D → AppStore; macOS not needed 2 | 3 | All you need is a web browser (sic). 4 | 5 | The whole setup should take about 20 minutes. I tried to write as much detail as possible so do not be daunted by the size of this guide, it's just very detailed to make the process easier. 6 | 7 | # Prerequisites 8 | 9 | - Apple account with active [Apple Development Program](http://developer.apple.com/account/) subscription, enrolled as individual or part of a team 10 | - GitHub account 11 | - Google account 12 | - iOS Device with [TestFlight](https://itunes.apple.com/us/app/testflight/id899247664?mt=8) installed for testing 13 | 14 | # General overview 15 | 16 | Here is a quick summary of what we are about to do: 17 | 18 | - Clone the GitHub repository and set it up 19 | - Generate Apple signing credentials and replace placeholders in the repo 20 | 21 | ### 1. Preparing the repo 22 | 23 | 1. Log in to [GitHub](http://github.com/) and press the ➕ button in the top right corner, then select "Import repository". We import the repository instead of forking it so that there's an option to set your repository to private. GitHub forks of public repositories can only be set to public. [⏯](https://i.imgur.com/btddTj3.gif) 24 | 2. Paste the clone url: `https://github.com/solar2d/demo-app-store-automation.git`, pick a name for your repo, (e.g. "Solar2Demo"), and choose a visibility. This particular project does not contain any unencrypted sensitive information but if you plan to extend it, make it private. You can change the visibility later. 25 | 3. In your repo press "⚙ Settings" in the menu bar and pick "Secrets" in the sidebar. 26 | 4. Press "New Repository Secret" and type the following Name and Value pairs into their corresponding fields, clicking "Add secret" for each. [⏯](https://i.imgur.com/yLcgLO6.gif): 27 | 1. Name: `AppleUser`
28 | Value: Your Apple ID user email. 29 | 2. Name: `ApplePassword`
30 | Value: Your Apple ID password. Most likely you have two-factor authentication set up, in which case don't use your actual password; Head to [https://appleid.apple.com/](https://appleid.apple.com/account/manage) and log in, generate an "app-specific password" to use instead. 31 | 5. If your Apple Account is enrolled in the development program as part of a team then you have to specify an `AppleTeamId` secret. This step is otherwise optional. [⏯](https://i.imgur.com/QEvOSJo.gif) 32 | 1. Click on "Actions" in the menu bar and select "List Apple Teams" from the sidebar. 33 | 2. Click on the "Run Workflow" button and confirm by clicking the green button. 34 | 3. Wait a moment for the workflow to appear on the list. After some time, the symbol next to it should become a check mark ✓. Click on "List Apple Teams" near the check mark. 35 | 4. Click "list" in the sidebar and then "List Teams" from the main page area. This should expand an ASCII table. 36 | 5. Locate the desired team short name from the ProviderShortname column and save it as `AppleTeamId` in "Settings" → "Secrets". 37 | 6. This action log can contain some sensitive information, such as your name, accessible by anyone who has access to the repo, so I recommend deleting it. To do that, head back to the Actions tab and in the main page area click on the ⋯ button next to "List Apple Teams". Run and select "Delete workflow run". [⏯](https://i.imgur.com/KSyEKI7.gif) 38 | 6. You may want to edit your app name. For that: 39 | 1. Click on "Code" in the menu bar, and navigate to the "Util" directory. 40 | 2. Click on the "recipe.lua" file and then the ✎ pencil button to edit it. 41 | 3. Change the name in quotes, (currently "Solar2Demo"), in the editor and click the "Commit changes" button to save the file. 42 | 4. I would strongly advise against using anything but basic English letters, or changing anything else in this file, unless you are very certain of what you are doing. 43 | 44 | ### 2. Creating an App ID 45 | 46 | 1. Log in to the Apple Developer Web Portal: [http://developer.apple.com/account/](http://developer.apple.com/account/) 47 | 2. Select "Certificates, Identifiers & Profiles". 48 | 3. In the sidebar, select "Identifiers" and click ➕ to create one. 49 | 4. You want to create an "App ID" of the type "App". 50 | 5. Fill out the form for this app: 51 | 1. Description: Something you will recognize your app by, e.g. `Solar2D Demo App`. 52 | 2. App prefix: I usually select one which says "Team ID", but it doesn't matter much. 53 | 3. Explicit bundle id: e.g. `com.solar2d.solar2demo`. You would have to change the company name to something else since this must be unique. 54 | 4. Default capabilities usually work just fine. You can edit them later. 55 | 56 | ### 3. Creating a signing certificate 57 | 58 | Apple requires applications to be cryptographically signed. To do that you need two things: certificate and provisioning profile. Certificate identify your team and created created per account (same certificate is shared for all your projects). Xcode automates this process, but we will instead use command line utilities provided for free by Google Cloud Shell. [⏯](https://i.imgur.com/6BoMPFi.mp4) 59 | 60 | 1. Follow this: [link](https://shell.cloud.google.com/?hl=en_US&fromcloudshell=true&show=terminal). It should open a new terminal session for you. 61 | 2. Run: `rm -f key.key distribution*; openssl req -newkey rsa:2048 -keyout key.key -out request.csr -nodes -subj "/C=CA/ST=/L=/O=/CN=Solar2D"; cloudshell dl request.csr` 62 | 3. This should prompt downloading a "request.csr" file. Accept it and do not close the terminal, you'll need it again in a minute. 63 | 4. In the [Apple Developer](https://developer.apple.com/account/resources/certificates/list) portal, go to "Certificates" → "IDs & Profiles" → "Certificates". 64 | 5. Hit the ➕ button to start the process of creating a certificate. 65 | 6. Select "Apple Distribution". 66 | 7. Hit "Choose File" and select the "request.csr" file we just downloaded. 67 | 8. Hit "Create" and then "Download" to get the "distribution.cer" certificate file. 68 | 9. Return to the Cloud Shell window and upload the certificate. You can do this by dragging and dropping the "distribution.cer" file to the console or by selecting it via "Upload Files" in the ⋮ (More) menu. 69 | 10. Run: `openssl x509 -legacy -inform DER -in distribution.cer -out distribution.crt && openssl pkcs12 -legacy -export -out distribution.p12 -inkey key.key -in distribution.crt && cloudshell dl distribution.p12 && rm -f key.key request.csr distribution.c*` 70 | 11. When prompted for a password I suggest using a strong [randomly generated password](https://passwordsgenerator.net/?length=22&symbols=0&numbers=1&lowercase=1&uppercase=1&similar=0&ambiguous=0&client=1&autoselect=1). 71 | 12. Save the password in your GitHub repo as `CertPassword` secret, (we added other secrets in the [previous](#secret-create) section). You will also need this password if you decide to use an actual Mac and import the certificate there. 72 | 13. Accept the p12 bundle, containing encrypted signing certificates. 73 | 14. In your GitHub repo, navigate to "Code", then click on the "Util" directory. 74 | 15. Press the "Add file" button and select "Upload files". 75 | 16. Select the downloaded "distribution.p12" file and click the "Commit changes" button. 76 | 77 | In your next project jump right to step 12 and reuse this password and `distribution.p12` file. 78 | 79 | ### 4. Creating a provisioning profile 80 | 81 | Second part involved in signing is a provisioning profile. It identifies your application and its capabilities, so it has to be created for each project individually. 82 | 83 | 1. Head to [Developer Portal](https://developer.apple.com/account/resources/profiles/list), select "Profiles" and click ➕ to create one. 84 | 2. Select "App Store" from the Distribution section. 85 | 3. Select the app ID we created earlier, ("com.solar2d.solar2demo" in my case). 86 | 4. On the next page select the certificate we just created. If you have multiple then pick one with an expiry date exactly one year forward. 87 | 5. On the next page type in the name "distribution" and hit "Generate". 88 | 6. Download the generated profile. If your file is named differently, make sure you rename it to `distribution.mobileprovision` as the build script expects the file to be named as such. 89 | 7. Upload the file to replace a placeholder in the "Util" directory of your GitHub repository, as per the end of the previous section. 90 | 91 | ### 5. Creating an App listing 92 | 93 | We have to create an App listing in order to upload and test the app. 94 | 95 | 1. Head to the App Store Connect website: [https://appstoreconnect.apple.com/](https://appstoreconnect.apple.com/) 96 | 2. Log in, read, and accept any user agreements. 97 | 3. Select "My Apps". 98 | 4. In the menu near "Apps" click the ➕ button and select "New App". 99 | 5. In the popup: 100 | 1. Select iOS as the platform. 101 | 2. Name your app, e.g. "Solar2Demo". 102 | 3. Choose a language, e.g. "English (U.S.)". 103 | 4. Set the Bundle ID we created previously. For me it is "Solar2D Demo App - com.solar2d.solar2demo". 104 | 5. Set an SKU to identify the app for yourself, e.g. "Solar2Demo". 105 | 6. Select "Full Access" and click "Create". 106 | 6. After a few moments you will have the App listing page. 107 | 7. You will need this browser window later to set up testers, so keep it around. 108 | 109 | ## Quick check-up 110 | 111 | When all is done you should have the following: 112 | 113 | - 4 Secrets in GitHub repository settings [⏯](https://i.imgur.com/zB92Fjr.png): 114 | - [x] `AppleUser` 115 | - [x] `ApplePassword` 116 | - [x] `AppleTeamId` *(Optional)* 117 | - [x] `CertPassword` 118 | - 2 files replaced in `Util` directory [⏯](https://i.imgur.com/6b9xcZS.png): 119 | - [x] `Util/distribution.p12` 120 | - [x] `Util/distribution.mobileprovision` 121 | 122 | # Building and uploading the App 123 | 124 | Now for the fun part; Building and uploading the app: 125 | 126 | 1. Navigate to your GitHub repo and select "Actions" from the menu bar. 127 | 2. Select "Build and Deliver" in the workflows sidebar. 128 | 3. Select "Run Workflow", leave all parameters as default and confirm by pressing the green button. 129 | 130 | Done! 131 | 132 | This will start a build. It should succeed in about 3-10 minutes, but it will also upload the built app to the App Store Connect, where it will undergo automatic processing. This may take some time. 133 | 134 | ## Testing your app 135 | 136 | Right after the GitHub action submitted a build, you can set up testing. To do that: 137 | 138 | 1. Head back to the [App Store Connect](https://appstoreconnect.apple.com/) portal, and navigate to your app in "My Apps". 139 | 2. In the top menu select "TestFlight" and then select "App Store Connect Users" in the sidebar under the "Internal Group" section. 140 | 3. Hit ➕ near "Testers" and add at least yourself. This will send you an email. 141 | 4. You have to open this email on your iOS device and click the button in it. The TestFlight app should open and prompt you to accept app testing. 142 | 143 | When the build process is complete, you will get an email and/or push notification with a status update. Use TestFlight on the device to install your app and test it. 144 | 145 | ### Consecutive builds 146 | 147 | With repository and TestFlight already set up, all you have to do is push your code, navigate to "Build and Deliver" in your repo Actions, and run the workflow. 148 | 149 | Then wait for a notification and use TestFlight to get the update. 150 | 151 | # What's next 152 | 153 | Replace the project in the "Project" directory with your creation. Clone the repository to your computer, replace or modify contents, commit changes, and make new builds. When the update is ready, update your app with TestFlight. 154 | 155 | Another option is to modify scripts and integrate them into your existing projects hosted on GitHub. Check out [`.github/workflows/build.yml`](.github/workflows/build.yml) and [`Util/build.sh`](Util/build.sh) for that. 156 | 157 | ## Show some love ❤️ (free) 158 | 159 | If you enjoyed this template and guide, make sure you "Star" these projects on GitHub: 160 | 161 | - Solar2D Game Engine: [https://github.com/coronalabs/corona](https://github.com/coronalabs/corona) 162 | - This template: [https://github.com/solar2d/demo-app-store-automation](https://github.com/solar2d/demo-app-store-automation) 163 | 164 | ## Support the project 165 | 166 | Solar2D is a fully open source game engine which relies on user donations to exist. Consider [supporting](http://github.com/coronalabs/corona?sponsor=1) the project on [Patreon](https://patreon.com/shchvova). 167 | 168 | ### Side notes 169 | 170 | GitHub Actions has [usage limits](https://docs.github.com/en/free-pro-team@latest/github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-actions), especially for private repositories, so make sure you check them out. Today free users get 200 macOS minutes and incur costs of ¢8/minute over that limit. This is more than enough for pushing a build once or twice a week. You don't have to set up billing details until you run out of free minutes, and even then it is hard to beat their pricing. 171 | 172 | ## Questions/Issues 173 | 174 | If you have any questions report them to [https://github.com/solar2d/demo-app-store-automation/issues](https://github.com/solar2d/demo-app-store-automation/issues). 175 | 176 | Enjoy and create some awesome Solar2D games! 177 | 178 | ![Solar2D Logo](https://solar2d.com/images/icon-180x180.png) 179 | -------------------------------------------------------------------------------- /README.ru.md: -------------------------------------------------------------------------------- 1 | # Solar2D → App Store; macOS не требуется 2 | 3 | Собственно все, что вам нужно, - это браузер. 4 | 5 | Вся настройка займет около 20 минут. Я постарался написать детальные инструкции с пояснениями, поэтому не пугайтесь большого размера руководства. Оно очень подробное, что должно упрощать, а не пугать и усложнять. 6 | 7 | # Требования 8 | 9 | - Активная учетная запись в [Apple Development Program](http://developer.apple.com/account/) для создания и загрузки приложений. Вы можете быть зарегистрироваться как частное лицо или как часть команды с активной подпиской 10 | - Аккаунт GitHub 11 | - Устройство iOS с приложением [TestFlight](https://itunes.apple.com/us/app/testflight/id899247664?mt=8), если вы хотите тестировать свое приложение 12 | - Аккаунт Google 13 | 14 | # Настройка 15 | 16 | Вот краткое изложение того, что мы собираемся сделать, без инструкций, просто для обзора: 17 | 18 | - Клонировать и настроить репозиторий в GitHub 19 | - Создать сертификаты для подписи iOS приложений и загрузить их в репозиторий вместо шаблонов 20 | 21 | ### 1. Подготовка репозитория 22 | 23 | 1. Войдите в [GitHub](http://github.com/) и нажмите кнопку ➕ в правом верхнем углу, выберите «Import repository». Мы импортируем репозиторий вместо форка, потому что так у вас будет возможность сделать вашу копию закрытой. На GitHub форки публичных репозиториев могут быть только публичными [⏯](https://i.imgur.com/btddTj3.gif) 24 | 2. Вставьте адрес `https://github.com/solar2d/demo-app-store-automation.git`, выберите имя для вашего репозитория (например, Solar2Demo) и видимость. Этот конкретный проект не содержит конфиденциальной информации, или конфиденциальная информация зашифрована. Но если вы хотите расширить его и сделать свой проект на его основе, возможно, есть смысл сделать его приватным. Вы можете изменить настройки приватности позже 25 | 3. В репозитории в строке меню нажмите «⚙ Settings» и на боковой панели выберите «Secrets» 26 | 4. Нажмите «New Repository Secret». Введите следующие пары Name и Value в соответствующие поля и нажмите «Add secret» для каждой пары [⏯](https://i.imgur.com/yLcgLO6.gif): 27 | 1. Name: `AppleUser`
28 | Value: ваш адрес электронной почты пользователя Apple ID 29 | 2. Name: `ApplePassword`
30 | Value: ваш пароль Apple ID. Скорее всего, у вас настроена двухфакторная аутентификация. В этом случае не используйте свой настоящий пароль. Перейдите на [https://appleid.apple.com/](https://appleid.apple.com/account/manage) и войдите в систему. Создайте пароль для приложения «app-specific password» и используйте его 31 | 5. Если ваша учетная запись Apple включена в программу разработки как часть команды, а не как индивидуальный разработчик, вам также необходимо указать секрет `AppleTeamId`. Вы также можете указывать его как индивидуальный разработчик, но это необязательно. Чтобы получить его [⏯](https://i.imgur.com/QEvOSJo.gif): 32 | 1. Нажмите «Actions» в строке заголовка GitHub репозитория и выберите «List Apple Teams» на боковой панели 33 | 2. Нажмите кнопку «Run Workflow» и подтвердите, нажав зеленую кнопку 34 | 3. Подождите. Процесс должен появиться в списке посреди окна. Через некоторое время символ рядом с ним должен стать галочкой ✓. Нажмите «List Apple Teams» рядом с галочкой 35 | 4. Щелкните в боковой панели выберите «list», потом в основной области щелкните на «List Teams». Через некоторое время должна появится текстовая таблица 36 | 5. Найдите желаемое короткое название команды (столбец ProviderShortname) и сохраните его как `AppleTeamId` в «Settings» → «Secrets» 37 | 6. После получения идентификатора группы вы можете удалить лог, щелкнув ⋯ в списке процессов во вкладке «Actions» и выбрав «Delete workflow run». Я рекомендую это сделать, поскольку логи доступны всем, кто имеет доступ к репозиторию. Эти логи могут содержать ваше настоящее имя и другую конфиденциальную информацию [⏯](https://i.imgur.com/KSyEKI7.gif) 38 | 6. При желании вы можете изменить название вашего приложения, для этого: 39 | 1. Нажмите «Code» в строке меню и перейдите в каталог «Util» 40 | 2. Щелкните файл recipe.lua и нажмите кнопку с иконкой карандаша ✎, чтобы отредактировать его 41 | 3. Измените имя в кавычках (Solar2Demo) в редакторе и нажмите кнопку «Commit changes» 42 | 4. Я настоятельно не рекомендую использовать что-либо, кроме простой латиницы, или изменять что-либо еще в этом файле, если вы не очень уверены в том что делаете 43 | 44 | ### 2. Создание идентификатора приложения 45 | 46 | 1. Войдите в веб-портал разработчика Apple: [http://developer.apple.com/account/](http://developer.apple.com/account/) 47 | 2. Выберите «Certificates, Identifiers & Profiles» 48 | 3. На боковой панели выберите «Identifiers» и нажмите ➕, чтобы создать его 49 | 4. Вам нужен «App ID» для типа «App» 50 | 5. Заполните форму 51 | 1. Description, описание, по которому вы узнаете свое приложение, например «Solar2D Demo App» 52 | 2. App prefix, я обычно выбираю тот в котором есть «Team ID», но это не имеет большого значения 53 | 3. Explicit bundle id, например «com.solar2d.solar2demo». Вам придется изменить название компании на другое, поскольку идентификаторы приложений должны быть уникальны 54 | 4. Capabilities, возможности по умолчанию обычно подходят, вы можете отредактировать их позже (в таком случае вам придется перевыпустить профиль подготовки (provisioning profile)) 55 | 56 | ### 3. Создание сертификата подписи 57 | 58 | Apple требует криптографической подписи приложений. Для подписи нужны две вещи: сертификат и профиль подготовки (provisioning profile). Сертификат идентифицирует команду, и создается один на все ваши приложения. Xcode автоматизирует этот процесс, но мы будем использовать утилиты командной строки, предоставляемые Google Cloud Shell бесплатно [⏯](https://i.imgur.com/6BoMPFi.mp4) 59 | 60 | 1. Перейдите по этой [ссылке](https://shell.cloud.google.com/?hl=en_US&fromcloudshell=true&show=terminal). Она должен открыть для вас новый сеанс терминала 61 | 2. Выполните: `rm -f key.key distribution*; openssl req -newkey rsa:2048 -keyout key.key -out request.csr -nodes -subj "/C=CA/ST=/L=/O=/CN=Solar2D"; cloudshell dl request.csr` 62 | 3. Это должно вызвать загрузку файла «request.csr». Скачайте его и не закрывайте терминал, он еще понадобится 63 | 4. На портале [Apple Developer](https://developer.apple.com/account/resources/certificates/list) перейдите в раздел «Certificates, Identifiers & Profiles», Certificates 64 | 5. Нажмите ➕, чтобы начать процесс создания сертификата 65 | 6. Выберите «Apple Distribution» 66 | 7. Нажмите «Choose File» и выберите только что скачанный «request.csr» 67 | 8. Нажмите «Create» и «Download». Должен скачаться файл «distribution.cer» 68 | 9. Вернитесь в окно Cloud Shell и загрузите сертификат. Вы можете сделать это, перетащив файл «distribution.cer» на консоль или выбрав его через «Upload Files» в меню ⋮ (More) 69 | 10. Запустите: `openssl x509 -legacy -inform DER -in distribution.cer -out distribution.crt && openssl pkcs12 -legacy -export -out distribution.p12 -inkey key.key -in distribution.crt && cloudshell dl distribution.p12 && rm -f key.key request.csr distribution.c*` 70 | 11. При запросе пароля я советую использовать надежный случайно сгенерированный пароль, например, [отсюда](https://passwordsgenerator.net/?length=22&symbols=0&numbers=1&lowercase=1&uppercase=1&similar=0&ambiguous=0&client=1&autoselect=1) 71 | 12. Сохраните пароль в репозитории GitHub как секрет `CertPassword` (мы уже добавляли секреты [выше](#secret-create)). Вам также понадобится этот пароль если вы решите использовать сертификат на настоящем маке 72 | 13. Скачайте пакет p12, содержащий зашифрованный сертификат и ключ подписи 73 | 14. В репозитории GitHub перейдите в раздел «Code», затем щелкните каталог «Util» 74 | 15. Нажмите кнопку «Add file» и выберите «Upload files» 75 | 16. Выберите загруженный файл «distribution.p12» и нажмите кнопку «Commit changes» 76 | 77 | В ваших последующих проектах сразу переходите к пункту 12 и переиспользуйте пароль и файл `distribution.p12`. 78 | 79 | ### 4. Создание профиля подготовки (provisioning profile) 80 | 81 | Вторая часть необходимая для подписи приложения это профиль подготовки. Он идентифицирует приложение и его возможности, то есть создается для каждого приложения отдельно. 82 | 83 | 1. Перейдите на [портал разработчика Apple](https://developer.apple.com/account/resources/profiles/list), выберите «Profiles» и нажмите ➕ 84 | 2. Выберите «App Store» в разделе «Distribution» 85 | 3. Выберите идентификатор приложения, который мы создали ранее (у меня com.solar2d.solar2demo) 86 | 4. На следующей странице выберите сертификат, который мы только что создали. Единственный способ который я знаю чтобы их отличать - это по дате истечения годности - должен быть ровно год от даты создания 87 | 5. На следующей странице введите имя «distribution» и нажмите «Generate» 88 | 6. Скачайте сгенерированный профиль. Если ваш файл назван по-другому, обязательно переименуйте его в `distribution.mobileprovision`, так как инструменты сборки ожидают, что файл будет именно так называться 89 | 7. Загрузите файл, заменив шаблон в каталоге Util в вашем репозитории, как в конце предыдущего раздела 90 | 91 | ### 5. Создание приложений в App Store 92 | 93 | Нам нужно создать приложение в App Store чтобы загружать и тестировать его 94 | 95 | 1. Перейдите на сайт App Store Connect: [https://appstoreconnect.apple.com/](https://appstoreconnect.apple.com/) 96 | 2. Войдите в систему, прочтите и примите все пользовательские соглашения 97 | 3. Выберите «My Apps» 98 | 4. В заголовке рядом с «Apps» нажмите кнопку ➕ и выберите «New App» 99 | 5. Во всплывающем окне: 100 | 1. Выберите iOS в качестве платформы 101 | 2. Назовите свое приложение, например, Solar2Demo 102 | 3. Выберите язык, который вам подходит, например, English (U.S.) 103 | 4. Идентификатор приложения, который мы создали ранее (для меня это «Solar2D Demo App - com.solar2d.solar2demo») 104 | 5. Какой-то SKU для идентификации приложения, например Solar2Demo 105 | 6. Выберите «Full Access» и нажмите «Create» 106 | 6. Через несколько секунд откроется страница со списком приложений 107 | 7. Это окно браузера понадобится вам позже для настройки тестировщиков, так что оставьте его открытым 108 | 109 | ## Проверка 110 | 111 | На этот момент, у вас должно быть следующее: 112 | 113 | - 4 секрета в настройках репозитория [⏯](https://i.imgur.com/zB92Fjr.png): 114 | - [x] `AppleUser` 115 | - [x] `ApplePassword` 116 | - [x] `AppleTeamId` *(Необязательно)* 117 | - [x] `CertPassword` 118 | - В каталоге `Util` заменены 2 файла [⏯](https://i.imgur.com/6b9xcZS.png): 119 | - [x] `Util/distribution.p12` 120 | - [x] `Util/distribution.mobileprovision` 121 | 122 | # Сборка и загрузка приложения 123 | 124 | Теперь самое интересное. Сборка и загрузка приложения 125 | 126 | 1. Перейдите в репозиторий GitHub и выберите «Actions» в строке меню 127 | 2. Выберите «Build and Deliver» на боковой панели 128 | 3. Выберите «Run Workflow», оставьте все параметры по умолчанию и подтвердите, нажав зеленую кнопку 129 | 130 | Готово! 131 | 132 | Это запустит сборку. Сама сборка должна завершится примерно за 3-10 минут, она также загрузит созданное в App Store Connect, где оно будет проходить автоматическую обработку. Иногда это может занять довольно много времени 133 | 134 | ## Тестирование 135 | 136 | Сразу после того, как GitHub отправило сборку, вы можете настроить тестирование. Для этого: 137 | 138 | 1. Перейдите на портал [App Store Connect](https://appstoreconnect.apple.com/), выберите «My Apps» и щелкните свое приложение 139 | 2. В верхнем меню выберите «TestFlight», а затем на боковой панели в разделе «Internal Group» выберите «App Store Connect Users» 140 | 3. Нажмите ➕ возле «Testers» и добавьте хотя бы себя 141 | 4. Вам будет отправлено электронное письмо. Откройте это письмо на iOS устройстве и нажмите на кнопку в нем. Должно запуститься приложение TestFlight и предложить вам присоединиться к тестированию приложения 142 | 143 | Когда обработка сборки будет завершена, вы получите электронное письмо. Используйте TestFlight, чтобы установить приложение и тестируйте его на своем устройстве 144 | 145 | ### Последующие сборки 146 | 147 | Когда сборка и TestFlight уже настроены, все, что вам нужно сделать, - это закоммитить свой код, перейти к «Build and Deliver» в Actions вашего репозитория и нажать «Run Workflow» 148 | 149 | Затем дождитесь уведомления и обновите приложение в TestFlight. Эту же сборку потом можно опубликовать в App Store 150 | 151 | # Что дальше 152 | 153 | Замените проект в каталоге Project своими творениями. Как правило, рекомендуется использовать систему управления версиями, такую ​​как Git, чтобы иметь историю изменений в вашем проекте и не потерять весь код из-за какой-то странной аварии. Вы можете клонировать репозиторий на свой компьютер, изменять содержимое, комитить изменения и создавать новые сборки. Когда обновление будет готово, тестируйте его при помощи TestFlight 154 | 155 | Другой вариант - интегрировать скрипты в ваши существующие проекты на GitHub. Все, что вам нужно, находится в файлах [`.github/workflows/build.yml`](.github/workflows/build.yml) и [`Util/build.sh`](Util/build.sh) 156 | 157 | ## Скажите спасибо ❤️ (бесплатно, без СМС) 158 | 159 | Если вам нравится этот шаблон и руководство, не забудьте отметить проекты звездочкой на GitHub: 160 | 161 | - Игровой движок Solar2D: [https://github.com/coronalabs/corona](https://github.com/coronalabs/corona) 162 | - Этот шаблон: [https://github.com/solar2d/demo-app-store-automation](https://github.com/solar2d/demo-app-store-automation) 163 | 164 | ## Поддержите проект 165 | 166 | Solar2D - это игровой движок с полностью открытым исходным кодом, для существования которого требуются пожертвования пользователей. Рассмотрите возможность [поддержки](http://github.com/coronalabs/corona?sponsor=1) проекта на [Patreon](https://patreon.com/shchvova) 167 | 168 | ### Примечания 169 | 170 | GitHub Actions имеют [ограничения на использование](https://docs.github.com/en/free-pro-team@latest/github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-actions), особенно для проектов в приватных репозиториях. Обязательно ознакомьтесь с ними. На данный момент минута для macOS равна 10 бесплатных минут для Linux и стоит 8 центов после превышения бесплатного лимита. Итого, в настоящее время у вас есть 200 бесплатных минут для сборки в приватных репозиториях. Этого более чем достаточно, чтобы билдить один или два раза в неделю. Вам не нужно вводить кредитную карту или что-то еще, пока у вас не закончатся бесплатные минуты, но даже если вы это сделаете, эту цену трудно превзойти 171 | 172 | ## Вопросы/пожелания 173 | 174 | Если у вас есть какие-либо вопросы, сообщите о них на [https://github.com/solar2d/demo-app-store-automation/issues](https://github.com/solar2d/demo-app-store-automation/issues) 175 | 176 | Наслаждайтесь и создавайте потрясающие игры с Solar2D! 177 | 178 | ![](https://solar2d.com/images/icon-180x180.png) 179 | -------------------------------------------------------------------------------- /Util/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ( 3 | set -e 4 | cd "$(dirname "$0")/.." 5 | WORKSPACE=${GITHUB_WORKSPACE:="$(pwd)"} 6 | export WORKSPACE 7 | 8 | function err { 9 | echo "$1" 1>&2 10 | return 1 11 | } 12 | 13 | echo "Verifying input parameters" 14 | 15 | S2D_BUILD_NUMBER="$(echo "$S2D_BUILD_NAME." | cut -d. -f2 )" 16 | [ "${APP_VERSION}" ] || err "AppVersion, required Action parameter is not set" 17 | [ "${S2D_BUILD_NAME}" ] || err "Solar2DBuild, required action parameter is not set" 18 | [ "${S2D_BUILD_NUMBER}" ] || err "Solar2DBuild, required action parameter has invalid format (i.e. 2020.3635)" 19 | [ "${CERT_PASSWORD}" ] || err "CertPassword secret is required" 20 | [ "${APPLE_USERNAME}" ] || err "AppleUser secret is required" 21 | [ "${APPLE_PASSWORD}" ] || err "ApplePassword secret is required" 22 | [ "${APPLE_TEAM_ID}" ] || echo "Warning AppleTeamId secret is not set. It is optional but may cause errors. To get your team ID run List Apple Teams workflow" 23 | 24 | # Setting op code signing only on CI not to screw with local Keychain if run on own machine 25 | if [ "$CI" ] 26 | then 27 | echo "Seting up code signing" 28 | 29 | security delete-keychain build.keychain || true 30 | security create-keychain -p 'Password123' build.keychain 31 | security default-keychain -s build.keychain 32 | security import "Util/distribution.p12" -A -P "$CERT_PASSWORD" 33 | security unlock-keychain -p 'Password123' build.keychain 34 | security set-keychain-settings build.keychain 35 | security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k 'Password123' build.keychain > /dev/null 36 | fi 37 | 38 | S2D_DMG="Util/S2D-${S2D_BUILD_NUMBER}.dmg" 39 | if [ ! -f "${S2D_DMG}" ] 40 | then 41 | echo "Downloading Solar2D" 42 | curl -L "https://github.com/coronalabs/corona/releases/download/${S2D_BUILD_NUMBER}/Solar2D-macOS-${S2D_BUILD_NAME}.dmg" -o "${S2D_DMG}" 43 | fi 44 | 45 | hdiutil attach "${S2D_DMG}" -noautoopen -mount required -mountpoint Util/S2D 46 | 47 | echo "Building the app" 48 | BUILDER="Util/S2D/Corona-${S2D_BUILD_NUMBER}/Native/Corona/mac/bin/CoronaBuilder.app/Contents/MacOS/CoronaBuilder" 49 | "$BUILDER" build --lua "Util/recipe.lua" 50 | 51 | hdiutil detach Util/S2D 52 | ) -------------------------------------------------------------------------------- /Util/deliver.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ( 3 | set -e 4 | 5 | echo "Uploading the app" 6 | if [ -z "${APPLE_TEAM_ID}" ] 7 | then 8 | xcrun altool --upload-app --type=ios -f Util/*.ipa -u "${APPLE_USERNAME}" -p "${APPLE_PASSWORD}" -asc_provider "${APPLE_TEAM_ID}" 9 | else 10 | xcrun altool --upload-app --type=ios -f Util/*.ipa -u "${APPLE_USERNAME}" -p "${APPLE_PASSWORD}" 11 | fi 12 | ) 13 | -------------------------------------------------------------------------------- /Util/distribution.mobileprovision: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Util/distribution.mobileprovision -------------------------------------------------------------------------------- /Util/distribution.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solar2d/demo-app-store-automation/dbce1daff28e60483ae947b2891c78b82149df8c/Util/distribution.p12 -------------------------------------------------------------------------------- /Util/recipe.lua: -------------------------------------------------------------------------------- 1 | 2 | local root = os.getenv('GITHUB_WORKSPACE') or os.getenv('WORKSPACE') 3 | 4 | return { 5 | appName = "Solar2Demo", 6 | platform = "ios", 7 | appVersion = os.getenv('APP_VERSION') or "1.0", 8 | projectPath = root .. "/Project", 9 | dstPath = root .. '/Util', 10 | certificatePath = root .. "/Util/distribution.mobileprovision", 11 | customTemplate = "-angle", 12 | } 13 | --------------------------------------------------------------------------------