0

Everytime a new file is added to my server, I want that file to be added into BitBucket server. The server containing files is non-git and I want to know if this is possible programmatically using Bitbucket server rest api. Is it possible to do a remote commit and push to a certain branch using rest api? I took a look into the documentation and couldn't figure out which is the one for this scenario. Any help would be appreciated.

Bishal Paudel
  • 1,896
  • 2
  • 21
  • 28

1 Answers1

1

Here is a snippet of Python which uses the Bitbucket REST API:

#!/usr/bin/python

import os
import tempfile
import sys
import urllib2
import json
import base64
import logging
import re
import pprint
import requests
import subprocess

projectKey= "FW"
repoKey = "fw"
branch = "master"
pathToVersionProperties = "core/CruiseControl/CI_version.properties"
localVersionProperties = "CI_version.properties"
bitbucketBaseUrl = "https://bitbucket.company.com/rest/api/latest"
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s')

def checkPersonalAccessToken():
      try:
         os.environ["PAT"]
         logging.info("Detected Personal Access Token")
      except KeyError: 
         logging.error("Personal Access Token: $PAT env variable not set, update Jenkins master with correct environment variable")
         sys.exit(1)

def getJenkinsPropertiesFile():
    restEndpoint = "{}/projects/{}/repos/{}/raw/{}".format(bitbucketBaseUrl, projectKey, repoKey, pathToVersionProperties)
    logging.info("REST endpoint : {}".format(restEndpoint))
    request = urllib2.Request(restEndpoint)
    request.add_header("Authorization", "Bearer %s" % os.environ["PAT"])
    result = urllib2.urlopen(request).read()
    return result

def extractBuildNumber(propertiesString):
    m = re.search(r'BUILD_NUMBER=(\d+)', propertiesString)
    if m:
        logging.info("Current build number: {}".format(m.group(1)))
    else:
        logging.error("Failed to extract build number")
        sys.exit(1)
    return int(m.group(1))

def extractVersion(propertiesString):
    m = re.search(r'\nVERSION=(.*)', propertiesString)
    if m:
        logging.info("Current version: {}".format(m.group(1)))
    else:
        logging.error("Failed to extract version")
        sys.exit(1)
    return m.group(1)

def updateBuildNumber(propertiesString, currentBuild, newBuildNumber):
    buildString = "BUILD_NUMBER=%s" % currentBuild
    newBuildString = "BUILD_NUMBER=%s" % newBuildNumber
    return propertiesString.replace(buildString, newBuildString)
    
def getLatestCommit():
    restEndpoint = "{}/projects/{}/repos/{}/commits?path={}".format(bitbucketBaseUrl, projectKey, repoKey, pathToVersionProperties)
    logging.info("REST endpoint : {}".format(restEndpoint))

    request = urllib2.Request(restEndpoint)
    request.add_header("Authorization", "Bearer %s" % os.environ["PAT"])
    result = json.loads(urllib2.urlopen(request).read())
    latestCommit = result["values"][0]["displayId"]
    if(len(latestCommit) > 0):
       logging.info("Latest commit: {}".format(latestCommit))
    else:
        logging.error("Commit hash is empty, failed to retrieve latest commit")
        sys.exit(1)
    return latestCommit

def commitUpdatedBuildNumber(commitId, commitMessage, updateVersionProperties):
    restEndpoint = "{}/projects/{}/repos/{}/browse/{}".format(bitbucketBaseUrl, projectKey, repoKey, pathToVersionProperties)
    logging.info("REST endpoint : {}".format(restEndpoint))
    tempFile = tempfile.NamedTemporaryFile(delete=False)
    try:
        with open(tempFile.name, "w") as f:
            f.write(updateVersionProperties)
    finally:
        tempFile.close()
        f.close()
    curlCommand = "curl -s -S -X PUT -H \"Authorization: Bearer %s\" -F content=@%s -F \'message=%s\' -F branch=master -F sourceCommitId=%s %s" % (os.environ["PAT"], tempFile.name, commitMessage,commitId, restEndpoint)

    try:
        FNULL = open(os.devnull, 'w')
        subprocess.call(curlCommand, shell=True, stdout=FNULL)
    finally:
        logging.info("Committed version update")
        FNULL.close()

def writeCommitNumber(latestCommit):
    revisionFile = "%s/%s/%s" % (os.environ["HOME"],"git_revisions", "FW_11_CI_git.revision")
    logging.info("Revision file: {}".format(revisionFile))
    writeString = "%s=%s\n" % ("VERSION_PROPERTIES_REVISION", latestCommit)
    try:
        with open(revisionFile,"w") as f:
            f.write(writeString)
    finally:
        f.close()

checkPersonalAccessToken()
propertiesString = getJenkinsPropertiesFile()
currentBuildNumber = extractBuildNumber(propertiesString)
currentVersion = extractVersion(propertiesString)
newBuildNumber = currentBuildNumber + 1
newBuild = "%s%s%s" % (currentVersion,'B',newBuildNumber)
logging.info("New build number: {}".format(newBuild))
updatedPropertiesString = updateBuildNumber(propertiesString, currentBuildNumber, newBuildNumber)
commitMessage = "%s %s" % (newBuild, "Version Update")
latestCommit = getLatestCommit()
commitUpdatedBuildNumber(latestCommit, commitMessage, updatedPropertiesString)
writeCommitNumber(latestCommit)
eeijlar
  • 1,232
  • 3
  • 20
  • 53