@daemux/store-automator 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/README.md +1 -1
- package/package.json +1 -1
- package/plugins/store-automator/.claude-plugin/plugin.json +1 -1
- package/templates/scripts/ci/android/manage-version.sh +16 -17
- package/templates/scripts/ci/android/sync-iap.sh +4 -4
- package/templates/scripts/ci/android/upload-metadata.sh +7 -5
- package/templates/scripts/ci/common/install-fastlane.sh +14 -0
- package/templates/scripts/ci/ios/build.sh +4 -10
- package/templates/scripts/ci/ios/set-build-number.sh +20 -17
- package/templates/scripts/ci/ios/setup-signing.sh +0 -9
- package/templates/scripts/ci/ios/sync-iap.sh +4 -4
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
},
|
|
6
6
|
"metadata": {
|
|
7
7
|
"description": "App Store & Google Play automation for Flutter apps",
|
|
8
|
-
"version": "0.9.
|
|
8
|
+
"version": "0.9.1"
|
|
9
9
|
},
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "store-automator",
|
|
13
13
|
"source": "./plugins/store-automator",
|
|
14
14
|
"description": "3 agents for app store publishing: reviewer, meta-creator, media-designer",
|
|
15
|
-
"version": "0.9.
|
|
15
|
+
"version": "0.9.1",
|
|
16
16
|
"keywords": ["flutter", "app-store", "google-play", "fastlane", "codemagic"]
|
|
17
17
|
}
|
|
18
18
|
]
|
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -47,8 +47,7 @@ if [ "${GOOGLE_PLAY_READY:-false}" != "true" ]; then
|
|
|
47
47
|
fi
|
|
48
48
|
fi
|
|
49
49
|
elif [ ! -f "$PROJECT_ROOT/$GOOGLE_SA_JSON_PATH" ]; then
|
|
50
|
-
echo "
|
|
51
|
-
exit 1
|
|
50
|
+
echo "WARNING: Service account JSON not found. Using default version code."
|
|
52
51
|
else
|
|
53
52
|
SA_FULL_PATH="$PROJECT_ROOT/$GOOGLE_SA_JSON_PATH"
|
|
54
53
|
cd "$APP_ROOT/android"
|
|
@@ -66,7 +65,7 @@ else
|
|
|
66
65
|
package_name:"$PACKAGE_NAME" \
|
|
67
66
|
json_key:"$SA_FULL_PATH" \
|
|
68
67
|
track:"$TRACK" 2>&1 \
|
|
69
|
-
| grep -oE '[0-9]+' | sort -n | tail -1)
|
|
68
|
+
| grep -oE '[0-9]+' | sort -n | tail -1 || echo "0")
|
|
70
69
|
|
|
71
70
|
# Fallback: direct Ruby Supply::Client API
|
|
72
71
|
if [ -z "$LATEST_CODE" ] || [ "$LATEST_CODE" = "0" ]; then
|
|
@@ -84,22 +83,22 @@ Supply.config = FastlaneCore::Configuration.create(
|
|
|
84
83
|
)
|
|
85
84
|
|
|
86
85
|
client = Supply::Client.make_from_config
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
begin
|
|
87
|
+
all_codes = []
|
|
88
|
+
['internal', 'alpha', 'beta', 'production'].each do |track|
|
|
89
|
+
begin
|
|
90
|
+
track_codes = client.track_version_codes(track)
|
|
91
|
+
all_codes.concat(track_codes) if track_codes
|
|
92
|
+
rescue => e
|
|
93
|
+
# Track may not exist yet
|
|
94
|
+
end
|
|
94
95
|
end
|
|
96
|
+
puts all_codes.max || 0
|
|
97
|
+
rescue => e
|
|
98
|
+
STDERR.puts \"Warning: Could not fetch version codes: #{e.message}\"
|
|
99
|
+
puts 0
|
|
95
100
|
end
|
|
96
|
-
|
|
97
|
-
")
|
|
98
|
-
fi
|
|
99
|
-
|
|
100
|
-
if [ -z "$LATEST_CODE" ]; then
|
|
101
|
-
echo "ERROR: Failed to fetch version codes from Google Play" >&2
|
|
102
|
-
exit 1
|
|
101
|
+
" 2>/dev/null || echo "0")
|
|
103
102
|
fi
|
|
104
103
|
|
|
105
104
|
echo "Latest version code from Google Play: $LATEST_CODE"
|
|
@@ -19,10 +19,10 @@ fi
|
|
|
19
19
|
|
|
20
20
|
# --- Check if IAP plugin is available ---
|
|
21
21
|
cd "$APP_ROOT/android"
|
|
22
|
-
if ! bundle exec gem list fastlane-plugin-iap --installed; then
|
|
23
|
-
echo "
|
|
24
|
-
echo "To enable: add it to app/android/Pluginfile and run 'bundle install'."
|
|
25
|
-
exit
|
|
22
|
+
if ! bundle exec gem list fastlane-plugin-iap --installed > /dev/null 2>&1; then
|
|
23
|
+
echo "WARNING: fastlane-plugin-iap not installed. Skipping IAP sync."
|
|
24
|
+
echo "To enable: add it to app/android/Pluginfile and run 'bundle install'."
|
|
25
|
+
exit 0
|
|
26
26
|
fi
|
|
27
27
|
|
|
28
28
|
# --- Hash-based change detection ---
|
|
@@ -60,12 +60,14 @@ echo "$FASTLANE_OUTPUT"
|
|
|
60
60
|
if [ $FASTLANE_EXIT -ne 0 ]; then
|
|
61
61
|
# Google Play API rejects non-draft edits on apps that have never been
|
|
62
62
|
# published. This resolves after the first manual release via the Play
|
|
63
|
-
# Console
|
|
63
|
+
# Console, so we warn instead of failing the workflow.
|
|
64
64
|
if echo "$FASTLANE_OUTPUT" | grep -qi "draft app"; then
|
|
65
|
-
echo "
|
|
66
|
-
echo "
|
|
67
|
-
echo "
|
|
68
|
-
|
|
65
|
+
echo ""
|
|
66
|
+
echo "WARNING: Metadata upload failed because the app is still in draft"
|
|
67
|
+
echo " state on Google Play. Complete the first release manually"
|
|
68
|
+
echo " via the Play Console, then re-run this workflow."
|
|
69
|
+
echo ""
|
|
70
|
+
exit 0
|
|
69
71
|
fi
|
|
70
72
|
exit $FASTLANE_EXIT
|
|
71
73
|
fi
|
|
@@ -30,6 +30,20 @@ if ! command -v bundle &>/dev/null; then
|
|
|
30
30
|
gem install bundler --no-document --user-install
|
|
31
31
|
fi
|
|
32
32
|
|
|
33
|
+
# Update Gemfile.lock to use the current bundler version.
|
|
34
|
+
# Old lockfiles (e.g., BUNDLED WITH 1.17.2) cause errors on modern Ruby
|
|
35
|
+
# because bundler auto-downloads the old version which may be incompatible.
|
|
36
|
+
LOCKFILE="$PLATFORM_DIR/Gemfile.lock"
|
|
37
|
+
if [ -f "$LOCKFILE" ]; then
|
|
38
|
+
CURRENT_BUNDLER=$(bundle --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
|
|
39
|
+
LOCK_BUNDLER=$(awk '/^BUNDLED WITH/{getline; gsub(/^[ \t]+|[ \t]+$/,""); print}' "$LOCKFILE")
|
|
40
|
+
if [ -n "$LOCK_BUNDLER" ] && [ "$LOCK_BUNDLER" != "$CURRENT_BUNDLER" ]; then
|
|
41
|
+
echo "Updating Gemfile.lock bundler: $LOCK_BUNDLER -> $CURRENT_BUNDLER"
|
|
42
|
+
awk -v ver=" $CURRENT_BUNDLER" '/^BUNDLED WITH/{print;getline;print ver;next}1' \
|
|
43
|
+
"$LOCKFILE" > "$LOCKFILE.tmp" && mv "$LOCKFILE.tmp" "$LOCKFILE"
|
|
44
|
+
fi
|
|
45
|
+
fi
|
|
46
|
+
|
|
33
47
|
bundle config set --local path vendor/bundle
|
|
34
48
|
bundle install --jobs 4 --retry 3
|
|
35
49
|
|
|
@@ -42,19 +42,13 @@ if [ -f "$PBXPROJ" ]; then
|
|
|
42
42
|
|
|
43
43
|
# Set the provisioning profile specifier for the Runner target
|
|
44
44
|
if [ -n "$PROFILE_NAME" ]; then
|
|
45
|
-
|
|
46
|
-
sed -i '' \
|
|
47
|
-
|
|
48
|
-
sed -i '' \
|
|
49
|
-
"s/$PKEY = ;/$PKEY = \"$PROFILE_NAME\";/g" "$PBXPROJ"
|
|
50
|
-
echo " $PKEY = $PROFILE_NAME"
|
|
45
|
+
sed -i '' "s/PROVISIONING_PROFILE_SPECIFIER = \"[^\"]*\"/PROVISIONING_PROFILE_SPECIFIER = \"$PROFILE_NAME\"/g" "$PBXPROJ"
|
|
46
|
+
sed -i '' "s/PROVISIONING_PROFILE_SPECIFIER = ;/PROVISIONING_PROFILE_SPECIFIER = \"$PROFILE_NAME\";/g" "$PBXPROJ"
|
|
47
|
+
echo " PROVISIONING_PROFILE_SPECIFIER = $PROFILE_NAME"
|
|
51
48
|
fi
|
|
52
49
|
|
|
53
50
|
# Set the code sign identity for distribution
|
|
54
|
-
sed -i '' \
|
|
55
|
-
's/"CODE_SIGN_IDENTITY\[sdk=iphoneos\*\]" = "iPhone Developer"/'\
|
|
56
|
-
'"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"/g' \
|
|
57
|
-
"$PBXPROJ"
|
|
51
|
+
sed -i '' 's/"CODE_SIGN_IDENTITY\[sdk=iphoneos\*\]" = "iPhone Developer"/"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"/g' "$PBXPROJ"
|
|
58
52
|
|
|
59
53
|
echo "Xcode project patched for CI signing"
|
|
60
54
|
fi
|
|
@@ -25,7 +25,7 @@ if [ -z "${APP_STORE_CONNECT_KEY_IDENTIFIER:-}" ]; then
|
|
|
25
25
|
fi
|
|
26
26
|
|
|
27
27
|
# --- Ensure PyJWT is installed ---
|
|
28
|
-
pip3 install --break-system-packages PyJWT
|
|
28
|
+
pip3 install --break-system-packages PyJWT >/dev/null 2>&1 || true
|
|
29
29
|
|
|
30
30
|
# --- Fetch latest build number from ASC ---
|
|
31
31
|
echo "Fetching latest build number from App Store Connect..."
|
|
@@ -44,22 +44,25 @@ payload = {'iss': issuer_id, 'iat': now, 'exp': now + 1200, 'aud': 'appstoreconn
|
|
|
44
44
|
token = jwt.encode(payload, private_key, algorithm='ES256', headers={'kid': key_id})
|
|
45
45
|
headers = {'Authorization': f'Bearer {token}'}
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
47
|
+
try:
|
|
48
|
+
# Resolve app ID from bundle ID
|
|
49
|
+
req = urllib.request.Request(
|
|
50
|
+
f'https://api.appstoreconnect.apple.com/v1/apps?filter[bundleId]={bundle_id}',
|
|
51
|
+
headers=headers)
|
|
52
|
+
with urllib.request.urlopen(req) as resp:
|
|
53
|
+
app_id = json.loads(resp.read())['data'][0]['id']
|
|
54
|
+
|
|
55
|
+
# Fetch latest build
|
|
56
|
+
req = urllib.request.Request(
|
|
57
|
+
f'https://api.appstoreconnect.apple.com/v1/builds?filter[app]={app_id}&sort=-version&limit=1',
|
|
58
|
+
headers=headers)
|
|
59
|
+
with urllib.request.urlopen(req) as resp:
|
|
60
|
+
builds = json.loads(resp.read())['data']
|
|
61
|
+
|
|
62
|
+
print(builds[0]['attributes']['version'] if builds else '0')
|
|
63
|
+
except Exception:
|
|
64
|
+
print('0')
|
|
65
|
+
" 2>/dev/null || echo "0")
|
|
63
66
|
|
|
64
67
|
echo "Latest build number from ASC: $LATEST_BUILD"
|
|
65
68
|
|
|
@@ -43,10 +43,6 @@ setup_ssh_agent() {
|
|
|
43
43
|
|
|
44
44
|
mkdir -p ~/.ssh
|
|
45
45
|
ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null
|
|
46
|
-
if ! grep -q "github.com" ~/.ssh/known_hosts; then
|
|
47
|
-
echo "ERROR: ssh-keyscan failed to retrieve github.com host key" >&2
|
|
48
|
-
exit 1
|
|
49
|
-
fi
|
|
50
46
|
|
|
51
47
|
echo "SSH agent configured with deploy key"
|
|
52
48
|
}
|
|
@@ -203,11 +199,6 @@ find_team_id() {
|
|
|
203
199
|
/dev/stdin <<< "$(security cms -D -i "$profile_file" 2>/dev/null)" \
|
|
204
200
|
2>/dev/null || echo "")
|
|
205
201
|
fi
|
|
206
|
-
|
|
207
|
-
if [ -z "$TEAM_ID" ]; then
|
|
208
|
-
echo "ERROR: Could not extract TEAM_ID from signing identity or provisioning profile" >&2
|
|
209
|
-
exit 1
|
|
210
|
-
fi
|
|
211
202
|
}
|
|
212
203
|
|
|
213
204
|
# --- Step 8: Generate ExportOptions.plist ---
|
|
@@ -21,10 +21,10 @@ fi
|
|
|
21
21
|
# ── Step 3: Check if IAP plugin is available ──
|
|
22
22
|
cd "$APP_ROOT/ios"
|
|
23
23
|
|
|
24
|
-
if ! bundle exec gem list fastlane-plugin-iap --installed; then
|
|
25
|
-
echo "
|
|
26
|
-
echo "To enable: add 'fastlane-plugin-iap' to $APP_ROOT/ios/Gemfile and run 'bundle install'."
|
|
27
|
-
exit
|
|
24
|
+
if ! bundle exec gem list fastlane-plugin-iap --installed >/dev/null 2>&1; then
|
|
25
|
+
echo "WARNING: fastlane-plugin-iap not installed. Skipping IAP sync."
|
|
26
|
+
echo "To enable: add 'fastlane-plugin-iap' to $APP_ROOT/ios/Gemfile and run 'bundle install'."
|
|
27
|
+
exit 0
|
|
28
28
|
fi
|
|
29
29
|
|
|
30
30
|
echo "fastlane-plugin-iap is installed. Proceeding with sync."
|