У меня есть приложение для весенней загрузки, и я хотел бы иметь страницу, на которой перечислены как номер последней сборки, так и список изменений, которые она содержит. Я использую Rally, git и Jenkins, но, если не считать ручного обновления таблицы HTML или db, мне интересно, нет ли более автоматизированного способа получить эту информацию?

Может ли кто-нибудь поделиться своим подходом к размещению этой информации на веб-странице из приложения?

0
sonoerin 12 Май 2016 в 18:51

2 ответа

Лучший ответ

Вы можете отслеживать успешные и неудачные сборки Jenkins от коммитов git до связанных артефактов CA AgileCentral (Rally), используя Соединитель Git и плагин Jenkins, если оба указывают на тот же репозиторий, и в коммите в git упоминается FormattedID связанного артефакта.

Вот пример Java, основанный на Rally API Toolkit для Java. Независимо от выбора набора инструментов, языка и т. Д. Это основной WS API. объектная модель, обеспечивающая доступ к этим данным. Я ограничил запрос сборки по CreationDate. Среди других полей объекта Build я получаю коллекцию наборов изменений. Каждый элемент этой коллекции является ссылкой на объект набора изменений. Коннектор Git создает объекты Changesets в CA Agile Central (Rally). Каждый объект набора изменений имеет поле коллекции Artfacts и поле коллекции изменений. Каждый элемент коллекции Artifacts является ссылкой на артефакт Rally, например пользовательская история, дефект. Выбирая PathAndFilename для каждого объекта Change, вы получаете связанный исходный файл. Теперь мы можем отследить неудачную сборку до конкретного коммита, файла и пользовательской истории.

Это снимок экрана с вывода консоли, созданного приведенным ниже кодом Java. В конце концов, вы можете захотеть представить данные в более привлекательном виде. Этот пример показывает только то, что сборки и фиксации можно отследить до пользовательских историй или дефектов через WS API.

Для гидратации коллекций в WS API часто требуются отдельные запросы. Поскольку данные Build и Cangesets могут быть большими, эти запросы связываются по некоторым критериям, например CreationDate сделает это быстрее.

enter image description here

public class GetBuildData {

    public static void main(String[] args) throws Exception {

        String host = "https://rally1.rallydev.com";
        String apiKey = "_abc123"; 
        String applicationName = "NickM:GetBuildData";
        String workspaceRef = "/workspace/12345";
        String projectRef = "/project/1346";

        RallyRestApi restApi = null;
        try {
            String dateString = "2016-05-12";
            restApi = new RallyRestApi(new URI(host),apiKey);
            restApi.setApplicationName(applicationName);
            QueryRequest buildRequest = new QueryRequest("Build");
            buildRequest.setFetch(new Fetch("Status,Message,Start,Uri,Changesets"));
            buildRequest.setQueryFilter(new QueryFilter("CreationDate", ">", dateString));
            buildRequest.setWorkspace(workspaceRef);
            buildRequest.setProject(projectRef);
            QueryResponse buildResponse = restApi.query(buildRequest);
            for (int i=0; i<buildResponse.getTotalResultCount();i++){
                JsonObject buildObj = buildResponse.getResults().get(i).getAsJsonObject();
                System.out.println("Build Status: " + buildObj.get("Status") +
                        "\n Build Message: " + buildObj.get("Message") +
                        "\n Build Start:   " + buildObj.get("Start") +
                        "\n Build Uri:     " + buildObj.get("Uri"));
                JsonObject changesetsCollection = buildObj.get("Changesets").getAsJsonObject();
                QueryRequest changesetsRequest = new QueryRequest(changesetsCollection);
                changesetsRequest.setFetch(new Fetch("Artifacts","Changes", "Revision"));
                changesetsRequest.setLimit(1000);
                QueryResponse changesetsResponse = restApi.query(changesetsRequest);
                for (int j=0; j<changesetsResponse.getTotalResultCount();j++) {
                    JsonObject changesetObj = changesetsResponse.getResults().get(j).getAsJsonObject();
                    System.out.println("\nChangeset Revision: " + changesetObj.get("Revision"));
                    JsonObject artifactsCollection = changesetObj.get("Artifacts").getAsJsonObject();
                    QueryRequest artifactsRequest = new QueryRequest(artifactsCollection);
                    artifactsRequest.setFetch(new Fetch("FormattedID"));
                    QueryResponse artifactsResponse = restApi.query(artifactsRequest);
                    for (int k=0; k<artifactsResponse.getTotalResultCount();k++) {
                        JsonObject artifactObj = artifactsResponse.getResults().get(k).getAsJsonObject();
                        System.out.println("\nArtifact FormattedID: " + artifactObj.get("FormattedID"));
                    }
                    JsonObject changesCollection = changesetObj.get("Changes").getAsJsonObject();
                    QueryRequest changesRequest = new QueryRequest(changesCollection);
                    changesRequest.setWorkspace(workspaceRef);
                    changesRequest.setProject(projectRef);
                    changesRequest.setFetch(new Fetch("PathAndFilename"));
                    QueryResponse changesResponse = restApi.query(changesRequest);
                    for (int l=0; l<changesResponse.getTotalResultCount();l++) {
                        JsonObject changeObj = changesResponse.getResults().get(l).getAsJsonObject();
                        System.out.println("Change PathAndFilename: " + changeObj.get("PathAndFilename"));
                    }

                }
                System.out.println("--------------------------------");
            }
        } finally {
            if (restApi != null) {
                restApi.close();
            }
        }
    }
}

