Skip to content
Open
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
28 changes: 26 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>1.509.2</version>
<version>2.3</version>
<relativePath />
</parent>

<groupId>sic.software</groupId>
<name>Keychains and Provisioning Profiles Management</name>
<name>Keychains and Provisioning Profiles Management for Pipeline</name>
<description>This Jenkins plugin integrates a keychains and provisioning profiles managment for iOS and OSX projects build on a mac.</description>
<artifactId>kpp-management-plugin</artifactId>
<version>1.0.1-SNAPSHOT</version>
Expand Down Expand Up @@ -60,5 +60,29 @@
</plugin>
</plugins>
</build>

<dependencies>
<!-- dependencies on Jenkins Pipeline plugins -->
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-job</artifactId>
<version>1.14</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-cps</artifactId>
<version>1.14</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-step-api</artifactId>
<version>1.14</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-basic-steps</artifactId>
<version>2.0</version>
</dependency>
</dependencies>

</project>
90 changes: 49 additions & 41 deletions src/main/java/com/sic/plugins/kpp/KPPKeychainsBuildWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,35 @@

import com.sic.plugins.kpp.model.KPPKeychain;
import com.sic.plugins.kpp.model.KPPKeychainCertificatePair;
import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Hudson;
import hudson.model.*;
import hudson.tasks.BuildWrapper;
import hudson.tasks.BuildWrapperDescriptor;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jenkins.tasks.SimpleBuildWrapper;
import org.kohsuke.stapler.DataBoundConstructor;

