@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.
@@ -5,14 +5,14 @@
5
5
  },
6
6
  "metadata": {
7
7
  "description": "App Store & Google Play automation for Flutter apps",
8
- "version": "0.9.0"
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.0",
15
+ "version": "0.9.1",
16
16
  "keywords": ["flutter", "app-store", "google-play", "fastlane", "codemagic"]
17
17
  }
18
18
  ]
package/README.md CHANGED
@@ -22,7 +22,7 @@ Plus CI/CD templates for Codemagic, Fastlane, web pages, and scripts.
22
22
 
23
23
  ```bash
24
24
  cd your-flutter-project
25
- npm install @daemux/store-automator
25
+ npm install @daemux/store-automator@latest
26
26
  ```
27
27
 
28
28
  The postinstall script will:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@daemux/store-automator",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Full App Store & Google Play automation for Flutter apps with Claude Code agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "store-automator",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "App Store & Google Play automation agents for Flutter app publishing",
5
5
  "author": {
6
6
  "name": "Daemux"
@@ -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 "ERROR: Service account JSON not found at $PROJECT_ROOT/$GOOGLE_SA_JSON_PATH" >&2
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
- 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
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
- puts all_codes.max || 0
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 "ERROR: fastlane-plugin-iap not installed." >&2
24
- echo "To enable: add it to app/android/Pluginfile and run 'bundle install'." >&2
25
- exit 1
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. Hard-fail so the CI run surfaces the issue immediately.
63
+ # Console, so we warn instead of failing the workflow.
64
64
  if echo "$FASTLANE_OUTPUT" | grep -qi "draft app"; then
65
- echo "ERROR: Metadata upload failed because the app is still in draft" >&2
66
- echo " state on Google Play. Complete the first release manually" >&2
67
- echo " via the Play Console, then re-run this workflow." >&2
68
- exit 1
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
- PKEY="PROVISIONING_PROFILE_SPECIFIER"
46
- sed -i '' \
47
- "s/$PKEY = \"[^\"]*\"/$PKEY = \"$PROFILE_NAME\"/g" "$PBXPROJ"
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
- # Resolve app ID from bundle ID
48
- req = urllib.request.Request(
49
- f'https://api.appstoreconnect.apple.com/v1/apps?filter[bundleId]={bundle_id}',
50
- headers=headers)
51
- with urllib.request.urlopen(req) as resp:
52
- app_id = json.loads(resp.read())['data'][0]['id']
53
-
54
- # Fetch latest build
55
- req = urllib.request.Request(
56
- f'https://api.appstoreconnect.apple.com/v1/builds?filter[app]={app_id}&sort=-version&limit=1',
57
- headers=headers)
58
- with urllib.request.urlopen(req) as resp:
59
- builds = json.loads(resp.read())['data']
60
-
61
- print(builds[0]['attributes']['version'] if builds else '0')
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 "ERROR: fastlane-plugin-iap not installed." >&2
26
- echo "To enable: add 'fastlane-plugin-iap' to $APP_ROOT/ios/Gemfile and run 'bundle install'." >&2
27
- exit 1
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."