Webhooks Cookbook - GitHub
The majority of webhook use cases for GitHub stem from changes being pushed to the repository. The most common example being building FlexDeploy projects from a repository push event.
Adding Webhooks in GitHub
Adding webhooks to Github is covered in official GitHub documentation
Incoming
Provider Match
This provider match script for GitHub validates based on the secret configured on your GitHub webhook. This script is largely based around GitHub's Hmac encryption. Note that using the secret is optional but it is strongly recommended to make use of it.
// perform checks and functions to ensure an incoming message is valid and matches this provider
LOG.fine("Evaluating GitHub for incoming message");
def match = false;
def gitHubSecret = 'REPLACE_ME';
// validating based on GitHub secret
if (HTTP_HEADERS['user-agent'] && HTTP_HEADERS['user-agent'].toLowerCase().contains('github-hookshot'))
{
//generate hmac string, be sure to replace with your github secret
def HMAC_RESULT = HMAC.generateHmacSHA1(FLX_PRISTINE_PAYLOAD, gitHubSecret);
def RECEIVED_HMAC = HTTP_HEADERS['x-hub-signature'];
match = RECEIVED_HMAC && RECEIVED_HMAC.contains(HMAC_RESULT);
}
LOG.fine("GitHub provider is a match: ${match}");
return match;
Building Projects and/or Packages from a Push Event
The below function builds both Projects and Packages from a GitHub push event. You can optionally send a projectId query parameter to limit the build results to a specific project.
//Execute FLEXDEPLOY functions on an incoming webhook message
def functionName = "BuildGitHub";
LOG.info("Running function: ${functionName}");
//Find and build projects from the payload
//If the QUERY_PARAMS include a projectId that single project will be built instead
//Lastly, the 3rd argument, when true, will create streams on the projects when the branch does not exist
GITHUB.buildProjects(PAYLOAD, QUERY_PARAMS, true);
GITHUB.buildPackages(PAYLOAD, QUERY_PARAMS, true);
Create a FlexDeploy Project when a GitHub repository is created
This sample GitHub function script creates a FlexDeploy SCM instance and project with the assumption it will be triggered only from a GitHub create repo event. The function will first use the repository name to create an SCM Instance with the given name and git url. Next the function creates and configures the project to use the newly created SCM Instance. Finally the function will update the necessary properties on the project. In this example we are creating an EBS project. You will need to replace certain values in the function with specific Ids from your FlexDeploy environment.
Note that this webhook is created at the User/Org level in GitHub since it doesnt apply to any specific repository.
import flexagon.fd.model.pojos.rest.topology.integrations.SCMInstancePojo;
import flexagon.fd.model.pojos.rest.properties.PropertyValuePojo;
import flexagon.fd.model.pojos.rest.project.*;
import flexagon.fd.core.enums.SCMTypeEnum;
import flexagon.fd.core.enums.ProjectTypeEnum;
import flexagon.fd.model.pojos.rest.properties.PropertyValuePojo;
//Execute FLEXDEPLOY functions on an incoming webhook message
def functionName = "myFunction";
LOG.info("Running function: ${functionName}");
def CEMLI_ID= PAYLOAD.repository.name;
LOG.info("CEMLI_ID: " + CEMLI_ID);
def scmInstance = new SCMInstancePojo();
scmInstance.setInstanceCode(CEMLI_ID);
scmInstance.setInstanceName(CEMLI_ID);
scmInstance.setScmType("GIT");
def props = [new PropertyValuePojo("FDGIT_URL", PAYLOAD.repository.git_url), new PropertyValuePojo("FDGIT_USER", "flexagon9"), new PropertyValuePojo("FDGIT_PASSWORD", null, 12345L)];
scmInstance.setProperties(props);
LOG.info(scmInstance.toString());
def scmId = FLEXDEPLOY.createSCMInstance(scmInstance);
LOG.info(scmId.toString());
def proj = new ProjectPojo();
proj.setProjectName(CEMLI_ID);
proj.setApplicationId(880708L);
proj.setPartialDeployment(true);
proj.setProjectType(ProjectTypeEnum.EBS);
proj.setScmType(SCMTypeEnum.GIT);
def buildInfo = new ProjectBuildInfo();
def deployInfo = new ProjectDeployInfo();
buildInfo.setWorkflowId(566261L);
buildInfo.setInstanceId(566269L);
deployInfo.setWorkflowId(566260L);
deployInfo.setInstanceIds([566269L]);
proj.setBuildInfo(buildInfo);
proj.setDeployInfo(deployInfo);
proj.setMainStreamName("master");
def projectSCMPojo = new ProjectSCMPojo();
def projectSCMConfig = new ProjectSCMConfig();
projectSCMConfig.setInstanceId(scmId);
def scmConfigs = [new ProjectSCMConfigValue("BranchScript", "StreamName"), new ProjectSCMConfigValue("TagScript", "ProjectVersion"), new ProjectSCMConfigValue("SparseCheckoutFoldersScript", "\"XXHR\""), new ProjectSCMConfigValue("CheckoutFolderScript", "ProjectName")];
projectSCMConfig.setConfigValues(scmConfigs);
projectSCMConfig.setSourceNumber(1);
projectSCMPojo.setSources([projectSCMConfig]);
proj.setScmConfiguration(projectSCMPojo);
def projId = FLEXDEPLOY.createProject(proj);
LOG.info(projId.toString());
LOG.info("Updating Project Properties.");
def properties = [
new PropertyValuePojo("FDEBS_APPLICATION_SHORT_NAME", "XXHR"),
new PropertyValuePojo("FDEBS_JAVA_ROOT_SOURCE_DIR", "java"),
new PropertyValuePojo("FDEBS_JAVA_ROOT_DESTINATION_DIR", "\$XXHR_TOP/java"),
new PropertyValuePojo("FDEBS_LOAD_JAVA_ROOT_DESTINATION_DIR", "\$XXHR_TOP/java"),
new PropertyValuePojo("FDEBS_AOL_ROOT_DESTINATION_DIR", "\$XXHR_TOP/patch/115/import/us"),
new PropertyValuePojo("FDEBS_FILE_PERMISSIONS", "755"),
new PropertyValuePojo("FD_PARTIAL_FILE_EXCLUDES", "*/misc/*")
];
FLEXDEPLOY.updateProjectProperties(projId, properties);
Outgoing
- style