/**
* Build wrapper for keychains
* @author mb
*/
public class KPPKeychainsBuildWrapper extends BuildWrapper {
public class KPPKeychainsBuildWrapper extends SimpleBuildWrapper implements Serializable {

private List<KPPKeychainCertificatePair> keychainCertificatePairs = new ArrayList<KPPKeychainCertificatePair>();
private boolean deleteKeychainsAfterBuild;
private boolean overwriteExistingKeychains;
private transient List<FilePath>copiedKeychains;

/**
* Constructor
* @param keychainCertificatePairs list of keychain certificate pairs
Expand All @@ -66,46 +67,47 @@ public KPPKeychainsBuildWrapper(List<KPPKeychainCertificatePair> keychainCertifi
this.deleteKeychainsAfterBuild = deleteKeychainsAfterBuild;
this.overwriteExistingKeychains = overwriteExistingKeychains;
}

/**
* Get if the keychain can be deleted after the build.
* @return true can be deleted, otherwise false
*/
public boolean getDeleteKeychainsAfterBuild() {
return deleteKeychainsAfterBuild;
}

/**
* Get if a current existing keychain with the same filename can be overwritten.
* @return true can be overwritten, otherwise false
*/
public boolean getOverwriteExistingKeychains() {
return overwriteExistingKeychains;
}

/**
* Get all keychain certificate pairs configured for this build job.
* @return list of keychain certificate pairs
*/
public List<KPPKeychainCertificatePair> getKeychainCertificatePairs() {
return keychainCertificatePairs;
}

@Override
public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
copyKeychainsToWorkspace(build);
return new EnvironmentImpl(keychainCertificatePairs);
public void setUp(Context context, Run<?, ?> run, FilePath filePath, Launcher launcher, TaskListener taskListener, EnvVars envVars) throws IOException, InterruptedException {
copyKeychainsToWorkspace(filePath);

Environment env = new EnvironmentImpl(keychainCertificatePairs, filePath);
env.buildEnvVars(context.getEnv());
context.setDisposer(new KPPKeychainsDisposer());
}

/**
* Copy the keychains configured for this build job to the workspace of the job.
* @param build the current build
* @param projectWorkspace the current build
* @throws IOException
* @throws InterruptedException
* @throws InterruptedException
*/
private void copyKeychainsToWorkspace(AbstractBuild build) throws IOException, InterruptedException {
FilePath projectWorkspace = build.getWorkspace();

private void copyKeychainsToWorkspace(FilePath projectWorkspace) throws IOException, InterruptedException {
Hudson hudson = Hudson.getInstance();
FilePath hudsonRoot = hudson.getRootPath();

Expand All @@ -124,18 +126,18 @@ private void copyKeychainsToWorkspace(AbstractBuild build) throws IOException, I
}
}
}

@Override
public DescriptorImpl getDescriptor() {
return (DescriptorImpl) super.getDescriptor();
}

/**
* Descriptor of the {@link KPPKeychainBuildWrapper}.
*/
@Extension
public static final class DescriptorImpl extends BuildWrapperDescriptor {

@Override
public boolean isApplicable(AbstractProject<?, ?> ap) {
return true;
Expand All @@ -146,22 +148,40 @@ public String getDisplayName() {
return Messages.KPPKeychainsBuildWrapper_DisplayName();
}
}


/**
* Disposer class for cleaning up copied keychains
*/
public class KPPKeychainsDisposer extends Disposer
{
@Override
public void tearDown(Run<?, ?> run, FilePath filePath, Launcher launcher, TaskListener taskListener) throws IOException, InterruptedException {
if (deleteKeychainsAfterBuild) {
for (FilePath keychainPath : copiedKeychains) {
keychainPath.delete();
}
}
}
}

/**
* Environment implementation that adds additional variables to the build.
* TODO: Does not need extend Environment anymore.
*/
private class EnvironmentImpl extends Environment {

private FilePath workspace;

private final List<KPPKeychainCertificatePair> keychainCertificatePairs;

/**
* Constructor
* @param keychainCertificatePairs list of keychain certificate pairs configured for this build job
*/
public EnvironmentImpl(List<KPPKeychainCertificatePair> keychainCertificatePairs) {
public EnvironmentImpl(List<KPPKeychainCertificatePair> keychainCertificatePairs, FilePath workspace) {
this.keychainCertificatePairs = keychainCertificatePairs;
this.workspace = workspace;
}

/**
* Adds additional variables to the build environment.
* @param env current environment
Expand All @@ -176,7 +196,7 @@ private Map<String, String> getEnvMap(Map<String, String> env) {
String password = keychain.getPassword();
String codeSigningIdentity = pair.getCodeSigningIdentity();
if (fileName!=null && fileName.length()!=0) {
String keychainPath = String.format("%s%s%s", env.get("WORKSPACE"), File.separator, fileName);
String keychainPath = String.format("%s%s%s", workspace, File.separator, fileName);
map.put(pair.getKeychainVariableName(), keychainPath);
}
if (password!=null && password.length()!=0)
Expand All @@ -187,22 +207,10 @@ private Map<String, String> getEnvMap(Map<String, String> env) {
}
return map;
}

@Override
public void buildEnvVars(Map<String, String> env) {
env.putAll(getEnvMap(env));
}

@Override
public boolean tearDown(AbstractBuild build, BuildListener listener)
throws IOException, InterruptedException {
if (deleteKeychainsAfterBuild) {
for (FilePath filePath : copiedKeychains) {
filePath.delete();
}
}
return true;
}

}
}
4 changes: 2 additions & 2 deletions src/main/java/com/sic/plugins/kpp/KPPNodeProperty.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ public String getProvisioningProfilesPath() {
* Get the {@link KPPNodeProperty}.
* @return node property
*/
public static KPPNodeProperty getCurrentNodeProperties() {
KPPNodeProperty property = Computer.currentComputer().getNode().getNodeProperties().get(KPPNodeProperty.class);
public static KPPNodeProperty getCurrentNodeProperties(Node node) {
KPPNodeProperty property = node.getNodeProperties().get(KPPNodeProperty.class);
if(property == null) {
property = Hudson.getInstance().getGlobalNodeProperties().get(KPPNodeProperty.class);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,30 +26,30 @@

import com.sic.plugins.kpp.model.KPPProvisioningProfile;
import com.sic.plugins.kpp.provider.KPPProvisioningProfilesProvider;
import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Hudson;
import hudson.model.Node;
import hudson.model.*;
import hudson.remoting.VirtualChannel;
import hudson.tasks.BuildWrapper;
import hudson.tasks.BuildWrapperDescriptor;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jenkins.tasks.SimpleBuildWrapper;
import org.kohsuke.stapler.DataBoundConstructor;

/**
* Build wrapper for provisioning profiles
* @author Michael Bär
*/
public class KPPProvisioningProfilesBuildWrapper extends BuildWrapper {
public class KPPProvisioningProfilesBuildWrapper extends SimpleBuildWrapper implements Serializable {

private List<KPPProvisioningProfile> provisioningProfiles;
private boolean deleteProfilesAfterBuild;
Expand Down Expand Up @@ -93,41 +93,43 @@ public boolean getDeleteProfilesAfterBuild() {
public boolean getOverwriteExistingProfiles() {
return overwriteExistingProfiles;
}

@Override
public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
copyProvisioningProfiles(build);
return new KPPProvisioningProfilesBuildWrapper.EnvironmentImpl(provisioningProfiles);
public void setUp(Context context, Run<?, ?> run, FilePath filePath, Launcher launcher, TaskListener taskListener, EnvVars envVars) throws IOException, InterruptedException {
copyProvisioningProfiles(filePath, envVars.get("NODE_NAME"));
EnvironmentImpl env = new KPPProvisioningProfilesBuildWrapper.EnvironmentImpl(provisioningProfiles);
env.buildEnvVars(context.getEnv());
context.setDisposer(new KPPProvisioningProfilesDisposer());
}

/**
* Copy the provisioning profiles configured for this job to the mobile provisioning profile path of the node or master, where the job is executed.
* @param build current build
* @param projectWorkspace current workspace
* @param nodeStr Name of the execution node
* @throws IOException
* @throws InterruptedException
*/
private void copyProvisioningProfiles(AbstractBuild build) throws IOException, InterruptedException {
private void copyProvisioningProfiles(FilePath projectWorkspace, String nodeStr) throws IOException, InterruptedException {

Hudson hudson = Hudson.getInstance();
FilePath hudsonRoot = hudson.getRootPath();
VirtualChannel channel;
String toProvisioningProfilesDirectoryPath = null;
String buildOn = build.getBuiltOnStr();

String buildOn = nodeStr;
boolean isMaster = false;
if (buildOn==null || buildOn.isEmpty()) {
if (buildOn.equals("master")) {
// build on master
FilePath projectWorkspace = build.getWorkspace();
channel = projectWorkspace.getChannel();
toProvisioningProfilesDirectoryPath = KPPProvisioningProfilesProvider.getInstance().getProvisioningProfilesPath();
isMaster = true;
} else {
// build on slave
Node node = build.getBuiltOn();
Node node = hudson.getNode(nodeStr);;
channel = node.getChannel();
KPPNodeProperty nodeProperty = KPPNodeProperty.getCurrentNodeProperties();
KPPNodeProperty nodeProperty = KPPNodeProperty.getCurrentNodeProperties(node);
if (nodeProperty != null) {
toProvisioningProfilesDirectoryPath = KPPNodeProperty.getCurrentNodeProperties().getProvisioningProfilesPath();
toProvisioningProfilesDirectoryPath = KPPNodeProperty.getCurrentNodeProperties(node).getProvisioningProfilesPath();
}
}

Expand Down Expand Up @@ -185,7 +187,22 @@ public String getDisplayName() {
return Messages.KPPProvisioningProfilesBuildWrapper_DisplayName();
}
}


/**
* Disposer class for cleaning up copied keychains
*/
public class KPPProvisioningProfilesDisposer extends Disposer
{
@Override
public void tearDown(Run<?, ?> run, FilePath filePath, Launcher launcher, TaskListener taskListener) throws IOException, InterruptedException {
if (deleteProfilesAfterBuild) {
for (FilePath profilePath : copiedProfiles) {
profilePath.delete();
}
}
}
}

/**
* Environment implementation that adds additional variables to the build.
*/
Expand Down Expand Up @@ -220,18 +237,6 @@ private Map<String, String> getEnvMap() {
public void buildEnvVars(Map<String, String> env) {
env.putAll(getEnvMap());
}

@Override
public boolean tearDown(AbstractBuild build, BuildListener listener)
throws IOException, InterruptedException {
if (deleteProfilesAfterBuild) {
for (FilePath filePath : copiedProfiles) {
filePath.delete();
}
}
return true;
}

}

}
Expand Down