Last active
August 15, 2023 14:46
-
-
Save jeffdonthemic/eec37b3980fcb1af7e80ddd58f4bcf7e to your computer and use it in GitHub Desktop.
Salesforce 2GP Packaging CLI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
source 'https://rubygems.org' | |
gem 'restforce', '~> 6.2.2' | |
gem 'thor' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'restforce' | |
require 'stringio' | |
require 'thor' | |
# INSTRUCTIONS | |
# 1. Place both files in a new directory | |
# 2. Install the ruby gems: | |
# > bundle | |
# Display the list of commands: | |
# > thor list | |
# thor packaging:subscribers # Returns all subscriber orgs filtered by an optional package version id | |
# thor packaging:subscribers_count # Returns the number of subscriber orgs filtered by an optional package version id | |
# thor packaging:upgrade # Upgrades all subscriber orgs or a specific subsciber org with a specific Package Version - ex: thor packaging:upgrade PACKAGE_VERSION_ID --org_id ORG_ID | |
# thor packaging:upgrade_status # Displays the status of PACKAGE_PUSH_REQUEST_ID and optionally the individual jobs - ex: thor packaging:upgrade_status PACKAGE_PUSH_REQUEST_ID --show_jobs | |
# thor packaging:versions # Returns all package versions | |
# COMMAND HELP | |
# > thor help packaging:upgrade | |
# Usage: | |
# thor packaging:upgrade | |
# | |
# Options: | |
# [--org-id=ORG_ID] # The Id of the subscriber org to be upgraded. | |
# | |
# Upgrades all subscriber orgs or a specific subsciber org with a specific Package Version - ex: thor packaging:upgrade PACKAGE_VERSION_ID --org_id ORG_ID | |
# UPGRADE DOCS: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/push_upgrade_use_api.htm?q=packageversion | |
# WARNING: Push upgrades have not been testing for >2000 subscriber orgs. | |
class Packaging < Thor | |
org = JSON.parse(`sfdx org display --json`) | |
if org['result']['username'] != 'YOUR_DEVHUB_ORG_USERNAME' | |
abort "Aborted! The DevHub org is not the default sfdx user. Run: sf config set defaultusername=YOUR_DEVHUB_ORG_USERNAME" | |
end | |
@@client = Restforce.new( | |
oauth_token: org['result']['accessToken'], | |
instance_url: org['result']['instanceUrl'], | |
api_version: '57.0' | |
) | |
desc "upgrade_status", "Displays the status of PACKAGE_PUSH_REQUEST_ID and optionally the individual jobs - ex: thor packaging:upgrade_status PACKAGE_PUSH_REQUEST_ID --show_jobs" | |
method_option :show_jobs, :desc => "Displays the individual jobs' status" | |
def upgrade_status(package_push_request_id) | |
status = @@client.query("SELECT DurationSeconds,EndTime,Id,PackageVersionId,ScheduledStartTime,StartTime,Status FROM PackagePushRequest WHERE ID = '#{package_push_request_id}'") | |
puts 'PACKAGE PUSH REQUEST' | |
puts '-----------------------' | |
puts "Status: #{status.first.Status}" | |
puts "ScheduledStartTime: #{status.first.ScheduledStartTime}" | |
puts "StartTime: #{status.first.StartTime}" | |
puts "EndTime: #{status.first.EndTime}" | |
puts "DurationSeconds: #{status.first.DurationSeconds}" | |
puts "PackageVersionId: #{status.first.PackageVersionId}" | |
puts '-----------------------' | |
if options[:show_jobs] | |
jobs = @@client.query("SELECT DurationSeconds,EndTime,Id,StartTime,Status,SubscriberOrganizationKey FROM PackagePushJob WHERE PackagePushRequestId = '#{package_push_request_id}'") | |
puts '' | |
puts 'INDIVIDUAL SUBSCRIBER ORG JOBS' | |
puts '-----------------------' | |
jobs.each do |v| | |
puts "SubscriberOrganizationKey: #{v.SubscriberOrganizationKey}" | |
puts "Status: #{v.Status}" | |
puts "DurationSeconds: #{v.DurationSeconds}" | |
puts "StartTime: #{v.StartTime}" | |
puts "EndTime: #{v.EndTime}" | |
puts '-----------------------' | |
end | |
end | |
end | |
desc "upgrade", "Upgrades all subscriber orgs or a specific subsciber org with a specific Package Version - ex: thor packaging:upgrade PACKAGE_VERSION_ID --org_id ORG_ID" | |
method_option :org_id, :desc => "The Id of the subscriber org to be upgraded." | |
def upgrade(package_version_id) | |
# check that the org is available for upgrade | |
if options[:org_id] | |
subscribers = @@client.query("SELECT OrgKey FROM PackageSubscriber WHERE OrgKey = '#{options[:org_id]}' AND MetadataPackageVersionId != '#{package_version_id}'") | |
org_count = subscribers.count | |
else | |
subscribers = @@client.query("SELECT OrgKey FROM PackageSubscriber WHERE MetadataPackageVersionId != '#{package_version_id}'") | |
org_count = subscribers.count | |
end | |
if org_count > 0 | |
request_id = @@client.create('PackagePushRequest', PackageVersionId: package_version_id) | |
# upgrade one specific org | |
if options[:org_id] | |
puts "Upgrading Org Id: #{options[:org_id]}" | |
@@client.create('PackagePushJob', PackagePushRequestId: request_id, SubscriberOrganizationKey: options[:org_id]) | |
# upgrade all orgs not on the package version | |
else | |
puts "Upgrading #{subscribers.count} orgs" | |
subscribers.each do |s| | |
@@client.create('PackagePushJob', PackagePushRequestId: request_id, SubscriberOrganizationKey: s.OrgKey) | |
end | |
end | |
# update the package push request to start the deployment | |
@@client.update('PackagePushRequest', Id: request_id, Status: 'Pending') | |
puts "Package Push Request #{request_id} started for #{org_count} subscriber org(s). Check the status with: thor packaging:upgrade_status #{request_id} --show_jobs" | |
else | |
puts 'No orgs found to upgrade.' | |
end | |
end | |
desc "versions", "Returns all package versions" | |
def versions | |
versions = @@client.query("SELECT Id,MajorVersion,MetadataPackageId,MinorVersion,Name,PatchVersion,ReleaseState FROM MetadataPackageVersion ORDER BY SystemModstamp") | |
puts '-----------------------' | |
versions.each do |v| | |
puts "Name: #{v.Name}" | |
puts "MetadataPackageId: #{v.MetadataPackageId}" | |
puts "MajorVersion: #{v.MajorVersion}" | |
puts "MinorVersion: #{v.MinorVersion}" | |
puts "PatchVersion: #{v.PatchVersion}" | |
puts "ReleaseState: #{v.ReleaseState}" | |
puts '-----------------------' | |
end | |
end | |
desc "subscribers", "Returns all subscriber orgs filtered by an optional package version id" | |
method_option :package_version_id, :aliases => :p, :desc => "Filter subscriber orgs by installed pacakge." | |
def subscribers | |
q = "SELECT Id,InstalledStatus,MetadataPackageId,MetadataPackageVersionId,OrgKey FROM PackageSubscriber WHERE OrgStatus != 'Inactive'" | |
if options[:package_version_id] | |
q << " AND MetadataPackageVersionId = '#{options[:package_version_id]}'" | |
end | |
subscribers = @@client.query(q) | |
puts '-----------------------' | |
subscribers.each do |o| | |
puts "InstalledStatus: #{o.InstalledStatus}" | |
puts "MetadataPackageVersionId: #{o.MetadataPackageVersionId}" | |
puts "Org ID: #{o.OrgKey}" | |
puts '-----------------------' | |
end | |
puts "#{subscribers.count} subscriber orgs" | |
end | |
desc "subscribers_count", "Returns the number of subscriber orgs filtered by an optional package version id" | |
method_option :package_version_id, :aliases => :p, :desc => "Filter subscriber orgs by installed pacakge." | |
def subscribers_count | |
q = "SELECT count() FROM PackageSubscriber WHERE OrgStatus != 'Inactive'" | |
if options[:package_version_id] | |
q << " AND MetadataPackageVersionId = '#{options[:package_version_id]}'" | |
end | |
subscribers = @@client.query(q) | |
pp subscribers.count | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment