deploy()
構文
1AsyncResult = metadatabinding.deploy(base64 zipFile, DeployOptions deployOptions)使用方法
このコールを使用して、ファイル表現のコンポーネントを取得し、ファイル表現のコンポーネントが表すコンポーネントを作成、更新、または削除することにより、組織にファイル表現のコンポーネントをリリースします。
リリース制限は次のとおりです。
| 機能 | 制限 |
|---|---|
| 最大圧縮 .zip フォルダーサイズ1 | 約 39 MB |
| 最大非圧縮フォルダーサイズ 2 | 約 400 MB |
| AppExchange パッケージの最大ファイル数 | 35,000 |
| パッケージの最大ファイル数 | 10,000 |
1 メタデータ API base-64 では、コンポーネントを圧縮後にエンコードします。結果の .zip ファイルの最大サイズは 50 MB です。Base-64 エンコードではペイロードのサイズが約 22% 増加するため、エンコードする前に、圧縮済みペイロードが約 39 MB を超えることはできません。
2 Ant 移行ツールを使用して、展開したプロジェクトをリリースする場合、まずプロジェクト内のすべてのファイルが圧縮されます。非圧縮プロジェクト内の非���縮コンポーネントの最大サイズは、ファイルの圧縮率に応じて 400 MB 以下です。ファイルの圧縮率が高い場合、圧縮されたサイズは 39 MB を下回るため、合計およそ 400 MB を移行できます。ただし、バイナリ静的リソースのように、それほど圧縮できないコンポーネントの場合、移行できるのは 400 MB 未満です。
API バージョン 29.0 では、Salesforce は、リリース状況プロパティを改善し、deploy() コール後にリリースに関する情報を取得するために checkStatus() を使用する要件を削除しました。Salesforce では、API バージョン 28.0 以前で deploy() を使用する場合の checkStatus() の使用を引き続きサポートします。
組織へのコンポーネントのリリース
package.xml ファイルは、取得またはリリースするすべてのコンポーネントをリストするプロジェクトマニフェストです。package.xml を使用して、コンポーネントを追加できます。コンポーネントを削除するには、別のマニフェストファイルを追加します。「組織からのコンポーネントの削除」を参照してください。
API バージョン 29.0 以降の場合、パッケージ化されたコンポーネントまたはパッケージ化されていないコンポーネントをリリース (作成または更新) する方法は次のとおりです。
- deploy() コールを発行して、非同期リリースを開始すると、AsyncResult オブジェクトが返されます。id 項目の値をメモし、次のステップで使用します。
- checkDeployStatus() コールの発行をループします。このループは、返される DeployResult の done 項目がコールの完了を示す true になるまで続けられます。DeployResult オブジェクトには、deploy() コールを使用して開始された進行中または完了済みのリリースに関する情報が含まれます。checkDeployStatus() をコールするとき、最初のステップの AsyncResult オブジェクトから id 値を渡します。
API バージョン 28.0 以前の場合、パッケージ化されたコンポーネントまたはパッケージ化されていないコンポーネントをリリース (作成または更新) する方法は次のとおりです。
- deploy() コールを発行して、非同期リリースを開始すると、AsyncResult オブジェクトが返されます。コールが完了すると、done 項目に true が含まれます。ほとんどの場合、コールはすぐに完了しないため、最初の結果に記述されません。完了している場合、返された id 項目の値を書き留め、次のステップを省略します。
- コールが完了していない場合、ループ内で checkStatus() コールを発行します。このループ内で、前のステップで deploy() コールから返された AsyncResult オブジェクトの id 項目の値を使用します。done 項目に true が含まれるまで、返される AsyncResult オブジェクトを確認します。deploy() コールを完了するまでにかかる時間は、リリースする zip ファイルのサイズによって異なります。そのため、zip ファイルのサイズが大きいほど、反復間の待機時間を長くします。
- 最初のステップで返された id 値を使用して、checkDeployStatus() コールを発行し、deploy() コールの結果を取得します。
リリースの状況の確認
メタデータ API を使用するか、[設定] からリリースの状況を確認します。進行中または過去 30 日間に完了したリリースの状況を確認できます。
メタデータ API を使用してリリースの状況を確認するには、checkDeployStatus() を参照してください。
[設定] からリリースの状況を確認するには、[クイック検索] ボックスに「リリース状況」と入力し、[リリース状況] を選択します。
リリースの実行中、[リリース状況] ページには、現在のリリースについてリアルタイムの進行状況が表示されます。このページでは、グラフで全体的なリリースの進行状況が視覚的に表現されます。最初のグラフでは、コンポーネント総数のうちリリースが終了したコンポーネント数と、エラーがあったコンポーネント数が表示されます。たとえば、次のグラフは、450 コンポーネント中 302 コンポーネントが正常に処理され、45 コンポーネントにエラーがあったことを示しています。

