package org.jenkinsci.plugins.p4.tasks; import hudson.AbortException; import hudson.EnvVars; import hudson.FilePath; import hudson.model.Item; import hudson.model.Run; import hudson.model.TaskListener; import org.jenkinsci.plugins.p4.build.ExecutorHelper; import org.jenkinsci.plugins.p4.build.NodeHelper; import org.jenkinsci.plugins.p4.client.ClientHelper; import org.jenkinsci.plugins.p4.client.ConnectionHelper; import org.jenkinsci.plugins.p4.credentials.P4BaseCredentials; import org.jenkinsci.plugins.p4.workspace.Workspace; import java.io.IOException; import java.io.Serializable; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.concurrent.TimeUnit; import java.util.logging.Logger; public abstract class AbstractTask implements Serializable { private static final long serialVersionUID = 1L; private static Logger logger = Logger.getLogger(AbstractTask.class.getName()); private final P4BaseCredentials credential; private final TaskListener listener; private Workspace workspace; @Deprecated public AbstractTask(String credential, TaskListener listener) { this.credential = ConnectionHelper.findCredential(credential); this.listener = listener; } public AbstractTask(String credential, Item project, TaskListener listener) { this.credential = ConnectionHelper.findCredential(credential, project); this.listener = listener; } public AbstractTask(String credential, Run run, TaskListener listener) { this.credential = ConnectionHelper.findCredential(credential, run); this.listener = listener; } /** * Set the workspace used for the task. * * Often AbstractTask#setEnvironment() is used to expand the variables in the workspace before set * * @param workspace Perforce Workspace type */ public void setWorkspace(Workspace workspace) { this.workspace = workspace; } protected ClientHelper getxxxConnection() { ClientHelper p4 = new ClientHelper(credential, listener, workspace); return p4; } /** * Implements the Perforce task to retry if necessary * * @param p4 Perforce connection helper * @return Task object * @throws Exception push up stack */ public abstract Object task(ClientHelper p4) throws Exception; public P4BaseCredentials getCredential() { return credential; } public TaskListener getListener() { return listener; } public Workspace setEnvironment(Run<?, ?> run, Workspace wsType, FilePath buildWorkspace) throws IOException, InterruptedException { Workspace ws = (Workspace) wsType.clone(); // Set Node environment EnvVars envVars = run.getEnvironment(listener); String nodeName = NodeHelper.getNodeName(buildWorkspace); envVars.put("NODE_NAME", envVars.get("NODE_NAME", nodeName)); String executor = ExecutorHelper.getExecutorID(buildWorkspace); envVars.put("EXECUTOR_NUMBER", envVars.get("EXECUTOR_NUMBER", executor)); ws.setExpand(envVars); // Set workspace root (check for parallel execution) String root = buildWorkspace.getRemote(); if (root.contains("@")) { root = root.replace("@", "%40"); } ws.setRootPath(root); if (ws.isPinHost()) { String hostname = getHostName(buildWorkspace); ws.setHostName(hostname); } else { ws.setHostName(""); } return ws; } /** * Remote execute to find hostname. * * @param buildWorkspace Jenkins remote path * @return Hostname */ private static String getHostName(FilePath buildWorkspace) { try { HostnameTask task = new HostnameTask(); String hostname = buildWorkspace.act(task); return hostname; } catch (Exception e) { return ""; } } public String getClientName() { return workspace.getFullName(); } public String getSyncID() { return workspace.getSyncID(); } protected Workspace getWorkspace() { return workspace; } protected boolean checkConnection(ClientHelper p4) { p4.log("\nP4 Task: establishing connection."); // test server connection if (!p4.isConnected()) { p4.log("P4: Server connection error: " + getCredential().getP4port()); return false; } p4.log("... server: " + getCredential().getP4port()); // test node hostname String host; try { host = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { host = "unknown"; } p4.log("... node: " + host); return true; } protected Object tryTask() throws AbortException { try (ClientHelper p4 = new ClientHelper(credential, listener, workspace)) { // Check for an abort if (p4.hasAborted()) { String msg = "P4: Previous Task Aborted!"; logger.warning(msg); p4.log(msg); throw new AbortException(msg); } // Check connection (might be on remote slave) if (!checkConnection(p4)) { String msg = "P4: Unable to connect."; logger.warning(msg); p4.log(msg); throw new AbortException(msg); } // Run the task and retry as required return retryTask(p4); } catch (Exception e) { String msg = "P4: Task Exception: " + e.getMessage(); logger.severe(msg); throw new AbortException(msg); } } private Object retryTask(ClientHelper p4) throws Exception { int t = 0; Exception last = null; while (t <= p4.getRetry()) { t++; try { // Run the task Object result = task(p4); if (p4.hasAborted()) { String msg = "P4: Task Aborted!"; logger.warning(msg); p4.log(msg); throw new AbortException(msg); } return result; } catch (Exception e) { last = e; String msg = "P4 Task: attempt: " + t; logger.severe(msg); p4.log(msg); // back off n^2 seconds, before retry try { TimeUnit.SECONDS.sleep(t ^ 2); } catch (InterruptedException e2) { Thread.currentThread().interrupt(); } } } throw new Exception(last); } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#8 | 24428 | Paul Allen |
Merging using p4-jenkins_main>dev @24406 - @24411 |
||
#7 | 23690 | Paul Allen | Cleanup P4Task: use Closable and not a call to p4.disconnect() | ||
#6 | 23689 | Paul Allen | Cleanup P4Task: Combined Workspace setup | ||
#5 | 23688 | Paul Allen | Cleanup P4Task: Pass workspace to ClientHelper | ||
#4 | 23687 | Paul Allen | Cleanup P4Task: Set Workspace | ||
#3 | 23686 | Paul Allen | Cleanup P4Task: Move setters into constructor. | ||
#2 | 23685 | Paul Allen | Copy main -> dev | ||
#1 | 20641 | Paul Allen | Copy main -> dev (jenkinsci/p4-plugin) | ||
//guest/perforce_software/p4jenkins/main/src/main/java/org/jenkinsci/plugins/p4/tasks/AbstractTask.java | |||||
#16 | 20308 | Paul Allen |
P4Groovy (experimental) Get a P4 object in groovy. Supporting basic functions: ’run’ (to run perforce commands), ‘fetch’ and ‘save’ (to access Perforce specs). |
||
#15 | 20245 | Paul Allen |
Don't disconnect after an abort. Don't disconnect from the P4 server immediately after an abort is detected. JENKINS-37487 @stuartr |
||
#14 | 20179 | Paul Allen | Javadoc fixes for java 8 builds. | ||
#13 | 19593 | Paul Allen | More minor fixes to satisfy FindBugs Analysis. | ||
#12 | 16815 | Paul Allen |
Enable early binding for CHARSET Expose CHARSET to AbstractTask to allow the charset to be set at the point the client workspace is set as current in ClientHelper. |
||
#11 | 16514 | Paul Allen |
Unshelve and resolve build step. Implements a classic Jenkins Build step (i.e. not Workflow). Must provide a shelf change number and resolve options. The shelf change number supports variable expansion ${VAR}. |
||
#10 | 15656 | Paul Allen |
Updated credentials to extend BaseStandardCredentials. Allows users to set the ID at creation. JENKINS-29702 |
||
#9 | 15430 | Paul Allen |
Trap User Abort and stop Perforce. Uses the ‘tick’ function on Progress to check if the Thread has been interrupted. If a user aborts the build then the Perforce connection is dropped at the next tick. JENKINS-26650 |
||
#8 | 15293 | Paul Allen |
Add retry attempts to Perforce Tasks. If a task fails due to an exception then the task will retry based on the value specified in the connection Credential. |
||
#7 | 13700 | Paul Allen | minor tidy up. | ||
#6 | 13681 | Paul Allen |
Abstracted Expand class from Workspace. Added support for Label variable expansion in the name and description. |
||
#5 | 13604 | Paul Allen | Improved error handling and fixed test case issue. | ||
#4 | 13603 | Paul Allen | Improved Error for Publish step when connection is down. | ||
#3 | 12976 | Paul Allen | Improved logging to include 'actual' Perforce command. | ||
#2 | 12953 | Paul Allen |
Update logging to support expand/collapse divs. - Additional Publish logging |
||
#1 | 11334 | Paul Allen |
Remote slave support for Publish Perforce Publish commands need to be executed from the remote slave. - Includes refactoring into task package |