Если вы хотите отображать данные сборки внутри Agile Central (Rally), AppSDK2.1 javascript приложение можно развернуть на настраиваемой странице. Вот быстрый пример для начала:

    <!DOCTYPE html>
<html>
<head>
    <title>Builds by Date</title>
    <script type="text/javascript" src="/apps/2.1/sdk.js"></script>
    <script type="text/javascript">
        Rally.onReady(function () {
                Ext.define('CustomApp', {
    extend: 'Rally.app.App',
    componentCls: 'app',
    launch: function() {
        this.add({
            xtype: 'component',
            itemId: 'datepick',
            html: 'pick a date:',
            width: 100,
            margin: 10
        },
        {
            xtype: 'rallydatepicker',
            showToday: false,
            contentEl: Ext.ComponentQuery.query('#datepick')[0],
            margin: 10,
            handler: function(picker, date) {
                this.getBuilds(date);
            },
            scope:this
        },
        {
            xtype: 'container',
            itemId: 'gridContainer'
        });
    },
    getBuilds:function(date){
        var formattedDate = Rally.util.DateTime.formatWithDefault(date, this.getContext());
        Ext.ComponentQuery.query('#datepick')[0].update((formattedDate) + '<br /> selected');
        if (this.down('rallygrid')) {
            Ext.ComponentQuery.query('#gridContainer')[0].remove(Ext.ComponentQuery.query('#buildsGrid')[0], true);
        }
        this.down('#gridContainer').add({
            xtype: 'rallygrid',
            itemId: 'buildsGrid',
            columnCfgs: [
                'Status',
                'Message',
                'Start',
                'Uri',
                'Changesets'
            ],
            storeConfig: {
                model: 'build',
                filters:[
                    {
                        property: 'CreationDate',
                        operator: '>=',
                        value: Rally.util.DateTime.toIsoString(date,true)
                    }
                ]
            }
        });
    }
});
            Rally.launchApp('CustomApp', {
                name:"Builds by Date",
                parentRepos:""
            });
        });
    </script>
    <style type="text/css">
        .app {
  /* Add app styles here */
}
    </style>
</head>
<body>
</body>
</html>

enter image description here

1
nickm 13 Май 2016 в 17:23

Если вы добавите /api/json?pretty=true в конец URL-адреса вашего задания в Jenkins, вы сможете увидеть вывод JSON самого задания, который может привести вас к последнему номеру сборки. Кроме того, это приведет вас к URL-адресу самой последней сборки, который (снова добавив /api/json?pretty=true) может привести вас к списку изменений JSON (и соответствующим сообщениям фиксации).

Возможно, вам даже не нужно подключаться к Rally! :-)

Вы можете использовать этот JSON из своего приложения Spring, используя маршалинг JSON и класс Spring RestTemplate.

1
R. Michael Rogers 12 Май 2016 в 17:26