すべてのコンポーネントがエラーなしでリリースされると、必要または有効な場合は Apex テストが実行を開始します。2 つ目のグラフは、Apex テストの総数のうち、実行された数と、返されたエラーの数が表示されます。さらに、このグラフには現在実行中のテスト名が表示されます。たとえば、次のグラフでは、合計 120 件のテストのうち 77 件の実行が完了し、1 件が失敗したことを示しています。

複数のリリースを開始できますが、一度に実行できるリリースは 1 つのみです。その他のリリースはキューに残り、現在のリリースの終了後に実行されるまで待機します。キューに入れられたリリースは、[待機中のリリース] の下にリストされます。それらは必ずしも送信された順序で実行されるわけではありません。特定の順序でリリースを実行するには、前のリリースが正常に完了した後に、1 つずつリリースを送信します。
リリースのキャンセル
メタデータ API を使用するか、[設定] からリリースをキャンセルします。進行中またはキュー内のリリースをキャンセルできます。
メタデータ API を使用してリリースをキャンセルするには、cancelDeploy() を参照してください。
[設定] からリリースをキャンセルするには、[クイック検索] ボックスに「リリース状況」と入力し、[リリース状況] を選択します。キャンセルするリリースの横にある [キャンセル] をクリックします。キャンセルが完了するまで、リリースの状況は [キャンセル要求済み] になります。キャンセルされたリリースは、[失敗] セクションにリストされます。
引数
| 名前 | 型 | 説明 |
|---|---|---|
| zipFile | base64 | Base 64 で符号化されたバイナリデータ。クライアントアプリケーションは、バイナリデータを base64 に符号化する必要があります。 |
| deployOptions | DeployOptions | リリースするパッケージまたはファイルを特定するためのオプションをカプセル化します。 |
DeployOptions
このコールでは次のリリースオプションを選択できます。
| 名前 | 型 | 説明 |
|---|---|---|
| allowMissingFiles | boolean | package.xml に指定されているファイルが .zip ファイル内に存在しない場合にも、リリースの継続を許可するかどうかを指定します。 |
| autoUpdatePackage | boolean | ファイルが .zip ファイルにはあるが、package.xml で指定されていない場合、ファイルを自動的にパッケージに追加するかどうかを指定します。.zip ファイルを含む package.xml が更新された場合は、retrieve() が発行されます。 本番組織へのリリースでは、この引数を設定することはできません。 |
| checkOnly | boolean | デフォルトは false です。コンポーネントを対象組織に保存せずにコンポーネントのテストリリース (検証) を実行するには、true に設定します。検証では、リリースで生成されるテストの結果を確認できますが、変更はコミットされません。テストに合格して検証が完了したら、テストを再実行することなくリリースできる場合があります。「deployRecentValidation()」を参照してください。 データ型を [主従関係] から [ルックアップ] (またはその逆) に変更している場合、checkOnly オプションを使用してリリースをテストするときに、この変更はサポートされません。データの完全な変更を避けるため、テストリリースではこの変更はサポートされていません。テストリリースでサポートされない変更がリリースパッケージに含まれる場合、テストリリースは失敗し、エラーが発生します。 リリースパッケージでデータ型が主従関係からルックアップ (またはその逆) に変更されている場合でも、本番組織にリリースする前に変更を検証することができます。別のテスト用 Sandbox 組織に対して完全リリースを実行します。完全リリースには、リリースプロセスの一部としての変更の検証が含まれます。 主従関係が含まれるメタデータ API リリースでは、次の場合にごみ箱内のすべての従レコードが削除されます。
|
| ignoreWarnings | boolean |
警告付きのリリースが正常に完了するか (true)、否か (false) を示します。デフォルトは false です。 警告の DeployMessage オブジェクトには次の値が含まれます。
警告が発生し、ignoreWarnings が true に設定されている場合は、DeployMessage の success 項目は true です。ignoreWarnings が false に設定されている場合、success は false に設定され、警告はエラーとして処理されます。 この項目は、API バージョン 18.0 以降で使用できます。バージョン 18.0 より前では、警告とエラーは区別されていませんでした。すべての問題はエラーとして処理され、リリースの成功を妨げていました。 |
| performRetrieve | boolean | retrieve() コールをリリース直後に実行するか (true)、否か (false) を示します。リリースされたものをすべて取得するには true に設定します。 |
| purgeOnDelete | boolean |
true の場合、destructiveChanges.xml マニフェストファイルの削除されたコンポーネントはごみ箱に保存されません。代わりに、即座に削除の対象となります。 この項目は、API バージョン 22.0 以降で使用できます。 このオプションは Developer Edition 組織または Sandbox 組織でのみ機能しますが、本番組織では機能しません。 メタデータ API を使用して積み上げ集計項目を削除した場合、その項目はごみ箱に保存されません。purgeOnDelete リリースオプションを true に設定していなくても、項目は消去されます。 |
| rollbackOnError | boolean | エラーが発生した場合、ロールバックを完了するか (true)、否か (false) を示します。false の場合、エラーなしで実行できるアクションはすべて実行され、残りのアクションではエラーが返されます。本番組織にリリースする場合は、このパラメーターは true に設定されている必要があります。デフォルトは、false です。 |
| runAllTests | boolean | (廃止済みであり、API バージョン 33.0 以前でのみ使用できます。)この項目のデフォルトは false です。インストール済みの管理パッケージから作成されたテストを含むすべての Apex テストをリリース後に実行するには、true に設定します。 リリースの一環として実行される Apex テストは、常に順序に従って同期実行されます。 |
| runTests | string[] | リリース時に実行される Apex テストのリスト。クラ��名 (1 インスタンスあたり 1 つの名前) を指定します。また、クラス名にはドット表記で名前空間を指定することもできます。詳細は、「リリースでのテストのサブセットの実行」を参照してください。 このオプションを使用するには、testLevel を RunSpecifiedTests に設定します。 |
| singlePackage | boolean | 指定された .zip ファイルが指し示すディレクトリ構造が 1 つのパッケージを持つか (true)、パッケージのセットを持つか (false)) を示します。 |
| testLevel | TestLevel (string 型の列挙) | 省略可能。リリースの一環として実行するテストを指定します。テストレベルは、リリースパッケージに存在するコンポーネントの種類に関係なく強制適用されます。有効な値は、次のとおりです。
テストレベルを指定しないと、デフォルトのテスト実行動作が使用されます。「リリースでのテストの実行」を参照してください。 リリースの一環として実行される Apex テストは、常に順序に従って同期実行されます。 この項目は、API バージョン 34.0 以降で使用できます。 |
応答
サンプルコード — Java
このサンプルでは、zip ファイルでコンポーネントをリリースする方法を示します。zip ファイルの取得方法についての詳細は、retrieve() のサンプルコードを参照してください。
1package com.doc.samples;
2
3import java.io.*;
4
5import java.rmi.RemoteException;
6
7import com.sforce.soap.metadata.AsyncResult;
8import com.sforce.soap.metadata.DeployDetails;
9import com.sforce.soap.metadata.MetadataConnection;
10import com.sforce.soap.metadata.DeployOptions;
11import com.sforce.soap.metadata.DeployResult;
12import com.sforce.soap.metadata.DeployMessage;
13import com.sforce.soap.metadata.RunTestsResult;
14import com.sforce.soap.metadata.RunTestFailure;
15import com.sforce.soap.metadata.CodeCoverageWarning;
16import com.sforce.soap.enterprise.LoginResult;
17import com.sforce.soap.enterprise.EnterpriseConnection;
18import com.sforce.ws.ConnectionException;
19import com.sforce.ws.ConnectorConfig;
20
21/**
22 * Deploy a zip file of metadata components.
23 * Prerequisite: Have a deploy.zip file that includes a package.xml manifest file that
24 * details the contents of the zip file.
25 */
26public class DeploySample {
27 // binding for the metadata WSDL used for making metadata API calls
28 private MetadataConnection metadataConnection;
29
30 static BufferedReader rdr = new BufferedReader(new InputStreamReader(System.in));
31
32 private static final String ZIP_FILE = "deploy.zip";
33
34 // one second in milliseconds
35 private static final long ONE_SECOND = 1000;
36 // maximum number of attempts to deploy the zip file
37 private static final int MAX_NUM_POLL_REQUESTS = 50;
38
39 public static void main(String[] args) throws Exception {
40 final String USERNAME = "user@company.com";
41 // This is only a sample. Hard coding passwords in source files is a bad practice.
42 final String PASSWORD = "password";
43 final String URL = "https://login.salesforce.com/services/Soap/c/29.0";
44
45 DeploySample sample = new DeploySample(USERNAME, PASSWORD, URL);
46 sample.deployZip();
47 }
48
49 public DeploySample(String username, String password, String loginUrl)
50 throws ConnectionException {
51 createMetadataConnection(username, password, loginUrl);
52 }
53
54 public void deployZip()
55 throws RemoteException, Exception
56 {
57 byte zipBytes[] = readZipFile();
58 DeployOptions deployOptions = new DeployOptions();
59 deployOptions.setPerformRetrieve(false);
60 deployOptions.setRollbackOnError(true);
61 AsyncResult asyncResult = metadataConnection.deploy(zipBytes, deployOptions);
62 String asyncResultId = asyncResult.getId();
63
64 // Wait for the deploy to complete
65 int poll = 0;
66 long waitTimeMilliSecs = ONE_SECOND;
67 DeployResult deployResult = null;
68 boolean fetchDetails;
69 do {
70 Thread.sleep(waitTimeMilliSecs);
71 // double the wait time for the next iteration
72 waitTimeMilliSecs *= 2;
73 if (poll++ > MAX_NUM_POLL_REQUESTS) {
74 throw new Exception("Request timed out. If this is a large set " +
75 "of metadata components, check that the time allowed by " +
76 "MAX_NUM_POLL_REQUESTS is sufficient.");
77 }
78
79 // Fetch in-progress details once for every 3 polls
80 fetchDetails = (poll % 3 == 0);
81 deployResult = metadataConnection.checkDeployStatus(asyncResultId, fetchDetails);
82 System.out.println("Status is: " + deployResult.getStatus());
83 if (!deployResult.isDone() && fetchDetails) {
84 printErrors(deployResult, "Failures for deployment in progress:\n");
85 }
86 }
87 while (!deployResult.isDone());
88
89 if (!deployResult.isSuccess() && deployResult.getErrorStatusCode() != null) {
90 throw new Exception(deployResult.getErrorStatusCode() + " msg: " +
91 deployResult.getErrorMessage());
92 }
93
94 if (!fetchDetails) {
95 // Get the final result with details if we didn't do it in the last attempt.
96 deployResult = metadataConnection.checkDeployStatus(asyncResultId, true);
97 }
98
99 if (!deployResult.isSuccess()) {
100 printErrors(deployResult, "Final list of failures:\n");
101 throw new Exception("The files were not successfully deployed");
102 }
103
104 System.out.println("The file " + ZIP_FILE + " was successfully deployed");
105 }
106
107 /**
108 * Read the zip file contents into a byte array.
109 * @return byte[]
110 * @throws Exception - if cannot find the zip file to deploy
111 */
112 private byte[] readZipFile()
113 throws Exception
114 {
115 // We assume here that you have a deploy.zip file.
116 // See the retrieve sample for how to retrieve a zip file.
117 File deployZip = new File(ZIP_FILE);
118 if (!deployZip.exists() || !deployZip.isFile())
119 throw new Exception("Cannot find the zip file to deploy. Looking for " +
120 deployZip.getAbsolutePath());
121
122 FileInputStream fos = new FileInputStream(deployZip);
123 ByteArrayOutputStream bos = new ByteArrayOutputStream();
124 int readbyte = -1;
125 while ((readbyte = fos.read()) != -1) {
126 bos.write(readbyte);
127 }
128 fos.close();
129 bos.close();
130 return bos.toByteArray();
131 }
132
133
134 /**
135 * Print out any errors, if any, related to the deploy.
136 * @param result - DeployResult
137 */
138 private void printErrors(DeployResult result, String messageHeader)
139 {
140 DeployDetails deployDetails = result.getDetails();
141
142 StringBuilder errorMessageBuilder = new StringBuilder();
143 if (deployDetails != null) {
144 DeployMessage[] componentFailures = deployDetails.getComponentFailures();
145 for (DeployMessage message : componentFailures) {
146 String loc = (message.getLineNumber() == 0 ? "" :
147 ("(" + message.getLineNumber() + "," +
148 message.getColumnNumber() + ")"));
149 if (loc.length() == 0
150 && !message.getFileName().equals(message.getFullName())) {
151 loc = "(" + message.getFullName() + ")";
152 }
153 errorMessageBuilder.append(message.getFileName() + loc + ":" +
154 message.getProblem()).append('\n');
155 }
156 RunTestsResult rtr = deployDetails.getRunTestResult();
157 if (rtr.getFailures() != null) {
158 for (RunTestFailure failure : rtr.getFailures()) {
159 String n = (failure.getNamespace() == null ? "" :
160 (failure.getNamespace() + ".")) + failure.getName();
161 errorMessageBuilder.append("Test failure, method: " + n + "." +
162 failure.getMethodName() + " -- " +
163 failure.getMessage() + " stack " +
164 failure.getStackTrace() + "\n\n");
165 }
166 }
167 if (rtr.getCodeCoverageWarnings() != null) {
168 for (CodeCoverageWarning ccw : rtr.getCodeCoverageWarnings()) {
169 errorMessageBuilder.append("Code coverage issue");
170 if (ccw.getName() != null) {
171 String n = (ccw.getNamespace() == null ? "" :
172 (ccw.getNamespace() + ".")) + ccw.getName();
173 errorMessageBuilder.append(", class: " + n);
174 }
175 errorMessageBuilder.append(" -- " + ccw.getMessage() + "\n");
176 }
177 }
178 }
179
180 if (errorMessageBuilder.length() > 0) {
181 errorMessageBuilder.insert(0, messageHeader);
182 System.out.println(errorMessageBuilder.toString());
183 }
184 }
185
186 private void createMetadataConnection(
187 final String username,
188 final String password,
189 final String loginUrl) throws ConnectionException {
190
191 final ConnectorConfig loginConfig = new ConnectorConfig();
192 loginConfig.setAuthEndpoint(loginUrl);
193 loginConfig.setServiceEndpoint(loginUrl);
194 loginConfig.setManualLogin(true);
195 LoginResult loginResult = (new EnterpriseConnection(loginConfig)).login(
196 username, password);
197
198 final ConnectorConfig metadataConfig = new ConnectorConfig();
199 metadataConfig.setServiceEndpoint(loginResult.getMetadataServerUrl());
200 metadataConfig.setSessionId(loginResult.getSessionId());
201 this.metadataConnection = new MetadataConnection(metadataConfig);
202 }
203
204}