Search code examples
githubgithub-api

correct steps of using the github/octonode API to upload and commit a zip


I am trying to push a zip file to github from a bitbucket pipeline using nodejs

Currently using octonode a nice github api wrapper.

What I am trying to figure out is the process/steps on how to do this.

I was successful in programmatically creating the initial commit

 var github = require('octonode');
 
 const client = github.client(access_token);
 
 const repo = client.repo('myuser/myrepo');
 
 repo.createContents('my.zip', 'Initial Commit', zipFile, (err, data, headers) => {
       
  }); 

But what to do next is where i end up in the weeds.

I was thinking, creating a branch off of master and then updating the zip file in that branch and then merge.

I can not seem to create a branch. I think i am suppose to use createReference, and suppose to use the sha of master??

By i can not find the sha of master.

repo.createReference('v1.0.0', 'sha', (err, data, headers) => {
      console.log('in createReference callback---err---->', err);
      console.log('in createReference callback---data---->', data);
      console.log('in createReference callback---headers---->', headers);
});

The question is, is this the correct method??

my end goal , is to programmatically push a new zip file to github.

Thanks for any help/suggestions


Solution

  • I am not sure if this is the best way, but this is how i got it to work

       const octokit = new Octokit.Octokit({
            auth: access_token
        });
    
    
        const base64Content = utilService.base64Encode(fs.readFileSync(`${zipFilePath}/${zipFileName}`));
    
        let newBranch = pluginVersionFromFile;
    
        /**
         * In order to create a new branch off of master, we first have to get the sha of master
         */
        const branches = await octokit.request(`GET /repos/myusername/${config.gitHubRepoName}/branches`, {
            owner: 'myusername',
            repo: config.gitHubRepoName
        });
    
        let masterSha;
        _.forEach(branches.data, function(branch) {
            if (branch.name === 'master') {
                masterSha = _.get(branch, 'commit.sha');
            }
            if (branch.name === newBranch) {
                newBranch = newBranch + '.' + moment().format('X');
            }
        });
    
        /**
         * Create a new branch off of master with the sha of master
         */
        await octokit.request(`POST /repos/myusername/${config.gitHubRepoName}/git/refs`, {
            owner: 'myusername',
            repo: config.gitHubRepoName,
            ref: `refs/heads/${newBranch}`,
            sha: masterSha
        });
    
        /**
         * In order to update the new version of the file, we now how to find the sha of the file we are going to update
         * that is not really straight forward.
         *
         * first we get all the commits for that file and iterate through them and get the Tree url and the tree
         * url will return the info needed to get the sha of the file.
         */
        const commits = await octokit.request(`GET /repos/myusername/${config.gitHubRepoName}/commits`, {
            owner: 'myusername',
            repo: config.gitHubRepoName,
            path: zipFileName
        });
    
        const treeURL = _.get(commits, 'data[0].commit.tree.url');
    
        /*
         * if there was a prior commit, we get the tree URL and from that we get the info about the file
         * that contains the sha
         */
        let sha;
        if (treeURL) {
            const treeResponse = await octokit.request(`GET ${treeURL}`);
            _.forEach(treeResponse.data.tree, function(tree) {
                if (tree.path === zipFileName) {
                    sha = tree.sha;
                }
            });
        }
    
        /*
         * update the file using the sha and the new branch name if file was already uploaded
         * only use the sha if this is not a new file that would have no commits
         */
        const updateFileData = {
            owner: 'myusername',
            repo: config.gitHubRepoName,
            path: zipFileName,
            message: `Plugin version ${pluginVersionFromFile}`,
            content: base64Content,
            branch: newBranch,
            sha:sha
        };
    
        if (!sha) {
            _.unset(updateFileData, 'sha');
        }
    
        await octokit.request(`PUT /repos/myusername/${config.gitHubRepoName}/contents/${zipFileName}`, updateFileData);
    
        /*
         * Create a PR
         */
        const prResponse = await octokit.request(`POST /repos/myusername/${config.gitHubRepoName}/pulls`, {
            owner: 'myusername',
            repo: config.gitHubRepoName,
            head: `myusername:${newBranch}`,
            base: 'master',
            title: `New Version of plugin ${newBranch}`
        });
        const prNumber = _.get(prResponse, 'data.number');
    
        /*
         * Merge the PR with the PR number from above
         */
        await octokit.request(`PUT /repos/myusername/${config.gitHubRepoName}/pulls/${prNumber}/merge`, {
            owner: 'myusername',
            repo: config.gitHubRepoName,
            pull_number: prNumber,
            commit_title:  `New Version of plugin ${newBranch}`
        });
    
        /*
        * Delete the branch after the merge is complete
        */
        //eslint-disable-next-line no-console
        console.log(' Deleting the branch ');
        await octokit.request(`DELETE /repos/myusername/${config.gitHubRepoName}/git/refs/heads/${newBranch}`, {
            owner: 'myusername',
            repo: config.gitHubRepoName
        });
    
        /**
         * Creating a release
         */
        await octokit.request(`POST /repos/myusername/${config.gitHubRepoName}/releases`, {
            owner: 'myusername',
            repo: config.gitHubRepoName,
            tag_name: pluginVersionFromFile,
            name: `Plugin Version  ${pluginVersionFromFile}`
        });