Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/snyk-security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
# Runs Snyk Code (SAST) analysis and uploads result into GitHub.
# Use || true to not fail the pipeline
- name: Snyk Code test
run: snyk code test --sarif > snyk-code.sarif # || true
run: snyk code test -d --sarif > snyk-code.sarif # || true

# Runs Snyk Open Source (SCA) analysis and uploads result to Snyk.
- name: Snyk Open Source monitor
Expand Down
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
<textarea class="form-control" rows="10" id="json-result" readonly></textarea>
<button type="button" class="btn btn-outline" href="#" onclick="copyToClipboard(event)">Copy</button>
<button type="button" class="btn btn-outline" href="#" onclick="downloadFile(event)">Download</button>
<button type="button" class="btn btn-outline" href="#" onclick="createProjectPR(event)">Create Pull Request</button>
</div>

</body>
Expand Down
214 changes: 214 additions & 0 deletions js/formDataToJson.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ async function createCodeJson(data) {
delete data.submit;
const codeJson = await populateCodeJson(data);

window.gh_api_key = data['gh_api_key']
console.log("TEST")
console.log(window.gh_api_key)

const jsonString = JSON.stringify(codeJson, null, 2);
document.getElementById("json-result").value = jsonString;
}
Expand All @@ -91,6 +95,215 @@ async function copyToClipboard(event){
document.execCommand("copy")
}

const NEW_BRANCH = 'code-json-branch' + Math.random().toString(36).substring(2, 10);

function getOrgAndRepoArgsGitHub(url)
{
const pattern = /https:\/\/github\.com\/([^\/]+)\/([^\/]+)/;
const match = url.match(pattern);

if(match)
{
const owner = match[1];
const repo = match[2];
return {owner,repo};
}
else
{
throw new Error('Invalid URL!');
}
}


async function createBranchOnProject(projectURL, token)
{
const {owner, repo} = getOrgAndRepoArgsGitHub(projectURL);

const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/git/refs/heads/main`,
{
method: 'GET',
headers: {
'Authorization': 'token '.concat(token),
},
}
);

const data = await response.json();

if (response.ok)
{
const sha = data.object.sha;

const createBranchApiUrl = `https://api.github.com/repos/${owner}/${repo}/git/refs`;

// Create the new branch from the base branch
const newBranchResponse = await fetch(createBranchApiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `token ${token}`,
},
body: JSON.stringify({
ref: `refs/heads/${NEW_BRANCH}`, // Name of the new branch
sha: sha, // SHA of the base branch (main)
}),
});

const newBranchData = await newBranchResponse.json();

if ( newBranchResponse.ok )
{
console.log('New branch created successfully: ', newBranchData);
return true;
}
else
{
Comment thread
IsaacMilarky marked this conversation as resolved.
console.error('Error creating new branch: ', newBranchData);
alert("Failed to create branch on project! Error code: " + newBranchResponse.status + ". Please check API Key permissions and try again.")
return false;
}
}
else
{
console.error('Error fetching base branch info:', data);
Comment thread
IsaacMilarky marked this conversation as resolved.
alert('Error fetching base branch info:', data);
return false;
}
}


async function addFileToBranch(projectURL, token, codeJSONObj)
{
const {owner, repo} = getOrgAndRepoArgsGitHub(projectURL);
const FILE_PATH = 'code.json'
const createFileApiUrl = `https://api.github.com/repos/${owner}/${repo}/contents/${FILE_PATH}`;
const encodedContent = btoa(codeJSONObj);
console.log("Content: ", encodedContent);
console.log("Branch: ", NEW_BRANCH);

const response = await fetch(createFileApiUrl,
{
method: 'PUT',
headers: {
'Accept': 'application/vnd.github+json',
'Authorization': 'Bearer '.concat(token),
'X-GitHub-Api-Version': "2022-11-28"
},
body: JSON.stringify({
message: "Add codejson to project",
committer: {
name: "codejson-generator form site",
email: "opensource@cms.hhs.gov"
},
content: encodedContent,
branch: NEW_BRANCH,
}),
}
);

const data = await response.json()

if ( response.ok )
{
console.log('File added successfully: ', data);
return true;
}
else
{
console.error('Error adding file: ', data);
alert("Failed to add file on project! Error code: " + response.status + ". Please check API Key permissions and try again.")
return false;
}
}

