Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .buildkite/commands/run-fastlane-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash

set -euo pipefail

if .buildkite/commands/should-skip-job.sh --job-type fastlane; then
exit 0
fi

echo '--- :fastlane: Run fastlane Helper Tests'
for test_file in fastlane/test/*_test.rb; do
ruby "$test_file"
done
29 changes: 27 additions & 2 deletions .buildkite/commands/should-skip-job.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ set -eu
# Since metrics measure app performance, test file changes don't affect them.
# - build: Skip if changes are limited to documentation and config files.
# Does NOT skip on localization changes since builds should include translation updates.
# - fastlane: Inverse of the others — only runs when fastlane/ or Ruby setup files change.
# Used for the standalone tests in fastlane/test/. App-only PRs skip it.
#
# Exit codes:
# 0 - Job should be skipped
Expand Down Expand Up @@ -76,6 +78,20 @@ TEST_PATTERNS=(
"metrics/**"
)

# Fastlane / Ruby setup files - changes here affect the standalone fastlane
# helper tests. Anything that the test runner reads (Fastfile, lib/, test/),
# that defines the Ruby environment, or that implements this CI job's runner /
# skip logic belongs here.
FASTLANE_PATTERNS=(
"fastlane/**"
"Gemfile"
"Gemfile.lock"
".ruby-version"
".bundle/**"
".buildkite/commands/run-fastlane-tests.sh"
".buildkite/commands/should-skip-job.sh"
)

show_skip_message() {
local job_type=$1
local job_label="${BUILDKITE_LABEL:-$job_type}"
Expand Down Expand Up @@ -107,7 +123,7 @@ done

if [[ -z "$job_type" ]]; then
echo "Error: --job-type is required"
echo "Usage: should-skip-job.sh --job-type <validation|metrics|build>"
echo "Usage: should-skip-job.sh --job-type <validation|metrics|build|fastlane>"
exit 1
fi

Expand Down Expand Up @@ -147,9 +163,18 @@ case "$job_type" in
fi
;;

"fastlane")
# Run only if at least one changed file is fastlane/ or Ruby-setup-related.
# Other job types treat fastlane changes as non-code; this one is the inverse.
if ! pr_changed_files --any-match "${FASTLANE_PATTERNS[@]}"; then
show_skip_message "$job_type"
exit 0
fi
;;

*)
echo "Unknown job type: $job_type"
echo "Valid types: validation, metrics, build"
echo "Valid types: validation, metrics, build, fastlane"
exit 1
;;
esac
Expand Down
10 changes: 10 additions & 0 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ steps:
- github_commit_status:
context: Lint

- label: ":fastlane: fastlane Helper Tests"
agents:
queue: mac
key: fastlane_tests
command: bash .buildkite/commands/run-fastlane-tests.sh
plugins: [$CI_TOOLKIT_PLUGIN]
notify:
- github_commit_status:
context: fastlane Helper Tests

- label: Unit Tests on {{matrix}}
key: unit_tests
command: bash .buildkite/commands/run-unit-tests.sh "{{matrix}}"
Expand Down
9 changes: 6 additions & 3 deletions fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ fastlane_require 'json'
fastlane_require 'net/http'
fastlane_require 'uri'

require_relative 'lib/studio_apps_cdn_upload'
require_relative 'lib/studio_release_git'
require_relative 'lib/studio_release_version'

Expand Down Expand Up @@ -712,12 +713,14 @@ def distribute_builds(
}
}

builds_to_upload = release_tag.nil? ? update_builds : { **update_builds, **full_install_builds }
builds_to_upload = { **update_builds, **full_install_builds }

UI.message("Uploading #{builds_to_upload.count} builds (#{release_tag.nil? ? 'dev: updates only' : 'release: all builds'})")
UI.message("Uploading #{builds_to_upload.count} builds (#{build_type})")

# Upload to Apps CDN
builds_to_upload.each_value do |build|
visibility = StudioAppsCdnUpload.visibility_for(build_type: build_type, install_type: build[:install_type])

result = upload_file_to_apps_cdn(
site_id: WPCOM_STUDIO_SITE_ID,
product: 'WordPress.com Studio',
Expand All @@ -726,7 +729,7 @@ def distribute_builds(
arch: build[:arch],
build_type: build_type,
install_type: build[:install_type],
visibility: 'external',
visibility: visibility,
version: version,
build_number: build_number,
release_notes: release_notes,
Expand Down
16 changes: 16 additions & 0 deletions fastlane/lib/studio_apps_cdn_upload.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

module StudioAppsCdnUpload
# Returns the Apps CDN visibility (`'internal'` or `'external'`) for a build.
#
# Nightly full installers are restricted to logged-in Automatticians via the
# Apps CDN visibility filter, so the `/nightly` link only resolves for
# internal users. Update binaries stay external — the in-app auto-updater is
# unauthenticated and would otherwise stop seeing nightly updates. Beta and
# Production stay external across the board.
def self.visibility_for(build_type:, install_type:)
return 'internal' if build_type == 'Nightly' && install_type == 'Full Install'

'external'
end
end
35 changes: 35 additions & 0 deletions fastlane/test/studio_apps_cdn_upload_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

# Sanity checks for fastlane/lib/studio_apps_cdn_upload.rb.
#
# Run with: `ruby fastlane/test/studio_apps_cdn_upload_test.rb`
# (No bundle / fastlane required — minitest ships with stdlib Ruby.)

require 'minitest/autorun'
require_relative '../lib/studio_apps_cdn_upload'

class StudioAppsCdnUploadTest < Minitest::Test
def test_nightly_full_install_is_internal
assert_equal 'internal', StudioAppsCdnUpload.visibility_for(build_type: 'Nightly', install_type: 'Full Install')
end

def test_nightly_update_is_external
assert_equal 'external', StudioAppsCdnUpload.visibility_for(build_type: 'Nightly', install_type: 'Update')
end

def test_beta_full_install_is_external
assert_equal 'external', StudioAppsCdnUpload.visibility_for(build_type: 'Beta', install_type: 'Full Install')
end

def test_beta_update_is_external
assert_equal 'external', StudioAppsCdnUpload.visibility_for(build_type: 'Beta', install_type: 'Update')
end

def test_production_full_install_is_external
assert_equal 'external', StudioAppsCdnUpload.visibility_for(build_type: 'Production', install_type: 'Full Install')
end

def test_production_update_is_external
assert_equal 'external', StudioAppsCdnUpload.visibility_for(build_type: 'Production', install_type: 'Update')
end
end