Obtain all work items from Azure DevOps that have been merged into a branch via JavaScript

Viewed 984

The idea

I am currently developing a 'release notes' application using NodeJS that calls various Azure DevOps REST API endpoints to obtain work items based on a specific tag.

What I have right now

What I have at the moment works like this;

  • Some work items on Azure DevOps are (custom) tagged with v1.1.
  • The JS functions I wrote, fetch all work items that match the given v1.1 tag.
  • A wiki entry is created using generated markdown, showing a breakdown of each work item (format not important to the question).
/**
 * Function used to fetch initial work items from Azure DevOps that match the provided release number
 * @param {String} releaseNumber - the given release number
 * @returns {Array} workItems - the initial work items fetched from Azure DevOps
 */
async function fetchWorkItems(releaseNumber) {
    console.log('\nFetching work items for given release number...');
    let response;
    try {
        response = await axios.post('https://dev.azure.com/myTestOrg/myTestProject/_apis/wit/wiql?api-version=6', {
            query: `SELECT [State], [Title] FROM WorkItems WHERE [Tags] CONTAINS '${releaseNumber}'`
        }, {
            headers: {
                Authorization: getAuthToken()
            }
        });
        console.log(`Found ${response.data.workItems.length} work item(s).`);
    } catch (e) {
        console.error('\nUnable to fetch work items. See below error message');
        console.error(e.message);
        process.exit(1);
    }

    return response.data.workItems;
}

/**
 * Function used to fetch the details for a given array of work items
 * @param {Array} givenWorkItems - given array of work items to fetch the details for
 * @returns {Array} details - the initial work items fetched from Azure DevOps
 */
async function fetchWorkItemDetails(givenWorkItems) {
    console.log('\nFetching further details for the given work item(s)...');
    const returnData = [];
    let response;

    for (const item of givenWorkItems) {
        try {
            // eslint-disable-next-line no-await-in-loop
            response = await axios.get(item.url, {
                headers: {
                    Authorization: getAuthToken()
                }
            });
        } catch (e) {
            console.error('\nUnable to fetch details for given work items. See below error message');
            console.error(e.message);
            process.exit(1);
        } finally {
            returnData.push({
                type: response.data.fields['System.WorkItemType'],
                title: response.data.fields['System.Title'],
                url: response.data._links.html.href
            });
        }
    }

    console.log(`Found details for ${returnData.length} work item(s).`);
    return returnData;
}

...

/**
 * Function used to create the wiki entry based on a given markup string
 * @param {String} releaseNumber - the given release number
 * @param {String} givenMarkdown - given array of work items to fetch the details for
 * @returns {undefined} nothing
 */
async function createWiki(releaseNumber, givenMarkdown) {
    console.log('\nCreating wiki entry...');
    try {
        await axios.put(`https://dev.azure.com/myTestOrg/myTestProject/_apis/wiki/wikis/myTestProject.wiki/pages?path=/Releases/Release%20${releaseNumber}&api-version=6.0`, {
            content: givenMarkdown
        }, {
            headers: {
                Authorization: getAuthToken()
            }
        });
    } catch (e) {
        console.error('\nUnable to create wiki entry for given markdown. See below error message');
        console.error(e.message);
        process.exit(1);
    } finally {
        console.log('Successfully created wiki entry.');
    }
}

...

const workItems = await fetchWorkItems(releaseNumber);
const workItemDetails = await fetchWorkItemDetails(workItems);
const formattedDetails = formatWorkItemDetails(workItemDetails);
const generatedMarkup = generateMarkdown(formattedDetails);
await createWiki(releaseNumber, generatedMarkup);
...

// creates the wiki based on the given `releaseNumber` variable
// (which is the workitem tag of `v1.1` in our case)

Why what I have right now is not good enough

This application works fine if I remember to tag the work item with the correct v1.1 tag - but in case I do not, this program will not pick up the fact that a specific ticket (and associated branch/ code) has been merged in and has been/ is awaiting release - I hope this makes sense?

The question

Is there a way for me to fetch all work items (regardless of tag) that have been merged into a branch (or a git tag) via the REST api?

I noticed there is also a azure-devops-node-api npm package which may be suitable but I have no idea if what I'm trying to achieve is possible.

Why can't I use XYZ

I saw this project https://marketplace.visualstudio.com/items?itemName=richardfennellBM.BM-VSTS-XplatGenerateReleaseNotes which when I tried it, seemed to work fine but won't suit my needs as;

  1. I do not use the dedicated release section in DevOps, I just have several application pipelines which contain gated steps used to deploy various apps to QA/ Staging/ Production environments
  2. I share the same release number across several Azure DevOps pipelines (and the above solution (I found) works best for a single pipeline)
  3. I don't want to combine several application pipelines into a single master one unless I really need to.
1 Answers

Note: I'm not going to write how to do it java script because I'm not js expert... the idea is rest api, so the language it doesn't matter.

  1. Get all the work items you want to check, you can do it with your current api, just in the query remove the Tags. (you can narrow the results by specify date, etc.)

  2. You need to get also the PRs that linked to the work items, this data not available with the WIQL api, so - after you have the work items IDs you need call the Work Items - Get Work Items Batch api (or loop each one and perform Work Items - Get Work Item api) and add the $expand in the body/url with relations/all value for get the linked PRs.

  3. After you have work items with their linked PRs (in the above api response you will see relations section and if inside it the url is with vstfs:///Git/PullRequestId so it's PR), you need to check if the PR is merged to the master branch. how? with the Pull Requests - Get Pull Request api, now, check the target branch of this PR and check if completed (merged).

Related