async function createPR(projectURL, token)
{
const {owner, repo} = getOrgAndRepoArgsGitHub(projectURL);
const createPrApiUrl = `https://api.github.com/repos/${owner}/${repo}/pulls`;
const response = await fetch(createPrApiUrl,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'token '.concat(token),
'X-GitHub-Api-Version': "2022-11-28"
},
body: JSON.stringify({
title: "Add code.json to Project",
body: "Add generated code.json file to project. Code.json was generated via codejson-generator form site.",
head: NEW_BRANCH,
base: 'main',

}),
}
);

const data = await response.json();

if (response.ok)
{
console.log('Pull request created successfully: ', data);
return true;
}
else
{
console.error("Error creating PR!: ", data);
alert("Failed to create PR on project! Error code: " + response.status + ". Please check API Key permissions and try again.")
return false;
}
}

// Creates PR on requested project
async function createProjectPR(event){
event.preventDefault();

var textArea = document.getElementById("json-result");//Step 1
var codeJSONObj = JSON.parse(textArea.value)

if('gh_api_key' in window)
{
var apiKey = window.gh_api_key;

if ('repositoryURL' in codeJSONObj)
{
var prCreated = false;
//Step 1
const branchCreated = await createBranchOnProject(codeJSONObj.repositoryURL,apiKey);
if (branchCreated)
{
const fileAdded = await addFileToBranch(codeJSONObj.repositoryURL, apiKey, textArea.value);

if (fileAdded)
{
prCreated = await createPR(codeJSONObj.repositoryURL, apiKey);
if(prCreated)
{
console.log("PR successfully created!");
alert("PR has been created!");
}
}
}
else
{
console.error("Could not create branch on requested repository with the requested API key!");
alert("Could not create branch on requested repository with the requested API key!");
}
}
else
{
console.error("No URL found!");
alert("No URL given for project! Please provide project URL in repositoryURL text box");
}

}
else
{
console.error("No API key found!");
alert("No API Key in submitted data! Please provide an API key");
}
//console.log(codeJSONObj)
}
Comment thread
IsaacMilarky marked this conversation as resolved.

Comment thread
IsaacMilarky marked this conversation as resolved.
// Triggers local file download
async function downloadFile(event) {
event.preventDefault();
Expand All @@ -112,3 +325,4 @@ async function downloadFile(event) {
window.createCodeJson = createCodeJson;
window.copyToClipboard = copyToClipboard;
window.downloadFile = downloadFile;
window.createProjectPR = createProjectPR;
16 changes: 16 additions & 0 deletions js/generateFormComponents.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,20 @@ async function createFormComponents() {

components = createAllComponents(jsonData);

//Form text box to input GitHub API Key
components.push({
"label": "GitHub API Key (optional)",
Comment thread
IsaacMilarky marked this conversation as resolved.
Comment thread
IsaacMilarky marked this conversation as resolved.
"disableSortingAndFiltering": false,
"tableView": true,
"key": "gh_api_key",
"type": "password",
"input": true,
"description": "Generate a Github API Key from here: https://github.com/settings/tokens/new .\n\
The token should have these permissions: \n\
- Contents: read & write \n- Workflows: read & write\
- Pull requests: read & write"
});

// Add submit button to form
components.push({
type: "button",
Expand All @@ -312,6 +326,8 @@ async function createFormComponents() {
tableView: false,
});



console.log(components);

return components;
Expand Down
Loading