├── src ├── main │ ├── resources │ │ ├── Messages.properties │ │ ├── META-INF │ │ │ └── hudson.remoting.ClassFilter │ │ ├── io │ │ │ └── apimap │ │ │ │ └── plugin │ │ │ │ └── jenkins │ │ │ │ ├── ApiMap │ │ │ │ ├── help-debugMode.html │ │ │ │ ├── help-dryRunMode.html │ │ │ │ ├── help-url.html │ │ │ │ ├── help-updateBuildStatus.html │ │ │ │ ├── help-allowReadmeUpload.html │ │ │ │ ├── help-allowChangelogUpload.html │ │ │ │ └── global.jelly │ │ │ │ ├── PublishStep │ │ │ │ ├── help-metadataFile.html │ │ │ │ ├── help-readmeFile.html │ │ │ │ ├── help-changelogFile.html │ │ │ │ ├── help-taxonomyFile.html │ │ │ │ ├── help-apiToken.html │ │ │ │ └── config.jelly │ │ │ │ └── ValidateStep │ │ │ │ ├── help-metadataFile.html │ │ │ │ ├── help-taxonomyFile.html │ │ │ │ └── config.jelly │ │ └── index.jelly │ └── java │ │ └── io │ │ └── apimap │ │ └── plugin │ │ └── jenkins │ │ ├── exceptions │ │ ├── PublishErrorException.java │ │ ├── FileUnreadableException.java │ │ └── IncorrectFileTypeException.java │ │ ├── output │ │ ├── ValidateResult.java │ │ └── PublishResult.java │ │ ├── utils │ │ ├── RestClientUtil.java │ │ └── FileReader.java │ │ ├── step │ │ ├── ValidateStep.java │ │ ├── PublishStep.java │ │ ├── validate │ │ │ └── ValidateStepExecution.java │ │ └── publish │ │ │ └── PublishStepExecution.java │ │ └── ApiMap.java ├── test │ └── java │ │ └── io │ │ └── apimap │ │ ├── UrlRestrictionsTest.java │ │ ├── SurrogatePublishStepExecution.java │ │ └── FileReaderTest.java └── integrationTest │ └── java │ └── io │ └── apimap │ └── MetadataUploadTest.java ├── .mvn ├── maven.config └── extensions.xml ├── .github ├── release-drafter.yml ├── dependabot.yml └── workflows │ └── cd.yaml ├── lib └── io │ └── apimap │ ├── client │ └── rest-client │ │ └── 3.0.1 │ │ ├── rest-client-3.0.1.jar.md5 │ │ ├── rest-client-3.0.1.pom.md5 │ │ ├── rest-client-3.0.1.module.md5 │ │ ├── rest-client-3.0.1.jar.sha1 │ │ ├── rest-client-3.0.1.module.sha1 │ │ ├── rest-client-3.0.1.pom.sha1 │ │ ├── rest-client-3.0.1.jar.sha256 │ │ ├── rest-client-3.0.1.pom.sha256 │ │ ├── rest-client-3.0.1.module.sha256 │ │ ├── rest-client-3.0.1.jar │ │ ├── rest-client-3.0.1.jar.sha512 │ │ ├── rest-client-3.0.1.module.sha512 │ │ ├── rest-client-3.0.1.pom.sha512 │ │ ├── rest-client-3.0.1.pom │ │ └── rest-client-3.0.1.module │ ├── file │ └── file-interface │ │ └── 1.0 │ │ ├── file-interface-1.0.jar.md5 │ │ ├── file-interface-1.0.pom.md5 │ │ ├── file-interface-1.0.module.md5 │ │ ├── file-interface-1.0.jar.sha1 │ │ ├── file-interface-1.0.module.sha1 │ │ ├── file-interface-1.0.pom.sha1 │ │ ├── file-interface-1.0.jar.sha256 │ │ ├── file-interface-1.0.pom.sha256 │ │ ├── file-interface-1.0.module.sha256 │ │ ├── file-interface-1.0.jar │ │ ├── file-interface-1.0.jar.sha512 │ │ ├── file-interface-1.0.module.sha512 │ │ ├── file-interface-1.0.pom.sha512 │ │ ├── file-interface-1.0.pom │ │ └── file-interface-1.0.module │ └── api │ └── rest-interface │ └── 2.2.0 │ ├── rest-interface-2.2.0.jar.md5 │ ├── rest-interface-2.2.0.module.md5 │ ├── rest-interface-2.2.0.pom.md5 │ ├── rest-interface-2.2.0.jar.sha1 │ ├── rest-interface-2.2.0.pom.sha1 │ ├── rest-interface-2.2.0.module.sha1 │ ├── rest-interface-2.2.0.jar.sha256 │ ├── rest-interface-2.2.0.module.sha256 │ ├── rest-interface-2.2.0.pom.sha256 │ ├── rest-interface-2.2.0.jar │ ├── rest-interface-2.2.0.jar.sha512 │ ├── rest-interface-2.2.0.pom.sha512 │ ├── rest-interface-2.2.0.module.sha512 │ ├── rest-interface-2.2.0.pom │ └── rest-interface-2.2.0.module ├── SUPPORT.md ├── FAQ.md ├── Jenkinsfile ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── .gitignore ├── README.md ├── DEVELOPER.md ├── mvnw.cmd ├── pom.xml ├── mvnw └── LICENSE /src/main/resources/Messages.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.mvn/maven.config: -------------------------------------------------------------------------------- 1 | -Pconsume-incrementals 2 | -Pmight-produce-incrementals 3 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | _extends: .github 2 | tag-template: Apimap-$NEXT_MINOR_VERSION -------------------------------------------------------------------------------- /lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.jar.md5: -------------------------------------------------------------------------------- 1 | 800f499242191d36d29e697b858c7336 -------------------------------------------------------------------------------- /lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.pom.md5: -------------------------------------------------------------------------------- 1 | 33520cede30365ba6b2dd06d8cd43b17 -------------------------------------------------------------------------------- /lib/io/apimap/file/file-interface/1.0/file-interface-1.0.jar.md5: -------------------------------------------------------------------------------- 1 | b1a83a8582fef1dbd09fcdb36ffb3507 -------------------------------------------------------------------------------- /lib/io/apimap/file/file-interface/1.0/file-interface-1.0.pom.md5: -------------------------------------------------------------------------------- 1 | 7bd652341377c375de1e41e0afabc49f -------------------------------------------------------------------------------- /src/main/resources/META-INF/hudson.remoting.ClassFilter: -------------------------------------------------------------------------------- 1 | io.apimap.client.RestClientConfiguration -------------------------------------------------------------------------------- /lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.jar.md5: -------------------------------------------------------------------------------- 1 | fe083cd8f194da5a7ef47417e0f63f33 -------------------------------------------------------------------------------- /lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.module.md5: -------------------------------------------------------------------------------- 1 | f88a851503b6b6f6959bbe564a00707b -------------------------------------------------------------------------------- /lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.pom.md5: -------------------------------------------------------------------------------- 1 | 294d19a9dfcd7b4564014a3b024c57b3 -------------------------------------------------------------------------------- /lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.module.md5: -------------------------------------------------------------------------------- 1 | e61279efd726c2d4f3da81e866208fad -------------------------------------------------------------------------------- /lib/io/apimap/file/file-interface/1.0/file-interface-1.0.module.md5: -------------------------------------------------------------------------------- 1 | b4e9432ea353851c8dc25d57d75fc2fd -------------------------------------------------------------------------------- /lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.jar.sha1: -------------------------------------------------------------------------------- 1 | e1ab48a4b5a6d9f2823fdbbe48816507220037ce -------------------------------------------------------------------------------- /lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.pom.sha1: -------------------------------------------------------------------------------- 1 | 6a781753e7b3a3c2dadac17c11225029aeb045ca -------------------------------------------------------------------------------- /lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.jar.sha1: -------------------------------------------------------------------------------- 1 | 3ba06306c3616d770bf4b7db65d42e36ef9b621a -------------------------------------------------------------------------------- /lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.module.sha1: -------------------------------------------------------------------------------- 1 | 22561efa7767485e85f4dca6242f72ed9ec543cb -------------------------------------------------------------------------------- /lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.pom.sha1: -------------------------------------------------------------------------------- 1 | 19661b1e51dece05cc829c75b6f8448b2af00cf8 -------------------------------------------------------------------------------- /lib/io/apimap/file/file-interface/1.0/file-interface-1.0.jar.sha1: -------------------------------------------------------------------------------- 1 | 904b90c2e92d7b90bcf945ecff533e617475fe44 -------------------------------------------------------------------------------- /lib/io/apimap/file/file-interface/1.0/file-interface-1.0.module.sha1: -------------------------------------------------------------------------------- 1 | cb346a4e0b501f8f30457e86905b966b7cdc5689 -------------------------------------------------------------------------------- /lib/io/apimap/file/file-interface/1.0/file-interface-1.0.pom.sha1: -------------------------------------------------------------------------------- 1 | 62867ccfb7c6fceea41cb5eb38ed29ba8ecd4fbe -------------------------------------------------------------------------------- /lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.module.sha1: -------------------------------------------------------------------------------- 1 | 03b3fd3da5894c711f1959b9f8460908e13a3b68 -------------------------------------------------------------------------------- /lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.jar.sha256: -------------------------------------------------------------------------------- 1 | 380b242bdaab0ec5a7b4392e756056da3c155954bdd39fc229ce8f0d507e7ae5 -------------------------------------------------------------------------------- /lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.pom.sha256: -------------------------------------------------------------------------------- 1 | 3b0227c2280e9d8e8bb7f1fcc95b5ea9473b3b553acc16b6432e4ba6d86e0601 -------------------------------------------------------------------------------- /lib/io/apimap/file/file-interface/1.0/file-interface-1.0.jar.sha256: -------------------------------------------------------------------------------- 1 | 12cb352883bf31a0327f99c71c33f8fcc2b5fc92fec9d2e6aba65bf6cb954198 -------------------------------------------------------------------------------- /lib/io/apimap/file/file-interface/1.0/file-interface-1.0.pom.sha256: -------------------------------------------------------------------------------- 1 | fc48a12c3fa6780ac1286a9cda6cb7ba2e105c1e16e18c3ca569741a9119d209 -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | Support 2 | ==== 3 | 4 | 5 | 6 | ## Project Lead 7 | ___ 8 | 9 | Magnus Sulland : [msulland](https://github.com/msulland) -------------------------------------------------------------------------------- /lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.jar.sha256: -------------------------------------------------------------------------------- 1 | a0c233f539fa8f280e6b84e7b84d5ac70b8f6b586c10a30b8e9f115050f32793 -------------------------------------------------------------------------------- /lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.module.sha256: -------------------------------------------------------------------------------- 1 | 9b01d4213ab4890539691a99d669c54c3d79863906e910531de0508e92b809e1 -------------------------------------------------------------------------------- /lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.pom.sha256: -------------------------------------------------------------------------------- 1 | 9189166bfccee15381706a0006e0fcfabc87fc3ec07209805c21d9106aba33c2 -------------------------------------------------------------------------------- /lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.module.sha256: -------------------------------------------------------------------------------- 1 | 10a9af0289b403b52a25b57032a22f3eed19da49cfc510180b3c2d319e9a67ee -------------------------------------------------------------------------------- /lib/io/apimap/file/file-interface/1.0/file-interface-1.0.module.sha256: -------------------------------------------------------------------------------- 1 | eac735788694a6dcf964aa600cbbe982530a746d23a13973492506832baf19dd -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: weekly 7 | -------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/ApiMap/help-debugMode.html: -------------------------------------------------------------------------------- 1 |
2 | Enables output to stdout and/or stderr to debug the code flow. 3 |
-------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/ApiMap/help-dryRunMode.html: -------------------------------------------------------------------------------- 1 |
2 | Perform all local tasks without communicating with the server. 3 |
-------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/PublishStep/help-metadataFile.html: -------------------------------------------------------------------------------- 1 |
2 | Path and filename to the location of the API metadata. 3 |
-------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/ValidateStep/help-metadataFile.html: -------------------------------------------------------------------------------- 1 |
2 | Path and filename to the location of the API metadata. 3 |
-------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/PublishStep/help-readmeFile.html: -------------------------------------------------------------------------------- 1 |
2 | Path and filename to the location of the API README.md file 3 |
-------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/PublishStep/help-changelogFile.html: -------------------------------------------------------------------------------- 1 |
2 | Path and filename to the location of the API CHANGELOG.md file 3 |
-------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/PublishStep/help-taxonomyFile.html: -------------------------------------------------------------------------------- 1 |
2 | Path and filename to the location of the API taxonomy categorization. 3 |
-------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/ValidateStep/help-taxonomyFile.html: -------------------------------------------------------------------------------- 1 |
2 | Path and filename to the location of the API taxonomy categorization. 3 |
-------------------------------------------------------------------------------- /lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/apimap-plugin/main/lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.jar -------------------------------------------------------------------------------- /lib/io/apimap/file/file-interface/1.0/file-interface-1.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/apimap-plugin/main/lib/io/apimap/file/file-interface/1.0/file-interface-1.0.jar -------------------------------------------------------------------------------- /lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/apimap-plugin/main/lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.jar -------------------------------------------------------------------------------- /src/main/resources/index.jelly: -------------------------------------------------------------------------------- 1 | 2 |
3 | API management plugin interacting with an ApiMap.io instance to publish API documentation. 4 |
5 | -------------------------------------------------------------------------------- /lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.jar.sha512: -------------------------------------------------------------------------------- 1 | 87b74572d8635bdae04c4bcfc107e368807a85946c8cd99a5a5c6058085aff827cc0e122a9b3f7ea55da84abcd210adca2996d6be05ea8d251d2f3015f3e6eb4 -------------------------------------------------------------------------------- /lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.pom.sha512: -------------------------------------------------------------------------------- 1 | 7b8a897bf22523c8c54b99f6a8995793b8f7a740b3f8a96feef83c50e6ca057c3c7d90af9716c612fa13ef54af6f9ed6370ea845f0ce94f4b0db23ed4b2d0516 -------------------------------------------------------------------------------- /lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.jar.sha512: -------------------------------------------------------------------------------- 1 | 5af289c73b7d5a50912f358f2bb149477e096ccb617093f2bea9555866283c6b0b1495910af24a52c52e0c1d9a59b8c911025e154e200aa9a39a41f8979a6b85 -------------------------------------------------------------------------------- /lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.module.sha512: -------------------------------------------------------------------------------- 1 | 46c32023ab37ee926fa6e6d9e8fc40ee67378701ec7abfb28bb3c42b00e2584ddb62eff99ff78b82522ad88ce94797a68d3dcd8b2e680dcca807f18e6a31b20e -------------------------------------------------------------------------------- /lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.pom.sha512: -------------------------------------------------------------------------------- 1 | 56c0888995f9656702c1c0d73e8b7bd3a40242488e7c9b27d644a36dc36f9dcce572dc4c881ea7ade5aa326cf30264b61990cad30825fa7adae94079bccc10ea -------------------------------------------------------------------------------- /lib/io/apimap/file/file-interface/1.0/file-interface-1.0.jar.sha512: -------------------------------------------------------------------------------- 1 | c11981c37897542360a212474b28f581841be0ef37fae4fc8431f83957b56d75141fa752a457792f782c09306a295f3360145f6f2608a55343726bfbb776e525 -------------------------------------------------------------------------------- /lib/io/apimap/file/file-interface/1.0/file-interface-1.0.module.sha512: -------------------------------------------------------------------------------- 1 | 973db28064e9feac8f60323e8f5afa8ac684aff6f96e4e69903e3e0f6af5bacde567e65c5907f6360845f8bd2a4940124d17e4f7795c8b1eae47da8cc35868e5 -------------------------------------------------------------------------------- /lib/io/apimap/file/file-interface/1.0/file-interface-1.0.pom.sha512: -------------------------------------------------------------------------------- 1 | c513d93ed4d767f44c3b360b90ea612f6a3b5ccaea7674cf8900dbb2421294b76093381a3b97cb523374bf7e3c43cc63a6e76f8fc61d278fac0902717abaec13 -------------------------------------------------------------------------------- /lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.module.sha512: -------------------------------------------------------------------------------- 1 | 6a2246fad27368a2e9868489954d42acea316ac83439ef9293a2fd3cdd3c8123f499d6c61386d9327757d30dd46382500a43c6b181a689c0b57715dd955fa122 -------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/ApiMap/help-url.html: -------------------------------------------------------------------------------- 1 |
2 | Root URL to the API instance this build system should use to publish API information (e.g. http://localhost:8080) 3 |
-------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/ApiMap/help-updateBuildStatus.html: -------------------------------------------------------------------------------- 1 |
2 | If checked, this plugin will update the global workspace build status alongside returning data objects. 3 |
-------------------------------------------------------------------------------- /FAQ.md: -------------------------------------------------------------------------------- 1 | Frequently Asked Questions (FAQ) 2 | === 3 | 4 | ## Table of Contents 5 | 6 | * [How-Tos](#how-tos) 7 | * [Build Problems](#build-problems) 8 | 9 | ## How-Tos 10 | - - - 11 | 12 | None 13 | 14 | ## Build Problems 15 | - - - 16 | 17 | None -------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/ApiMap/help-allowReadmeUpload.html: -------------------------------------------------------------------------------- 1 |
2 | Enable users upload files into the readme resources attached to the API. SECURITY IMPORTANCE: This enables the user to specify any file inside their code repository. 3 |
-------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/ApiMap/help-allowChangelogUpload.html: -------------------------------------------------------------------------------- 1 |
2 | Enable users upload files into the changelog resources attached to the API. SECURITY IMPORTANCE: This enables the user to specify any file inside their code repository. 3 |
-------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/PublishStep/help-apiToken.html: -------------------------------------------------------------------------------- 1 |
2 | A token is required if the API already existing in the catalog. If a new API is created the return value from this step includes the newly created token that is required in any future interaction. 3 |
-------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | def configurations = [ 2 | [ platform: 'linux', jdk: '8', jenkins: '2.300' ], 3 | [ platform: 'linux', jdk: '11', jenkins: '2.300' ], 4 | [ platform: 'linux', jdk: '17', jenkins: '2.300' ] 5 | ] 6 | 7 | buildPlugin( 8 | tests: [ skip: true ], 9 | configurations: configurations 10 | ) -------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/ValidateStep/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.mvn/extensions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | io.jenkins.tools.incrementals 4 | git-changelist-maven-extension 5 | 1.3 6 | 7 | -------------------------------------------------------------------------------- /.github/workflows/cd.yaml: -------------------------------------------------------------------------------- 1 | # Note: additional setup is required, see https://www.jenkins.io/redirect/continuous-delivery-of-plugins 2 | 3 | name: cd 4 | on: 5 | workflow_dispatch: 6 | check_run: 7 | types: 8 | - completed 9 | 10 | jobs: 11 | maven-cd: 12 | uses: jenkins-infra/github-reusable-workflows/.github/workflows/maven-cd.yml@v1 13 | secrets: 14 | MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} 15 | MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }} -------------------------------------------------------------------------------- /src/test/java/io/apimap/UrlRestrictionsTest.java: -------------------------------------------------------------------------------- 1 | package io.apimap; 2 | 3 | import io.apimap.plugin.jenkins.utils.RestClientUtil; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertFalse; 7 | import static org.junit.Assert.assertTrue; 8 | 9 | public class UrlRestrictionsTest { 10 | @Test 11 | public void urlWithArguments_didFail() { 12 | assertFalse(RestClientUtil.bareboneURL("https://www.google.com/search?channel=fs&client=ubuntu")); 13 | } 14 | 15 | @Test 16 | public void urlWithoutArguments_didSucceed() { 17 | assertTrue(RestClientUtil.bareboneURL("https://api.apimap.io/")); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/PublishStep/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Changelog 2 | === 3 | 4 | ### 01.09.2022 5 | - Fixed repository url bug 6 | 7 | ### 19.08.2022 8 | - Added readme and changelog resource uploads 9 | - Using log levels FINER and FINE 10 | - Added default values to all parameters 11 | - Return token even on failure if a token is returned upon create a new API 12 | - Fixed enabling dry run bug 13 | 14 | ### 29.06.2022 15 | - Code added to the jenkins git repo 16 | - Added jar libraries to local repository 17 | 18 | ### 28.06.2022 19 | - Removed connection testing function 20 | 21 | ### 22.06.2022 22 | - Testing a URL now requires the user to be Administrator 23 | - Added description text if people use arguments in the apimap url 24 | 25 | ### 21.04.2022 26 | - Updated dependencies 27 | 28 | ### 29.10.2021 29 | - First public release 30 | -------------------------------------------------------------------------------- /src/main/resources/io/apimap/plugin/jenkins/ApiMap/global.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/io/apimap/plugin/jenkins/exceptions/PublishErrorException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package io.apimap.plugin.jenkins.exceptions; 21 | 22 | public class PublishErrorException extends Exception { 23 | public PublishErrorException(String message) { 24 | super(message); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/apimap/plugin/jenkins/exceptions/FileUnreadableException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package io.apimap.plugin.jenkins.exceptions; 21 | 22 | public class FileUnreadableException extends Exception { 23 | public FileUnreadableException(String message) { 24 | super(message); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/apimap/plugin/jenkins/exceptions/IncorrectFileTypeException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package io.apimap.plugin.jenkins.exceptions; 21 | 22 | public class IncorrectFileTypeException extends Exception { 23 | public IncorrectFileTypeException(String message) { 24 | super(message); 25 | } 26 | } -------------------------------------------------------------------------------- /lib/io/apimap/file/file-interface/1.0/file-interface-1.0.pom: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 4.0.0 10 | io.apimap.file 11 | file-interface 12 | 1.0 13 | 14 | 15 | com.fasterxml.jackson.core 16 | jackson-databind 17 | 2.13.0 18 | runtime 19 | 20 | 21 | com.fasterxml.jackson.core 22 | jackson-core 23 | 2.13.0 24 | runtime 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.pom: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 4.0.0 10 | io.apimap.api 11 | rest-interface 12 | 2.2.0 13 | 14 | 15 | com.fasterxml.jackson.core 16 | jackson-databind 17 | 2.13.3 18 | runtime 19 | 20 | 21 | com.fasterxml.jackson.core 22 | jackson-annotations 23 | 2.13.3 24 | runtime 25 | 26 | 27 | io.swagger.core.v3 28 | swagger-annotations 29 | 2.2.0 30 | runtime 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.pom: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 4.0.0 10 | io.apimap.client 11 | rest-client 12 | 3.0.1 13 | 14 | 15 | org.apache.httpcomponents.client5 16 | httpclient5 17 | 5.1.3 18 | compile 19 | 20 | 21 | io.apimap.api 22 | rest-interface 23 | 2.1.3 24 | compile 25 | 26 | 27 | com.fasterxml.jackson.core 28 | jackson-databind 29 | 2.13.3 30 | runtime 31 | 32 | 33 | com.fasterxml.jackson.core 34 | jackson-annotations 35 | 2.13.3 36 | runtime 37 | 38 | 39 | commons-io 40 | commons-io 41 | 2.11.0 42 | runtime 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/main/java/io/apimap/plugin/jenkins/output/ValidateResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package io.apimap.plugin.jenkins.output; 21 | 22 | import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.Whitelisted; 23 | 24 | public class ValidateResult { 25 | public enum Status { 26 | VALID, 27 | MISSING, 28 | INVALID, 29 | ABORTED, 30 | FAILED, 31 | UNKNOWN 32 | } 33 | 34 | private final Status status; 35 | private final String description; 36 | 37 | public ValidateResult(final Status status, 38 | final String description) { 39 | this.status = status; 40 | this.description = description; 41 | } 42 | 43 | @Whitelisted 44 | public Status getStatus() { 45 | return status; 46 | } 47 | 48 | @Whitelisted 49 | public String getDescription() { 50 | return description; 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return "ValidateResult{" + 56 | "status=" + status + 57 | ", description='" + description + '\'' + 58 | '}'; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/io/apimap/plugin/jenkins/utils/RestClientUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package io.apimap.plugin.jenkins.utils; 21 | 22 | import io.apimap.client.RestClientConfiguration; 23 | import io.apimap.plugin.jenkins.ApiMap; 24 | import jenkins.model.Jenkins; 25 | 26 | import java.io.IOException; 27 | 28 | public class RestClientUtil { 29 | public static RestClientConfiguration configuration(String token) throws IOException { 30 | final Jenkins instance = Jenkins.getInstanceOrNull(); 31 | 32 | if (instance == null) { 33 | throw new IOException("Unable to find Jenkins Instance"); 34 | } 35 | 36 | final ApiMap.ApiMapDescriptorImpl descImpl = (ApiMap.ApiMapDescriptorImpl) instance.getDescriptorByName(ApiMap.class.getName()); 37 | 38 | if (descImpl.getUrl() == null) { 39 | throw new IOException("Missing required root URL"); 40 | } 41 | 42 | final RestClientConfiguration client = new RestClientConfiguration( 43 | token, 44 | descImpl.getUrl(), 45 | descImpl.isDebugMode() 46 | ); 47 | 48 | client.setDryRunMode(descImpl.isDryRunMode()); 49 | 50 | return client; 51 | } 52 | 53 | public static boolean bareboneURL(String url){ 54 | return !url.matches(".*([&?]).*"); 55 | } 56 | } -------------------------------------------------------------------------------- /src/main/java/io/apimap/plugin/jenkins/output/PublishResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package io.apimap.plugin.jenkins.output; 21 | 22 | import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.Whitelisted; 23 | 24 | public class PublishResult { 25 | public enum Status { 26 | CREATED, 27 | UPDATED, 28 | FAILED, 29 | ABORTED, 30 | UNKNOWN 31 | } 32 | 33 | private final Status status; 34 | private final String description; 35 | private final String token; 36 | 37 | public PublishResult(final Status status, 38 | final String description) { 39 | this.status = status; 40 | this.description = description; 41 | this.token = null; 42 | } 43 | 44 | public PublishResult(final Status status, 45 | final String description, 46 | final String token) { 47 | this.status = status; 48 | this.description = description; 49 | this.token = token; 50 | } 51 | 52 | @Whitelisted 53 | public Status getStatus() { 54 | return status; 55 | } 56 | 57 | @Whitelisted 58 | public String getDescription() { 59 | return description; 60 | } 61 | 62 | @Whitelisted 63 | public String getToken() { 64 | return token; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | return "PublishResult{" + 70 | "status=" + status + 71 | ", description='" + description + '\'' + 72 | ", token='" + token + '\'' + 73 | '}'; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /lib/io/apimap/file/file-interface/1.0/file-interface-1.0.module: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1.1", 3 | "component": { 4 | "group": "io.apimap.file", 5 | "module": "file-interface", 6 | "version": "1.0", 7 | "attributes": { 8 | "org.gradle.status": "release" 9 | } 10 | }, 11 | "createdBy": { 12 | "gradle": { 13 | "version": "7.1" 14 | } 15 | }, 16 | "variants": [ 17 | { 18 | "name": "apiElements", 19 | "attributes": { 20 | "org.gradle.category": "library", 21 | "org.gradle.dependency.bundling": "external", 22 | "org.gradle.jvm.version": 8, 23 | "org.gradle.libraryelements": "jar", 24 | "org.gradle.usage": "java-api" 25 | }, 26 | "files": [ 27 | { 28 | "name": "file-interface-1.0.jar", 29 | "url": "file-interface-1.0.jar", 30 | "size": 9054, 31 | "sha512": "c11981c37897542360a212474b28f581841be0ef37fae4fc8431f83957b56d75141fa752a457792f782c09306a295f3360145f6f2608a55343726bfbb776e525", 32 | "sha256": "12cb352883bf31a0327f99c71c33f8fcc2b5fc92fec9d2e6aba65bf6cb954198", 33 | "sha1": "904b90c2e92d7b90bcf945ecff533e617475fe44", 34 | "md5": "b1a83a8582fef1dbd09fcdb36ffb3507" 35 | } 36 | ] 37 | }, 38 | { 39 | "name": "runtimeElements", 40 | "attributes": { 41 | "org.gradle.category": "library", 42 | "org.gradle.dependency.bundling": "external", 43 | "org.gradle.jvm.version": 8, 44 | "org.gradle.libraryelements": "jar", 45 | "org.gradle.usage": "java-runtime" 46 | }, 47 | "dependencies": [ 48 | { 49 | "group": "com.fasterxml.jackson.core", 50 | "module": "jackson-databind", 51 | "version": { 52 | "requires": "2.13.0" 53 | } 54 | }, 55 | { 56 | "group": "com.fasterxml.jackson.core", 57 | "module": "jackson-core", 58 | "version": { 59 | "requires": "2.13.0" 60 | } 61 | } 62 | ], 63 | "files": [ 64 | { 65 | "name": "file-interface-1.0.jar", 66 | "url": "file-interface-1.0.jar", 67 | "size": 9054, 68 | "sha512": "c11981c37897542360a212474b28f581841be0ef37fae4fc8431f83957b56d75141fa752a457792f782c09306a295f3360145f6f2608a55343726bfbb776e525", 69 | "sha256": "12cb352883bf31a0327f99c71c33f8fcc2b5fc92fec9d2e6aba65bf6cb954198", 70 | "sha1": "904b90c2e92d7b90bcf945ecff533e617475fe44", 71 | "md5": "b1a83a8582fef1dbd09fcdb36ffb3507" 72 | } 73 | ] 74 | } 75 | ] 76 | } 77 | -------------------------------------------------------------------------------- /lib/io/apimap/api/rest-interface/2.2.0/rest-interface-2.2.0.module: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1.1", 3 | "component": { 4 | "group": "io.apimap.api", 5 | "module": "rest-interface", 6 | "version": "2.2.0", 7 | "attributes": { 8 | "org.gradle.status": "release" 9 | } 10 | }, 11 | "createdBy": { 12 | "gradle": { 13 | "version": "7.1" 14 | } 15 | }, 16 | "variants": [ 17 | { 18 | "name": "apiElements", 19 | "attributes": { 20 | "org.gradle.category": "library", 21 | "org.gradle.dependency.bundling": "external", 22 | "org.gradle.jvm.version": 8, 23 | "org.gradle.libraryelements": "jar", 24 | "org.gradle.usage": "java-api" 25 | }, 26 | "files": [ 27 | { 28 | "name": "rest-interface-2.2.0.jar", 29 | "url": "rest-interface-2.2.0.jar", 30 | "size": 72462, 31 | "sha512": "87b74572d8635bdae04c4bcfc107e368807a85946c8cd99a5a5c6058085aff827cc0e122a9b3f7ea55da84abcd210adca2996d6be05ea8d251d2f3015f3e6eb4", 32 | "sha256": "a0c233f539fa8f280e6b84e7b84d5ac70b8f6b586c10a30b8e9f115050f32793", 33 | "sha1": "e1ab48a4b5a6d9f2823fdbbe48816507220037ce", 34 | "md5": "fe083cd8f194da5a7ef47417e0f63f33" 35 | } 36 | ] 37 | }, 38 | { 39 | "name": "runtimeElements", 40 | "attributes": { 41 | "org.gradle.category": "library", 42 | "org.gradle.dependency.bundling": "external", 43 | "org.gradle.jvm.version": 8, 44 | "org.gradle.libraryelements": "jar", 45 | "org.gradle.usage": "java-runtime" 46 | }, 47 | "dependencies": [ 48 | { 49 | "group": "com.fasterxml.jackson.core", 50 | "module": "jackson-databind", 51 | "version": { 52 | "requires": "2.13.3" 53 | } 54 | }, 55 | { 56 | "group": "com.fasterxml.jackson.core", 57 | "module": "jackson-annotations", 58 | "version": { 59 | "requires": "2.13.3" 60 | } 61 | }, 62 | { 63 | "group": "io.swagger.core.v3", 64 | "module": "swagger-annotations", 65 | "version": { 66 | "requires": "2.2.0" 67 | } 68 | } 69 | ], 70 | "files": [ 71 | { 72 | "name": "rest-interface-2.2.0.jar", 73 | "url": "rest-interface-2.2.0.jar", 74 | "size": 72462, 75 | "sha512": "87b74572d8635bdae04c4bcfc107e368807a85946c8cd99a5a5c6058085aff827cc0e122a9b3f7ea55da84abcd210adca2996d6be05ea8d251d2f3015f3e6eb4", 76 | "sha256": "a0c233f539fa8f280e6b84e7b84d5ac70b8f6b586c10a30b8e9f115050f32793", 77 | "sha1": "e1ab48a4b5a6d9f2823fdbbe48816507220037ce", 78 | "md5": "fe083cd8f194da5a7ef47417e0f63f33" 79 | } 80 | ] 81 | } 82 | ] 83 | } 84 | -------------------------------------------------------------------------------- /src/integrationTest/java/io/apimap/MetadataUploadTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package io.apimap; 21 | 22 | import io.apimap.client.RestClientConfiguration; 23 | import io.apimap.client.exception.IncorrectTokenException; 24 | import io.apimap.file.metadata.MetadataDataWrapper; 25 | import io.apimap.file.metadata.MetadataFile; 26 | import io.apimap.plugin.jenkins.exceptions.PublishErrorException; 27 | import io.apimap.plugin.jenkins.step.PublishStep; 28 | import org.apache.http.HttpEntity; 29 | import org.jenkinsci.plugins.workflow.steps.StepContext; 30 | import org.junit.Test; 31 | 32 | import java.io.IOException; 33 | import java.util.Arrays; 34 | import java.util.Locale; 35 | 36 | import static junit.framework.TestCase.assertTrue; 37 | import static org.mockito.Mockito.mock; 38 | import static org.mockito.Mockito.when; 39 | 40 | 41 | public class MetadataUploadTest { 42 | @Test 43 | public void uploadFile_didSucceed() throws IncorrectTokenException, IOException, PublishErrorException, InterruptedException { 44 | PublishStep publishStep = mock(PublishStep.class); 45 | when(publishStep.getRepositoryURL()).thenReturn("http://localhost:888"); 46 | 47 | StepContext context = mock(StepContext.class); 48 | 49 | SurrogatePublishStepExecution publishStepExecution = new SurrogatePublishStepExecution(publishStep, context); 50 | 51 | MetadataDataWrapper data = new MetadataDataWrapper( 52 | "Hello World", 53 | "My first API", 54 | "Public", 55 | "1.0.0", 56 | "Design", 57 | "JSON:API v1.1", 58 | "OpenAPI Specification", 59 | "My department", 60 | "Apimap.io", 61 | "System1", 62 | Arrays.asList("http://localhost:8080") 63 | ); 64 | 65 | MetadataFile metadataFile = new MetadataFile("1", data); 66 | RestClientConfiguration configuration = new RestClientConfiguration(null, "http://localhost:8080", true); 67 | publishStepExecution.uploadMetadata(metadataFile, configuration); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/io/apimap/SurrogatePublishStepExecution.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package io.apimap; 21 | 22 | import io.apimap.api.rest.ClassificationRootRestEntity; 23 | import io.apimap.api.rest.MetadataDataRestEntity; 24 | import io.apimap.client.RestClientConfiguration; 25 | import io.apimap.client.exception.IncorrectTokenException; 26 | import io.apimap.file.metadata.MetadataFile; 27 | import io.apimap.file.taxonomy.TaxonomyFile; 28 | import io.apimap.plugin.jenkins.exceptions.PublishErrorException; 29 | import io.apimap.plugin.jenkins.output.PublishResult; 30 | import io.apimap.plugin.jenkins.step.PublishStep; 31 | import io.apimap.plugin.jenkins.step.publish.PublishStepExecution; 32 | import org.apache.commons.lang.mutable.MutableBoolean; 33 | import org.jenkinsci.plugins.workflow.steps.StepContext; 34 | 35 | import java.io.IOException; 36 | 37 | public class SurrogatePublishStepExecution extends PublishStepExecution { 38 | public SurrogatePublishStepExecution(PublishStep step, StepContext context) { 39 | super(step, context); 40 | } 41 | 42 | public PublishResult failure(String description){ 43 | return super.failure(description, null); 44 | } 45 | 46 | public PublishResult success(String description, String token, MutableBoolean isApiCreated){ 47 | return super.success(description, token, isApiCreated); 48 | } 49 | 50 | public PublishResult run() throws Exception { 51 | return super.run(); 52 | } 53 | 54 | public MetadataDataRestEntity uploadMetadata(MetadataFile metadataFile, RestClientConfiguration configuration, MutableBoolean isApiCreated) throws IOException, InterruptedException, IncorrectTokenException, PublishErrorException { 55 | return super.uploadMetadata(metadataFile, configuration, isApiCreated); 56 | } 57 | 58 | public ClassificationRootRestEntity uploadTaxonomy(String apiName, String apiVersion, TaxonomyFile taxonomyFile, RestClientConfiguration configuration) throws IOException, IncorrectTokenException, PublishErrorException { 59 | return super.uploadTaxonomy(apiName, apiVersion, taxonomyFile, configuration); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to make participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies within all project spaces, and it also applies when 49 | an individual is representing the project or its community in public spaces. 50 | Examples of representing a project or community include using an official 51 | project e-mail address, posting via an official social media account, or acting 52 | as an appointed representative at an online or offline event. Representation of 53 | a project may be further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at https://github.com/apimap. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /lib/io/apimap/client/rest-client/3.0.1/rest-client-3.0.1.module: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1.1", 3 | "component": { 4 | "group": "io.apimap.client", 5 | "module": "rest-client", 6 | "version": "3.0.1", 7 | "attributes": { 8 | "org.gradle.status": "release" 9 | } 10 | }, 11 | "createdBy": { 12 | "gradle": { 13 | "version": "7.5.1" 14 | } 15 | }, 16 | "variants": [ 17 | { 18 | "name": "apiElements", 19 | "attributes": { 20 | "org.gradle.category": "library", 21 | "org.gradle.dependency.bundling": "external", 22 | "org.gradle.jvm.version": 8, 23 | "org.gradle.libraryelements": "jar", 24 | "org.gradle.usage": "java-api" 25 | }, 26 | "dependencies": [ 27 | { 28 | "group": "org.apache.httpcomponents.client5", 29 | "module": "httpclient5", 30 | "version": { 31 | "requires": "5.1.3" 32 | } 33 | }, 34 | { 35 | "group": "io.apimap.api", 36 | "module": "rest-interface", 37 | "version": { 38 | "requires": "2.1.3" 39 | } 40 | } 41 | ], 42 | "files": [ 43 | { 44 | "name": "rest-client-3.0.1.jar", 45 | "url": "rest-client-3.0.1.jar", 46 | "size": 22590, 47 | "sha512": "5af289c73b7d5a50912f358f2bb149477e096ccb617093f2bea9555866283c6b0b1495910af24a52c52e0c1d9a59b8c911025e154e200aa9a39a41f8979a6b85", 48 | "sha256": "380b242bdaab0ec5a7b4392e756056da3c155954bdd39fc229ce8f0d507e7ae5", 49 | "sha1": "3ba06306c3616d770bf4b7db65d42e36ef9b621a", 50 | "md5": "800f499242191d36d29e697b858c7336" 51 | } 52 | ] 53 | }, 54 | { 55 | "name": "runtimeElements", 56 | "attributes": { 57 | "org.gradle.category": "library", 58 | "org.gradle.dependency.bundling": "external", 59 | "org.gradle.jvm.version": 8, 60 | "org.gradle.libraryelements": "jar", 61 | "org.gradle.usage": "java-runtime" 62 | }, 63 | "dependencies": [ 64 | { 65 | "group": "com.fasterxml.jackson.core", 66 | "module": "jackson-databind", 67 | "version": { 68 | "requires": "2.13.3" 69 | } 70 | }, 71 | { 72 | "group": "com.fasterxml.jackson.core", 73 | "module": "jackson-annotations", 74 | "version": { 75 | "requires": "2.13.3" 76 | } 77 | }, 78 | { 79 | "group": "commons-io", 80 | "module": "commons-io", 81 | "version": { 82 | "requires": "2.11.0" 83 | } 84 | }, 85 | { 86 | "group": "org.apache.httpcomponents.client5", 87 | "module": "httpclient5", 88 | "version": { 89 | "requires": "5.1.3" 90 | } 91 | }, 92 | { 93 | "group": "io.apimap.api", 94 | "module": "rest-interface", 95 | "version": { 96 | "requires": "2.1.3" 97 | } 98 | } 99 | ], 100 | "files": [ 101 | { 102 | "name": "rest-client-3.0.1.jar", 103 | "url": "rest-client-3.0.1.jar", 104 | "size": 22590, 105 | "sha512": "5af289c73b7d5a50912f358f2bb149477e096ccb617093f2bea9555866283c6b0b1495910af24a52c52e0c1d9a59b8c911025e154e200aa9a39a41f8979a6b85", 106 | "sha256": "380b242bdaab0ec5a7b4392e756056da3c155954bdd39fc229ce8f0d507e7ae5", 107 | "sha1": "3ba06306c3616d770bf4b7db65d42e36ef9b621a", 108 | "md5": "800f499242191d36d29e697b858c7336" 109 | } 110 | ] 111 | } 112 | ] 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/io/apimap/plugin/jenkins/step/ValidateStep.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package io.apimap.plugin.jenkins.step; 21 | 22 | import edu.umd.cs.findbugs.annotations.NonNull; 23 | import hudson.Extension; 24 | import hudson.model.Run; 25 | import hudson.model.TaskListener; 26 | import io.apimap.plugin.jenkins.step.validate.ValidateStepExecution; 27 | import org.jenkinsci.Symbol; 28 | import org.jenkinsci.plugins.workflow.steps.Step; 29 | import org.jenkinsci.plugins.workflow.steps.StepContext; 30 | import org.jenkinsci.plugins.workflow.steps.StepDescriptor; 31 | import org.jenkinsci.plugins.workflow.steps.StepExecution; 32 | import org.kohsuke.stapler.DataBoundConstructor; 33 | import org.kohsuke.stapler.DataBoundSetter; 34 | 35 | import java.io.Serializable; 36 | import java.util.HashSet; 37 | import java.util.Set; 38 | import java.util.logging.Logger; 39 | 40 | public class ValidateStep extends Step implements Serializable { 41 | public static final String BUILD_STEP_DISPLAY_NAME = "File content validation"; 42 | public static final String BUILD_STEP_FUNCTION_NAME = "validateAPI"; 43 | 44 | public static final String DEFAULT_METADATA_FILE_VALUE = "apimap/metadata.apimap"; 45 | public static final String DEFAULT_TAXONOMY_FILE_VALUE = "apimap/taxonomy.apimap"; 46 | 47 | public String metadataFile; 48 | public String taxonomyFile; 49 | 50 | @DataBoundConstructor 51 | public ValidateStep(final String metadataFile, 52 | final String taxonomyFile) { 53 | this.metadataFile = metadataFile; 54 | this.taxonomyFile = taxonomyFile; 55 | } 56 | 57 | public String getMetadataFile() { 58 | if(metadataFile == null) return DEFAULT_METADATA_FILE_VALUE; 59 | return metadataFile; 60 | } 61 | 62 | @DataBoundSetter 63 | public void setMetadataFile(final String metadataFile) { 64 | this.metadataFile = metadataFile; 65 | } 66 | 67 | public String getTaxonomyFile() { 68 | if(taxonomyFile == null) return DEFAULT_TAXONOMY_FILE_VALUE; 69 | return taxonomyFile; 70 | } 71 | 72 | @DataBoundSetter 73 | public void setTaxonomyFile(final String taxonomyFile) { 74 | this.taxonomyFile = taxonomyFile; 75 | } 76 | 77 | @Override 78 | public StepExecution start(final StepContext stepContext) throws Exception { 79 | return new ValidateStepExecution(this, stepContext); 80 | } 81 | 82 | @Symbol(BUILD_STEP_FUNCTION_NAME) 83 | @Extension 84 | public static final class DescriptorImpl extends StepDescriptor { 85 | @Override 86 | public Set> getRequiredContext() { 87 | Set> contexts = new HashSet<>(); 88 | contexts.add(TaskListener.class); 89 | contexts.add(Run.class); 90 | return contexts; 91 | } 92 | 93 | @Override 94 | public String getFunctionName() { 95 | return BUILD_STEP_FUNCTION_NAME; 96 | } 97 | 98 | @NonNull 99 | @Override 100 | public String getDisplayName() { 101 | return BUILD_STEP_DISPLAY_NAME; 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing to the Project 2 | ===== 3 | 4 | 🥳 **Happy Coding** 🥳 5 | 6 | The following is a set of guidelines for contributing to the Apimap.io project. Although the project consists of 7 | multiple components they all share the same "way of working". 8 | 9 | Remember, these are mostly guidelines and not strict rules. Feel free to propose changes to this document. 10 | 11 | ## Table of Contents 12 | 13 | * [Code of Conduct](#code-of-conduct) 14 | * [Report a Bug](#report-a-bug) 15 | * [Request a Feature](#request-a-feature) 16 | * [Code and Asset Contributions](#code-and-asset-contributions) 17 | * [Where can I ask for help?](#where-can-i-ask-for-help) 18 | 19 | ## Code of Conduct 20 | ___ 21 | 22 | This project and everyone that participates in it is governed by our [Code of Conduct](CODE_OF_CONDUCT.md). 23 | By participating, we expect you to uphold this code. 24 | 25 | ## How Can I Contribute? 26 | ___ 27 | 28 | **We love contributions** 🎉 29 | 30 | Remember, it is better to report a bug to many than not reporting at all. If in doubt report a bug or create a feature 31 | request ️🧙 Future features depends on community feedback. 32 | 33 | > **Note:** Please don't file an issue to ask a question, you will get a faster answer by using 34 | > other means of contact 35 | 36 | > **Note:** We try to list questions we get in our [FAQ](FAQ.md), please read there first 37 | 38 | ### Report a Bug 39 | ___ 40 | 41 | 🎉 **We love bug reports** 🎉 42 | 43 | #### Before Submitting 44 | 45 | - **Check** the [FAQ](FAQ.md) 46 | - **Perform a search** to see if an equal problem has already been reported. If so, please add a comment to the reported issue 47 | - **Already have a fix?** If you want to fix the bug please make a note in the description 48 | - **Determine** the correct Apimap.io component, it might be relevant to multiple components 49 | 50 | #### Howto Submit A Report 51 | 52 | [We use GitHub to track our bugs and features.](https://github.com/jenkinsci/apimap-plugin) 53 | 54 | ##### A Good Bug Report Should Contain 55 | 56 | - **A clear and descriptive title** 57 | - **Step by step** description on how to reproduce the results 58 | - A clear and **"to the point"** description of the problem 59 | - **Stack traces**, system outputs or any other information that might be relevant 60 | 61 | ### Request a Feature 62 | ___ 63 | 64 | 🎉 **We love feature request** 🎉 65 | 66 | #### Before Submitting 67 | 68 | - **Determine** the correct component. We read everything, although the correct component could help us understand the 69 | context of the feature 70 | 71 | ##### A Good Feature Request Should Contain 72 | 73 | - **A clear and descriptive title** 74 | - **Use case examples**. We don't need features just to have features, they have to give value 75 | - **Examples from other software products** if the feature is implemented by others 76 | - A clear and **"to the point"** description of the feature 77 | 78 | ### Code and Asset Contributions 79 | ___ 80 | 81 | 🎉 **We love code contributions** 🎉 82 | 83 | ##### Setting up your environment 84 | 85 | This is a Java based solution 86 | 87 | You will need 88 | - Java version 8 or newer 89 | 90 | ##### Creating a Pull Request 91 | 92 | 1. Be up-to-date with our development branch 93 | 2. Squash your commits (git merge --squash) 94 | 3. Create a pull request on GitHub 95 | 96 | We strive to include contributions without too much delay. If the diff between your commit and the development branch 97 | becomes to great, we will ask you to rebase. 98 | 99 | ##### A Good Pull Request Should Contain 100 | 101 | - **A clear and descriptive branch name** that starts with feature/ or bugfix/ 102 | - A clear and **"to the point"** summary of the changes within 103 | - A **up-to-date** code merge with our development branch 104 | 105 | **Remember**: No change is too small 106 | 107 | ### Where can I ask for help? 108 | ___ 109 | 110 | Didn't find what you where looking for? I want to contribute but still have questions? Please [contact us](SUPPORT.md) after reading our [FAQ](FAQ.md). -------------------------------------------------------------------------------- /src/main/java/io/apimap/plugin/jenkins/utils/FileReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package io.apimap.plugin.jenkins.utils; 21 | 22 | import hudson.FilePath; 23 | import io.apimap.file.FileFactory; 24 | import io.apimap.file.exceptions.MissingRequiredFieldException; 25 | import io.apimap.file.exceptions.UnsupportedVersionException; 26 | import io.apimap.file.metadata.MetadataFile; 27 | import io.apimap.file.taxonomy.TaxonomyFile; 28 | import io.apimap.plugin.jenkins.exceptions.FileUnreadableException; 29 | import io.apimap.plugin.jenkins.exceptions.IncorrectFileTypeException; 30 | 31 | import java.io.*; 32 | import java.nio.charset.StandardCharsets; 33 | import java.util.stream.Collectors; 34 | 35 | public class FileReader { 36 | public static MetadataFile metadataFile(final FilePath filePath) throws InterruptedException, MissingRequiredFieldException, UnsupportedVersionException, IOException, FileUnreadableException { 37 | if (filePath == null) throw new FileNotFoundException("[ERROR] Empty metadata file path"); 38 | 39 | try (final InputStream fileReader = FileReader.readFileInDirectory(filePath)) { 40 | return FileFactory.metadataFromInputStream(fileReader); 41 | } catch (IOException | InterruptedException ignored) { 42 | throw new FileUnreadableException("Unable to read file"); 43 | } 44 | } 45 | 46 | public static TaxonomyFile taxonomyFile(final FilePath filePath) throws IOException, InterruptedException, FileUnreadableException { 47 | if (filePath == null) throw new FileNotFoundException("[ERROR] Empty taxonomy file path"); 48 | 49 | try (final InputStream fileReader = FileReader.readFileInDirectory(filePath)) { 50 | return FileFactory.taxonomyFromInputStream(fileReader); 51 | } catch (IOException | InterruptedException ignored) { 52 | throw new FileUnreadableException("Unable to read file"); 53 | } 54 | } 55 | 56 | public static String readDocument(final FilePath filePath) throws IncorrectFileTypeException, FileUnreadableException { 57 | if(!filePath.getName().endsWith(".md")){ 58 | throw new IncorrectFileTypeException("File must be of type markdown, ending with .md"); 59 | } 60 | 61 | try (final InputStream fileReader = FileReader.readFileInDirectory(filePath); 62 | final InputStreamReader reader = new InputStreamReader(fileReader, StandardCharsets.UTF_8); 63 | final BufferedReader bufferedReader = new BufferedReader(reader)) { 64 | 65 | return bufferedReader 66 | .lines() 67 | .collect(Collectors.joining("\n")); 68 | } catch (IOException | InterruptedException ignored) { 69 | throw new FileUnreadableException("Unable to read file"); 70 | } 71 | } 72 | 73 | public static InputStream readFileInDirectory(final FilePath file) throws IOException, InterruptedException { 74 | if (file == null) throw new IOException(); 75 | if (!file.exists()) throw new FileNotFoundException(); 76 | return file.read(); 77 | } 78 | 79 | public static FilePath filePath(final FilePath basePath, final String additionalFilePath) { 80 | FilePath filePath = basePath; 81 | if (additionalFilePath != null) filePath = new FilePath(basePath, additionalFilePath); 82 | return filePath; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target* 2 | 3 | # General 4 | .DS_Store 5 | .AppleDouble 6 | .LSOverride 7 | 8 | # Icon must end with two \r 9 | Icon 10 | 11 | # Thumbnails 12 | ._* 13 | 14 | # Files that might appear in the root of a volume 15 | .DocumentRevisions-V100 16 | .fseventsd 17 | .Spotlight-V100 18 | .TemporaryItems 19 | .Trashes 20 | .VolumeIcon.icns 21 | .com.apple.timemachine.donotpresent 22 | 23 | # Directories potentially created on remote AFP share 24 | .AppleDB 25 | .AppleDesktop 26 | Network Trash Folder 27 | Temporary Items 28 | .apdisk 29 | 30 | *~ 31 | 32 | # temporary files which can be created if a process still has a handle open of a deleted file 33 | .fuse_hidden* 34 | 35 | # KDE directory preferences 36 | .directory 37 | 38 | # Linux trash folder which might appear on any partition or disk 39 | .Trash-* 40 | 41 | # .nfs files are created when an open file is removed but is still being accessed 42 | .nfs* 43 | 44 | Cache files for Sublime Text 45 | *.tmlanguage.cache 46 | *.tmPreferences.cache 47 | *.stTheme.cache 48 | 49 | # Workspace files are user-specific 50 | *.sublime-workspace 51 | 52 | # Project files should be checked into the repository, unless a significant 53 | # proportion of contributors will probably not be using Sublime Text 54 | # *.sublime-project 55 | 56 | # SFTP configuration file 57 | sftp-config.json 58 | 59 | # Package control specific files 60 | Package Control.last-run 61 | Package Control.ca-list 62 | Package Control.ca-bundle 63 | Package Control.system-ca-bundle 64 | Package Control.cache/ 65 | Package Control.ca-certs/ 66 | Package Control.merged-ca-bundle 67 | Package Control.user-ca-bundle 68 | oscrypto-ca-bundle.crt 69 | bh_unicode_properties.cache 70 | 71 | # Sublime-github package stores a github token in this file 72 | # https://packagecontrol.io/packages/sublime-github 73 | GitHub.sublime-settings 74 | 75 | # Windows thumbnail cache files 76 | Thumbs.db 77 | Thumbs.db:encryptable 78 | ehthumbs.db 79 | ehthumbs_vista.db 80 | 81 | # Dump file 82 | *.stackdump 83 | 84 | # Folder config file 85 | [Dd]esktop.ini 86 | 87 | # Recycle Bin used on file shares 88 | $RECYCLE.BIN/ 89 | 90 | # Windows Installer files 91 | *.cab 92 | *.msi 93 | *.msix 94 | *.msm 95 | *.msp 96 | 97 | # Windows shortcuts 98 | *.lnk 99 | 100 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 101 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 102 | 103 | .idea/* 104 | 105 | # User-specific stuff 106 | .idea/**/workspace.xml 107 | .idea/**/tasks.xml 108 | .idea/**/usage.statistics.xml 109 | .idea/**/dictionaries 110 | .idea/**/shelf 111 | 112 | # Generated files 113 | .idea/**/contentModel.xml 114 | 115 | # Sensitive or high-churn files 116 | .idea/**/dataSources/ 117 | .idea/**/dataSources.ids 118 | .idea/**/dataSources.local.xml 119 | .idea/**/sqlDataSources.xml 120 | .idea/**/dynamic.xml 121 | .idea/**/uiDesigner.xml 122 | .idea/**/dbnavigator.xml 123 | 124 | # Gradle 125 | .idea/**/gradle.xml 126 | .idea/**/libraries 127 | 128 | # Gradle and Maven with auto-import 129 | # When using Gradle or Maven with auto-import, you should exclude module files, 130 | # since they will be recreated, and may cause churn. Uncomment if using 131 | # auto-import. 132 | # .idea/modules.xml 133 | # .idea/*.iml 134 | # .idea/modules 135 | # *.iml 136 | # *.ipr 137 | 138 | # CMake 139 | cmake-build-*/ 140 | 141 | # Mongo Explorer plugin 142 | .idea/**/mongoSettings.xml 143 | 144 | # File-based project format 145 | *.iws 146 | 147 | # IntelliJ 148 | out/ 149 | 150 | # mpeltonen/sbt-idea plugin 151 | .idea_modules/ 152 | 153 | # JIRA plugin 154 | atlassian-ide-plugin.xml 155 | 156 | # Cursive Clojure plugin 157 | .idea/replstate.xml 158 | .idea/ 159 | 160 | # Crashlytics plugin (for Android Studio and IntelliJ) 161 | com_crashlytics_export_strings.xml 162 | crashlytics.properties 163 | crashlytics-build.properties 164 | fabric.properties 165 | 166 | # Editor-based Rest Client 167 | .idea/httpRequests 168 | 169 | # Android studio 3.1+ serialized cache file 170 | .idea/caches/build_file_checksums.ser 171 | 172 | .gradle 173 | /build/ 174 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Apimap.io Jenkins Plugin 2 | === 3 | 4 | 🎉 **Welcome** 🎉 5 | 6 | This is a part of the Apimap.io project https://github.com/apimap, a freestanding solution to keep track of all functionality a company 7 | provides through an API. It is a push based system, connected with your build pipeline or manually updated using our CLI. 8 | 9 | > **Application programming interface (API)**: Point of functional integration between two or more systems connected 10 | > through commonly known standards 11 | 12 | **Why is this project useful?** Lost track of all the API functionality provided inside your organization? Don't want 13 | to be tied to an API proxy or management solution? The Apimap.io project uploads, indexes and enables discoverability of all 14 | your organizations APIs. We care about the source code, removing the limitation of where the API is hosted and how your 15 | network is constructed. 16 | 17 | 18 | ## Table of Contents 19 | 20 | * [Project Components](#project-components) 21 | * [Build and Run](#build-and-run) 22 | * [Contributing](#contributing) 23 | 24 | I want to know more of the technical details and implementation guides: [DEVELOPER.md](DEVELOPER.md) 25 | 26 | ## Project Components 27 | ___ 28 | This is a complete software solution consisting of a collection of freestanding components. Use only the components you 29 | find useful, create the rest to custom fit your organization. 30 | 31 | - A **Developer Portal** with wizards and implementation information 32 | - A **Discovery Portal** to display APIs and filter search results 33 | - An **API** to accommodate all the information 34 | - A **Jenkins plugin** to automate information parsing and upload 35 | - A **CLI** to enable manual information uploads 36 | 37 | ## Build and Run 38 | ___ 39 | 40 | This is the Jenkins plugin, created to automatically upload metadata and taxonomy files. 41 | 42 | 43 | ### Jenkinsfile 44 | 45 | The following is an example of how to use the plugin inside a Jenkinsfile 46 | 47 | #### Default values (used if not overwritten when used) 48 | 49 | The plugin is configured by default with the following values. If a value is not overwritten with another value the defaults will be used. 50 | 51 | | Argument | Default Value | 52 | |----------------|--------------------------| 53 | | metadataFile | "apimap/metadata.apimap" | 54 | | taxonomyFile | "apimap/taxonomy.apimap" | 55 | | readmeFile | "README.md" | 56 | | changelogFile | "CHANGELOG.md" | 57 | | repositoryURL | empty | 58 | 59 | #### Pipeline as Code 60 | 61 | The following example show how to use the plugin in a Pipeline as Code environment. 62 | 63 | ```groovy 64 | pipeline { 65 | agent any 66 | stages{ 67 | stage('Get source'){ 68 | steps{ 69 | git 'https://....' 70 | } 71 | } 72 | stage('Validate'){ 73 | steps{ 74 | script{ 75 | def result = validateAPI metadataFile: 'apimap/metadata.apimap', 76 | taxonomyFile: 'apimap/taxonomy.apimap' 77 | 78 | echo result.getDescription() 79 | } 80 | } 81 | } 82 | stage('Publish'){ 83 | steps{ 84 | script{ 85 | def result = publishAPI metadataFile: 'apimap/metadata.apimap', 86 | taxonomyFile: 'apimap/taxonomy.apimap', 87 | readmeFile: 'README.md', 88 | changelogFile: 'CHANGELOG.md', 89 | repositoryURL: scm.getUserRemoteConfigs()[0].getUrl() 90 | 91 | echo result.getStatus().toString() 92 | echo result.getDescription() 93 | echo result.getToken() 94 | } 95 | } 96 | } 97 | } 98 | } 99 | ``` 100 | 101 | #### Build JAR 102 | 103 | Based on Java the easiest way to build the artifact is using **package** 104 | 105 | > mvnw package 106 | 107 | If you build this component on anything newer than Java 8, please add the following parameter. This is due to a limitation in one of the jenkins dependencies. 108 | 109 | > -Dmaven.test.skip 110 | 111 | #### Requirements 112 | 113 | Java version 8 or newer. 114 | 115 | 116 | ## Contributing 117 | ___ 118 | 119 | Read [howto contribute](CONTRIBUTING.md) to this project. -------------------------------------------------------------------------------- /src/main/java/io/apimap/plugin/jenkins/ApiMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package io.apimap.plugin.jenkins; 21 | 22 | import hudson.Extension; 23 | import hudson.Util; 24 | import hudson.model.AbstractProject; 25 | import hudson.model.Job; 26 | import hudson.model.JobProperty; 27 | import hudson.model.JobPropertyDescriptor; 28 | import hudson.util.FormValidation; 29 | import io.apimap.api.rest.ApiCollectionRootRestEntity; 30 | import io.apimap.api.rest.jsonapi.JsonApiRestResponseWrapper; 31 | import io.apimap.client.IRestClient; 32 | import io.apimap.client.RestClientConfiguration; 33 | import io.apimap.plugin.jenkins.utils.RestClientUtil; 34 | import jenkins.model.Jenkins; 35 | import net.sf.json.JSONObject; 36 | import org.kohsuke.stapler.QueryParameter; 37 | import org.kohsuke.stapler.StaplerRequest; 38 | 39 | public class ApiMap extends JobProperty> { 40 | 41 | @Extension 42 | public static final ApiMapDescriptorImpl DESCRIPTOR = new ApiMapDescriptorImpl(); 43 | 44 | @Override 45 | public JobPropertyDescriptor getDescriptor() { 46 | return DESCRIPTOR; 47 | } 48 | 49 | public static final class ApiMapDescriptorImpl extends JobPropertyDescriptor { 50 | public static final String BUILD_STEP_DISPLAY_NAME = "ApiMap.io"; 51 | 52 | private String url; 53 | private boolean updateBuildStatus; 54 | private boolean dryRunMode; 55 | private boolean debugMode; 56 | private boolean allowReadmeUpload; 57 | private boolean allowChangelogUpload; 58 | 59 | public ApiMapDescriptorImpl() { 60 | super(ApiMap.class); 61 | load(); 62 | } 63 | 64 | @Override 65 | public boolean isApplicable(Class aClass) { 66 | return true; //Supports all types of projects 67 | } 68 | 69 | @Override 70 | public String getDisplayName() { 71 | return BUILD_STEP_DISPLAY_NAME; 72 | } 73 | 74 | @Override 75 | public boolean configure(StaplerRequest req, JSONObject formData) throws FormException { 76 | req.bindJSON(this, formData); 77 | save(); 78 | return super.configure(req, formData); 79 | } 80 | 81 | public String getUrl() { 82 | return url; 83 | } 84 | 85 | public void setUrl(String url) { 86 | this.url = url; 87 | } 88 | 89 | public boolean updateBuildStatus() { 90 | return updateBuildStatus; 91 | } 92 | 93 | public void setUpdateBuildStatus(boolean updateBuildStatus) { 94 | this.updateBuildStatus = updateBuildStatus; 95 | } 96 | 97 | public boolean isDryRunMode() { 98 | return dryRunMode; 99 | } 100 | 101 | public void setDryRunMode(boolean dryRunMode) { 102 | this.dryRunMode = dryRunMode; 103 | } 104 | 105 | public boolean isDebugMode() { 106 | return debugMode; 107 | } 108 | 109 | public void setDebugMode(boolean debugMode) { 110 | this.debugMode = debugMode; 111 | } 112 | 113 | public boolean isUpdateBuildStatus() { 114 | return updateBuildStatus; 115 | } 116 | 117 | public boolean isAllowReadmeUpload() { 118 | return allowReadmeUpload; 119 | } 120 | 121 | public void setAllowReadmeUpload(boolean allowReadmeUpload) { 122 | this.allowReadmeUpload = allowReadmeUpload; 123 | } 124 | 125 | public boolean isAllowChangelogUpload() { 126 | return allowChangelogUpload; 127 | } 128 | 129 | public void setAllowChangelogUpload(boolean allowChangelogUpload) { 130 | this.allowChangelogUpload = allowChangelogUpload; 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /DEVELOPER.md: -------------------------------------------------------------------------------- 1 | Apimap.io Jenkins Plugin 2 | ===== 3 | 4 | 🥳 **Happy Coding** 🥳 5 | 6 | This section is targeted to developers that want to use the Jenkins Plugin provided by the project. 7 | 8 | ## Table of Contents 9 | 10 | * [Introduction](#introduction) 11 | * [Getting Started](#getting-started) 12 | * [Other Resources](#other-resources) 13 | 14 | ## Introduction 15 | 16 | ### Global Configuration 17 | 18 | #### Debug Mode 19 | 20 | More extensive logging. Please note that the output is generated using System.out.println and will be printed to STDOUT. 21 | 22 | #### Dryrun Mode 23 | 24 | Does not communicate to any APIs on any actions and returns a default object from create resources. 25 | 26 | #### Configuration Options 27 | 28 | ##### Update Global Build Status 29 | 30 | | Status | Description | 31 | |-----------------|------------------------------------------------------| 32 | | Enabled | Updated the global build status to match step result | 33 | | Disabled | Only returns the validation result as a object | 34 | 35 | #### ApiMap.io instance URL 36 | 37 | Complete URL to the API instance the build system should connect to. 38 | 39 | > E.g. http://127.0.0.1:8080 40 | 41 | ## Getting Started 42 | 43 | This plugin is created to be used with Pipeline-as-Code and returns a result object depending on the step activated. 44 | 45 | ### Results from the Validate Step 46 | 47 | The following Java-object is returned from the validate step: 48 | 49 | | Variable | Description | 50 | |-------------|----------------------------------------------------------------------------------------------| 51 | | status | The status of the action. If the API was created, updated, something failed or if it crashed | 52 | | description | An explanation to the status | 53 | 54 | ```java 55 | public class ValidateResult { 56 | public enum Status { 57 | VALID, 58 | MISSING, 59 | INVALID, 60 | ABORTED, 61 | FAILED, 62 | UNKNOWN 63 | } 64 | 65 | private final Status status; 66 | private final String description; 67 | 68 | public ValidateResult(Status status, String description) { 69 | this.status = status; 70 | this.description = description; 71 | } 72 | 73 | @Whitelisted 74 | public Status getStatus() { 75 | return status; 76 | } 77 | 78 | @Whitelisted 79 | public String getDescription() { 80 | return description; 81 | } 82 | } 83 | ``` 84 | 85 | ### Results from the Publish Step 86 | 87 | The following Java-object is returned from the publish step: 88 | 89 | | Variable | Description | 90 | |-------------|-------------------------------------------------------------------------------------------------------------------------| 91 | | status | The status of the action. If the API was created, updated, something failed or if it crashed | 92 | | description | An explanation to the status | 93 | | token | If the status is created theres is also a token returned with the result. This token must be used in any future updates | 94 | 95 | > Note: Do not use the token or description to test if the API is created or updated. Use the status ENUM to determine the status. 96 | 97 | ```java 98 | public class PublishResult { 99 | public enum Status { 100 | CREATED, 101 | UPDATED, 102 | FAILED, 103 | ABORTED, 104 | UNKNOWN 105 | } 106 | 107 | private final Status status; 108 | private final String description; 109 | private final String token; 110 | 111 | public PublishResult(Status status, String description) { 112 | this.status = status; 113 | this.description = description; 114 | this.token = null; 115 | } 116 | 117 | public PublishResult(Status status, String description, String token) { 118 | this.status = status; 119 | this.description = description; 120 | this.token = token; 121 | } 122 | 123 | @Whitelisted 124 | public Status getStatus() { 125 | return status; 126 | } 127 | 128 | @Whitelisted 129 | public String getDescription() { 130 | return description; 131 | } 132 | 133 | @Whitelisted 134 | public String getToken() { 135 | return token; 136 | } 137 | } 138 | ``` 139 | 140 | ## Other Resources 141 | ___ 142 | 143 | - [Hypermedia as the Engine of Application State (HATEOAS) ](https://en.wikipedia.org/wiki/HATEOAS) 144 | - [JSON:API — A specification for building APIs in JSON](https://jsonapi.org/) 145 | - [Jenkins Plugin development](https://www.jenkins.io/doc/developer/plugin-development/) 146 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /src/main/java/io/apimap/plugin/jenkins/step/PublishStep.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package io.apimap.plugin.jenkins.step; 21 | 22 | import edu.umd.cs.findbugs.annotations.NonNull; 23 | import hudson.Extension; 24 | import hudson.model.Run; 25 | import hudson.model.TaskListener; 26 | import io.apimap.plugin.jenkins.step.publish.PublishStepExecution; 27 | import org.jenkinsci.Symbol; 28 | import org.jenkinsci.plugins.workflow.steps.Step; 29 | import org.jenkinsci.plugins.workflow.steps.StepContext; 30 | import org.jenkinsci.plugins.workflow.steps.StepDescriptor; 31 | import org.jenkinsci.plugins.workflow.steps.StepExecution; 32 | import org.kohsuke.stapler.DataBoundConstructor; 33 | import org.kohsuke.stapler.DataBoundSetter; 34 | 35 | import java.io.Serializable; 36 | import java.util.HashSet; 37 | import java.util.Set; 38 | 39 | public class PublishStep extends Step implements Serializable { 40 | 41 | public static final String BUILD_STEP_DISPLAY_NAME = "File content publishing"; 42 | public static final String BUILD_STEP_FUNCTION_NAME = "publishAPI"; 43 | 44 | public static final String DEFAULT_METADATA_FILE_VALUE = "apimap/metadata.apimap"; 45 | public static final String DEFAULT_TAXONOMY_FILE_VALUE = "apimap/taxonomy.apimap"; 46 | public static final String DEFAULT_README_FILE_VALUE = "README.md"; 47 | public static final String DEFAULT_CHANGELOG_FILE_VALUE = "CHANGELOG.md"; 48 | 49 | public String metadataFile; 50 | public String taxonomyFile; 51 | public String readmeFile; 52 | public String changelogFile; 53 | public String repositoryURL; 54 | public String token; 55 | 56 | @DataBoundSetter 57 | public void setMetadataFile(final String metadataFile) { 58 | this.metadataFile = metadataFile; 59 | } 60 | 61 | public String getMetadataFile() { 62 | if(metadataFile == null) return DEFAULT_METADATA_FILE_VALUE; 63 | return metadataFile; 64 | } 65 | 66 | @DataBoundSetter 67 | public void setTaxonomyFile(final String taxonomyFile) { 68 | this.taxonomyFile = taxonomyFile; 69 | } 70 | 71 | public String getTaxonomyFile() { 72 | if(taxonomyFile == null) return DEFAULT_TAXONOMY_FILE_VALUE; 73 | return taxonomyFile; 74 | } 75 | 76 | @DataBoundSetter 77 | public void setRepositoryURL(final String repositoryURL) { 78 | this.repositoryURL = repositoryURL; 79 | } 80 | 81 | public String getRepositoryURL() { 82 | return repositoryURL; 83 | } 84 | 85 | @DataBoundSetter 86 | public void setToken(final String token) { 87 | this.token = token; 88 | } 89 | 90 | public String getToken() { 91 | return token; 92 | } 93 | 94 | @DataBoundSetter 95 | public void setReadmeFile(final String readmeFile) { 96 | this.readmeFile = readmeFile; 97 | } 98 | 99 | public String getReadmeFile() { 100 | if(readmeFile == null) return DEFAULT_README_FILE_VALUE; 101 | return readmeFile; 102 | } 103 | 104 | @DataBoundSetter 105 | public void setChangelogFile(final String changelogFile) { 106 | this.changelogFile = changelogFile; 107 | } 108 | 109 | public String getChangelogFile() { 110 | if(changelogFile == null) return DEFAULT_CHANGELOG_FILE_VALUE; 111 | return changelogFile; 112 | } 113 | 114 | @DataBoundConstructor 115 | public PublishStep(final String metadataFile, 116 | final String taxonomyFile, 117 | final String readmeFile, 118 | final String changelogFile, 119 | final String token, 120 | final String repositoryURL) { 121 | this.metadataFile = metadataFile; 122 | this.taxonomyFile = taxonomyFile; 123 | this.readmeFile = readmeFile; 124 | this.changelogFile = changelogFile; 125 | this.token = token; 126 | this.repositoryURL = repositoryURL; 127 | } 128 | 129 | @Override 130 | public StepExecution start(final StepContext stepContext) throws Exception { 131 | return new PublishStepExecution(this, stepContext); 132 | } 133 | 134 | @Symbol(BUILD_STEP_FUNCTION_NAME) 135 | @Extension 136 | public static final class DescriptorImpl extends StepDescriptor { 137 | @Override 138 | public Set> getRequiredContext() { 139 | Set> contexts = new HashSet<>(); 140 | contexts.add(TaskListener.class); 141 | contexts.add(Run.class); 142 | return contexts; 143 | } 144 | 145 | @Override 146 | public String getFunctionName() { 147 | return BUILD_STEP_FUNCTION_NAME; 148 | } 149 | 150 | @NonNull 151 | @Override 152 | public String getDisplayName() { 153 | return BUILD_STEP_DISPLAY_NAME; 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/main/java/io/apimap/plugin/jenkins/step/validate/ValidateStepExecution.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package io.apimap.plugin.jenkins.step.validate; 21 | 22 | import com.fasterxml.jackson.core.JsonParseException; 23 | import com.fasterxml.jackson.databind.JsonMappingException; 24 | import hudson.FilePath; 25 | import hudson.model.Result; 26 | import io.apimap.file.metadata.MetadataFile; 27 | import io.apimap.file.taxonomy.TaxonomyFile; 28 | import io.apimap.plugin.jenkins.ApiMap; 29 | import io.apimap.plugin.jenkins.output.ValidateResult; 30 | import io.apimap.plugin.jenkins.step.ValidateStep; 31 | import io.apimap.plugin.jenkins.utils.FileReader; 32 | import jenkins.model.Jenkins; 33 | import org.jenkinsci.plugins.workflow.steps.StepContext; 34 | import org.jenkinsci.plugins.workflow.steps.SynchronousStepExecution; 35 | 36 | import java.io.IOException; 37 | import java.util.logging.Level; 38 | import java.util.logging.Logger; 39 | 40 | public class ValidateStepExecution extends SynchronousStepExecution { 41 | private static final Logger LOGGER = Logger.getLogger(ValidateStepExecution.class.getName()); 42 | 43 | public static final String FILEPATH_IS_A_NULL_OBJECT = "Filepath returned as a null object"; 44 | public static final String UNABLE_TO_READ_METADATA_ERROR_MESSAGE = "Unable read metadata content"; 45 | public static final String METADATA_FILE_NOT_FOUND = "Unable to read metadata file"; 46 | public static final String UNABLE_TO_PARSE_METADATA_ERROR_MESSAGE = "Unable to map metadata file values"; 47 | public static final String TAXONOMY_FILE_NOT_FOUND = "Unable to read taxonomy file"; 48 | public static final String UNABLE_TO_READ_TAXONOMY_ERROR_MESSAGE = "Unable read taxonomy content"; 49 | public static final String UNABLE_TO_PARSE_TAXONOMY_ERROR_MESSAGE = "Unable to map taxonomy file values"; 50 | public static final String STEP_COMPLETED_SUCCESSFULLY = "Successfully validated information"; 51 | 52 | private static final long serialVersionUID = 1L; 53 | 54 | private final ValidateStep step; 55 | 56 | public ValidateStepExecution(final ValidateStep step, 57 | final StepContext context){ 58 | super(context); 59 | this.step = step; 60 | } 61 | 62 | protected ValidateResult failure(final String description, 63 | final ValidateResult.Status result){ 64 | final ApiMap.ApiMapDescriptorImpl descImpl = (ApiMap.ApiMapDescriptorImpl) Jenkins.getInstance().getDescriptorByName(ApiMap.class.getName()); 65 | 66 | if (descImpl.updateBuildStatus()) { 67 | getContext().setResult(Result.FAILURE); 68 | getContext().onFailure(new IOException(description)); 69 | } 70 | 71 | return new ValidateResult(result, description); 72 | } 73 | 74 | protected ValidateResult success(final String description){ 75 | final ApiMap.ApiMapDescriptorImpl descImpl = (ApiMap.ApiMapDescriptorImpl) Jenkins.getInstance().getDescriptorByName(ApiMap.class.getName()); 76 | 77 | final ValidateResult returnValue = new ValidateResult(ValidateResult.Status.VALID, description); 78 | 79 | if(descImpl.updateBuildStatus()) { 80 | getContext().setResult(Result.SUCCESS); 81 | getContext().onSuccess(returnValue); 82 | } 83 | 84 | return returnValue; 85 | } 86 | 87 | @Override 88 | protected ValidateResult run() throws Exception { 89 | final FilePath path = getContext().get(FilePath.class); 90 | if(path == null) { return failure(FILEPATH_IS_A_NULL_OBJECT, ValidateResult.Status.MISSING); } 91 | 92 | LOGGER.log(Level.FINER, "Reading metadata file"); 93 | try { 94 | final MetadataFile metadataFile = FileReader.metadataFile(FileReader.filePath(path, this.step.getMetadataFile())); 95 | if (metadataFile == null) { 96 | return failure(UNABLE_TO_READ_METADATA_ERROR_MESSAGE, ValidateResult.Status.MISSING); 97 | } 98 | } catch (JsonMappingException e) { 99 | return failure(UNABLE_TO_PARSE_METADATA_ERROR_MESSAGE, ValidateResult.Status.INVALID); 100 | } catch (JsonParseException e) { 101 | return failure(UNABLE_TO_READ_METADATA_ERROR_MESSAGE, ValidateResult.Status.FAILED); 102 | } catch (IOException e) { 103 | return failure(METADATA_FILE_NOT_FOUND, ValidateResult.Status.MISSING); 104 | } 105 | 106 | LOGGER.log(Level.INFO, "Reading taxonomy file"); 107 | try { 108 | final TaxonomyFile taxonomyFile = FileReader.taxonomyFile(FileReader.filePath(path, this.step.getTaxonomyFile())); 109 | if (taxonomyFile == null) { 110 | return failure(UNABLE_TO_READ_TAXONOMY_ERROR_MESSAGE, ValidateResult.Status.MISSING); 111 | } 112 | } catch (JsonMappingException e) { 113 | return failure(UNABLE_TO_PARSE_TAXONOMY_ERROR_MESSAGE, ValidateResult.Status.INVALID); 114 | } catch (JsonParseException e) { 115 | return failure(UNABLE_TO_READ_TAXONOMY_ERROR_MESSAGE, ValidateResult.Status.FAILED); 116 | } catch (IOException e) { 117 | return failure(TAXONOMY_FILE_NOT_FOUND, ValidateResult.Status.MISSING); 118 | } 119 | 120 | return success(STEP_COMPLETED_SUCCESSFULLY); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/test/java/io/apimap/FileReaderTest.java: -------------------------------------------------------------------------------- 1 | package io.apimap; 2 | 3 | import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; 4 | import hudson.FilePath; 5 | import io.apimap.api.rest.ApiDataRestEntity; 6 | import io.apimap.file.exceptions.MissingRequiredFieldException; 7 | import io.apimap.file.exceptions.UnsupportedVersionException; 8 | import io.apimap.file.metadata.MetadataFile; 9 | import io.apimap.file.taxonomy.TaxonomyFile; 10 | import io.apimap.plugin.jenkins.exceptions.FileUnreadableException; 11 | import io.apimap.plugin.jenkins.utils.FileReader; 12 | import org.apache.tools.ant.filters.StringInputStream; 13 | import org.junit.Assert; 14 | import org.junit.Test; 15 | import org.mockito.ArgumentMatchers; 16 | import org.mockito.MockedStatic; 17 | import org.mockito.Mockito; 18 | 19 | import java.io.FileNotFoundException; 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | import static org.mockito.ArgumentMatchers.any; 25 | 26 | public class FileReaderTest { 27 | @Test 28 | public void readMetadataFile_didFailWithNotFound() throws MissingRequiredFieldException, IOException, InterruptedException, UnsupportedVersionException { 29 | Assert.assertThrows(FileNotFoundException.class, 30 | ()->{ 31 | FileReader.metadataFile(null); 32 | }); 33 | } 34 | 35 | @Test 36 | public void readTaxonomyFile_didFailWithNotFound() throws MissingRequiredFieldException, IOException, InterruptedException, UnsupportedVersionException { 37 | Assert.assertThrows(FileNotFoundException.class, 38 | ()->{ 39 | FileReader.taxonomyFile(null); 40 | }); 41 | } 42 | 43 | @Test 44 | public void readMetadataFile_didFailWithJsonParsing() { 45 | FilePath filePath = Mockito.mock(FilePath.class); 46 | 47 | MockedStatic fileReader = Mockito.mockStatic(FileReader.class, Mockito.CALLS_REAL_METHODS); 48 | StringInputStream inputStream = new StringInputStream("{" + 49 | "\"api catalog version\": 1," + 50 | "\"failure\":" + 51 | "{\"name\":\"name\"," + 52 | "\"visibility\":\"visibility\"," + 53 | "\"description\":\"description\"," + 54 | "\"api version\":\"apiVersion\"," + 55 | "\"release status\":\"releaseStatus\"," + 56 | "\"system identifier\":\"systemIdentifier\"," + 57 | "\"documentation\":[\"url1\",\"url2\"]," + 58 | "\"interface specification\":\"interfaceSpecification\"," + 59 | "\"interface description language\":\"interfaceDescriptionLanguage\"," + 60 | "\"architecture layer\":\"architectureLayer\"," + 61 | "\"business unit\":\"businessUnit\"}}}" 62 | ); 63 | fileReader.when(() -> FileReader.readFileInDirectory(any())).thenReturn(inputStream); 64 | 65 | Assert.assertThrows(io.apimap.plugin.jenkins.exceptions.FileUnreadableException.class, 66 | ()->{ 67 | MetadataFile object = FileReader.metadataFile(filePath); 68 | fileReader.close(); 69 | 70 | }); 71 | } 72 | 73 | @Test 74 | public void readMetadataFile_didSucceed() throws MissingRequiredFieldException, IOException, InterruptedException, UnsupportedVersionException, FileUnreadableException { 75 | FilePath filePath = Mockito.mock(FilePath.class); 76 | 77 | MockedStatic fileReader = Mockito.mockStatic(FileReader.class, Mockito.CALLS_REAL_METHODS); 78 | StringInputStream inputStream = new StringInputStream("{" + 79 | "\"api catalog version\": 1," + 80 | "\"data\":" + 81 | "{\"name\":\"name\"," + 82 | "\"visibility\":\"visibility\"," + 83 | "\"description\":\"description\"," + 84 | "\"api version\":\"apiVersion\"," + 85 | "\"release status\":\"releaseStatus\"," + 86 | "\"system identifier\":\"systemIdentifier\"," + 87 | "\"documentation\":[\"url1\",\"url2\"]," + 88 | "\"interface specification\":\"interfaceSpecification\"," + 89 | "\"interface description language\":\"interfaceDescriptionLanguage\"," + 90 | "\"architecture layer\":\"architectureLayer\"," + 91 | "\"business unit\":\"businessUnit\"}}}" 92 | ); 93 | fileReader.when(() -> FileReader.readFileInDirectory(any())).thenReturn(inputStream); 94 | 95 | MetadataFile object = FileReader.metadataFile(filePath); 96 | fileReader.close(); 97 | 98 | assertEquals("name", object.getData().getName()); 99 | assertEquals("visibility", object.getData().getVisibility()); 100 | assertEquals("description", object.getData().getDescription()); 101 | assertEquals("apiVersion", object.getData().getApiVersion()); 102 | assertEquals("releaseStatus", object.getData().getReleaseStatus()); 103 | assertEquals("systemIdentifier", object.getData().getSystemIdentifier()); 104 | assertEquals("interfaceSpecification", object.getData().getInterfaceSpecification()); 105 | assertEquals("interfaceDescriptionLanguage", object.getData().getInterfaceDescriptionLanguage()); 106 | assertEquals("architectureLayer", object.getData().getArchitectureLayer()); 107 | assertEquals("businessUnit", object.getData().getBusinessUnit()); 108 | } 109 | 110 | //- 111 | @Test 112 | public void readTaxonomyFile_didFailWithJsonParsing() { 113 | FilePath filePath = Mockito.mock(FilePath.class); 114 | 115 | MockedStatic fileReader = Mockito.mockStatic(FileReader.class, Mockito.CALLS_REAL_METHODS); 116 | StringInputStream inputStream = new StringInputStream("{" + 117 | "\"api catalog version\": 1," + 118 | "\"failure\":" + 119 | "{\"taxonomy\": \"apimap\"," + 120 | "\"classifications\": [\"urn:apimap:1\"]}}}" 121 | ); 122 | fileReader.when(() -> FileReader.readFileInDirectory(any())).thenReturn(inputStream); 123 | fileReader.close(); 124 | 125 | Assert.assertThrows(io.apimap.plugin.jenkins.exceptions.FileUnreadableException.class, 126 | ()->{ 127 | TaxonomyFile object = FileReader.taxonomyFile(filePath); 128 | fileReader.close(); 129 | 130 | }); 131 | } 132 | 133 | @Test 134 | public void readTaxonomyFile_didSucceed() throws MissingRequiredFieldException, IOException, InterruptedException, UnsupportedVersionException, FileUnreadableException { 135 | FilePath filePath = Mockito.mock(FilePath.class); 136 | 137 | MockedStatic fileReader = Mockito.mockStatic(FileReader.class, Mockito.CALLS_REAL_METHODS); 138 | StringInputStream inputStream = new StringInputStream("{" + 139 | "\"api catalog version\": 1," + 140 | "\"data\":" + 141 | "{\"taxonomy\": \"apimap\", \"classifications\": [\"urn:apimap:1\"]}}}" 142 | ); 143 | fileReader.when(() -> FileReader.readFileInDirectory(any())).thenReturn(inputStream); 144 | 145 | TaxonomyFile object = FileReader.taxonomyFile(filePath); 146 | fileReader.close(); 147 | 148 | assertEquals("apimap", object.getData().getTaxonomy()); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | org.jenkins-ci.plugins 8 | plugin 9 | 4.41 10 | 11 | 12 | 13 | 14 | 15 | Apache License, Version 2.0 16 | http://www.apache.org/licenses/LICENSE-2.0.txt 17 | repo 18 | 19 | 20 | 21 | 22 | 23 | msulland 24 | Magnus Sulland 25 | magnus@apperiet.no 26 | 27 | maintainer 28 | 29 | 30 | 31 | 32 | io.jenkins.plugins 33 | apimap 34 | Apimap.io 35 | ${revision}${changelist} 36 | hpi 37 | Enables automated publishing of API metadata to your Apimap.io instance 38 | https://github.com/jenkinsci/apimap-plugin 39 | 40 | 41 | 1 42 | -SNAPSHOT 43 | 2.300 44 | UTF-8 45 | 3.0.5 46 | true 47 | 48 | 49 | 50 | 51 | 52 | org.jenkins-ci.tools 53 | maven-hpi-plugin 54 | 55 | true 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | org.jenkins-ci.plugins.workflow 64 | workflow-step-api 65 | 2.24 66 | 67 | 68 | org.jenkins-ci.plugins 69 | script-security 70 | 1.78 71 | 72 | 73 | org.apache.httpcomponents.client5 74 | httpclient5 75 | 5.1.3 76 | 77 | 78 | org.mockito 79 | mockito-core 80 | 4.6.1 81 | test 82 | 83 | 84 | com.fasterxml.jackson.core 85 | jackson-databind 86 | 2.13.2.1 87 | 88 | 89 | javax.json.bind 90 | javax.json.bind-api 91 | 1.0 92 | 93 | 94 | javax.json 95 | javax.json-api 96 | 1.1.4 97 | 98 | 99 | javax.servlet 100 | javax.servlet-api 101 | 4.0.1 102 | 103 | 104 | commons-io 105 | commons-io 106 | 2.11.0 107 | 108 | 109 | io.jenkins.tools.bom 110 | bom-2.303.x 111 | 950.v396cb834de1e 112 | pom 113 | 114 | 115 | io.apimap.client 116 | rest-client 117 | 3.0.1 118 | 119 | 120 | io.apimap.file 121 | file-interface 122 | 1.0 123 | 124 | 125 | io.apimap.api 126 | rest-interface 127 | 2.2.0 128 | 129 | 130 | org.jenkins-ci.main 131 | jenkins-core 132 | 2.319.2 133 | 134 | 135 | org.mockito 136 | mockito-inline 137 | 4.0.0 138 | test 139 | 140 | 141 | 142 | 143 | 144 | lib-rest-client 145 | REST Client 146 | file:///${project.basedir}/lib 147 | default 148 | 149 | true 150 | always 151 | 152 | 153 | true 154 | never 155 | 156 | 157 | 158 | lib-file-interface 159 | File Interface 160 | file:///${project.basedir}/lib 161 | default 162 | 163 | true 164 | always 165 | 166 | 167 | true 168 | never 169 | 170 | 171 | 172 | lib-rest-interface 173 | REST Interface 174 | file:///${project.basedir}/lib 175 | default 176 | 177 | true 178 | always 179 | 180 | 181 | true 182 | never 183 | 184 | 185 | 186 | repo.jenkins-ci.org 187 | Jenkins CI 188 | https://repo.jenkins-ci.org/public/ 189 | default 190 | 191 | 192 | repo.maven.apache.org 193 | Central Repository 194 | https://repo.maven.apache.org/maven2/ 195 | default 196 | 197 | 198 | 199 | 200 | 201 | repo.jenkins-ci.org 202 | https://repo.jenkins-ci.org/public/ 203 | 204 | 205 | 206 | 207 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Mingw, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | ########################################################################################## 204 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 205 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 206 | ########################################################################################## 207 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 208 | if [ "$MVNW_VERBOSE" = true ]; then 209 | echo "Found .mvn/wrapper/maven-wrapper.jar" 210 | fi 211 | else 212 | if [ "$MVNW_VERBOSE" = true ]; then 213 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 214 | fi 215 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" 216 | while IFS="=" read key value; do 217 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 218 | esac 219 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 220 | if [ "$MVNW_VERBOSE" = true ]; then 221 | echo "Downloading from: $jarUrl" 222 | fi 223 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 224 | 225 | if command -v wget > /dev/null; then 226 | if [ "$MVNW_VERBOSE" = true ]; then 227 | echo "Found wget ... using wget" 228 | fi 229 | wget "$jarUrl" -O "$wrapperJarPath" 230 | elif command -v curl > /dev/null; then 231 | if [ "$MVNW_VERBOSE" = true ]; then 232 | echo "Found curl ... using curl" 233 | fi 234 | curl -o "$wrapperJarPath" "$jarUrl" 235 | else 236 | if [ "$MVNW_VERBOSE" = true ]; then 237 | echo "Falling back to using Java to download" 238 | fi 239 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 240 | if [ -e "$javaClass" ]; then 241 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 242 | if [ "$MVNW_VERBOSE" = true ]; then 243 | echo " - Compiling MavenWrapperDownloader.java ..." 244 | fi 245 | # Compiling the Java class 246 | ("$JAVA_HOME/bin/javac" "$javaClass") 247 | fi 248 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 249 | # Running the downloader 250 | if [ "$MVNW_VERBOSE" = true ]; then 251 | echo " - Running MavenWrapperDownloader.java ..." 252 | fi 253 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 254 | fi 255 | fi 256 | fi 257 | fi 258 | ########################################################################################## 259 | # End of extension 260 | ########################################################################################## 261 | 262 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 263 | if [ "$MVNW_VERBOSE" = true ]; then 264 | echo $MAVEN_PROJECTBASEDIR 265 | fi 266 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 267 | 268 | # For Cygwin, switch paths to Windows format before running java 269 | if $cygwin; then 270 | [ -n "$M2_HOME" ] && 271 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 272 | [ -n "$JAVA_HOME" ] && 273 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 274 | [ -n "$CLASSPATH" ] && 275 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 276 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 277 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 278 | fi 279 | 280 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 281 | 282 | exec "$JAVACMD" \ 283 | $MAVEN_OPTS \ 284 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 285 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 286 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 287 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2020 TELENOR NORGE AS 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /src/main/java/io/apimap/plugin/jenkins/step/publish/PublishStepExecution.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package io.apimap.plugin.jenkins.step.publish; 21 | 22 | import hudson.FilePath; 23 | import hudson.model.Result; 24 | import io.apimap.api.rest.ApiDataRestEntity; 25 | import io.apimap.api.rest.ApiVersionDataRestEntity; 26 | import io.apimap.api.rest.ClassificationDataRestEntity; 27 | import io.apimap.api.rest.ClassificationRootRestEntity; 28 | import io.apimap.api.rest.MetadataDataRestEntity; 29 | import io.apimap.api.rest.jsonapi.JsonApiRestResponseWrapper; 30 | import io.apimap.client.IRestClient; 31 | import io.apimap.client.RestClientConfiguration; 32 | import io.apimap.client.exception.IncorrectTokenException; 33 | import io.apimap.file.metadata.MetadataFile; 34 | import io.apimap.file.taxonomy.TaxonomyFile; 35 | import io.apimap.plugin.jenkins.ApiMap; 36 | import io.apimap.plugin.jenkins.exceptions.IncorrectFileTypeException; 37 | import io.apimap.plugin.jenkins.exceptions.PublishErrorException; 38 | import io.apimap.plugin.jenkins.output.PublishResult; 39 | import io.apimap.plugin.jenkins.step.PublishStep; 40 | import io.apimap.plugin.jenkins.utils.FileReader; 41 | import io.apimap.plugin.jenkins.utils.RestClientUtil; 42 | import jenkins.model.Jenkins; 43 | import org.apache.commons.lang.mutable.MutableBoolean; 44 | import org.apache.hc.core5.http.ContentType; 45 | import org.jenkinsci.plugins.workflow.steps.StepContext; 46 | import org.jenkinsci.plugins.workflow.steps.SynchronousStepExecution; 47 | 48 | import java.io.FileNotFoundException; 49 | import java.io.IOException; 50 | import java.util.ArrayList; 51 | import java.util.concurrent.atomic.AtomicReference; 52 | import java.util.function.Consumer; 53 | import java.util.logging.Level; 54 | import java.util.logging.Logger; 55 | import java.util.stream.Collectors; 56 | 57 | public class PublishStepExecution extends SynchronousStepExecution { 58 | private static final Logger LOGGER = Logger.getLogger(PublishStepExecution.class.getName()); 59 | 60 | public static final String FILEPATH_IS_A_NULL_OBJECT = "Filepath returned as a null object"; 61 | public static final String METADATA_FILE_MISSING_ERROR = "Unable to read metadata file"; 62 | public static final String TAXONOMY_FILE_MISSING_ERROR = "Unable to read taxonomy file"; 63 | public static final String README_FILE_MISSING_ERROR = "Unable to read README.md file"; 64 | public static final String CHANGELOG_FILE_MISSING_ERROR = "Unable to read CHANGELOG.md file"; 65 | public static final String UNABLE_TO_UPLOAD_METADATA_ERROR_MESSAGE = "Unable to upload metadata. Please contact your system administrator"; 66 | public static final String UNABLE_TO_UPLOAD_TAXONOMY_ERROR_MESSAGE = "Unable to upload taxonomy classifications. Please contact your system administrator"; 67 | public static final String UNABLE_TO_UPLOAD_README_ERROR_MESSAGE = "Unable to upload README.md classifications. Please contact your system administrator"; 68 | public static final String UNABLE_TO_UPLOAD_CHANGELOG_ERROR_MESSAGE = "Unable to upload CHANGELOG.md classifications. Please contact your system administrator"; 69 | public static final String MISSING_OR_INVALID_API_TOKEN_ERROR_MESSAGE = "Unable to find correct API token"; 70 | public static final String STEP_COMPLETED_SUCCESSFULLY = "Successfully published information"; 71 | public static final String MARKDOWN_FILE_FORMAT_REQUIRED = "File must be of type markdown, ending with .md"; 72 | 73 | 74 | private static final long serialVersionUID = 1L; 75 | 76 | private final PublishStep step; 77 | 78 | public PublishStepExecution(final PublishStep step, 79 | final StepContext context){ 80 | super(context); 81 | this.step = step; 82 | } 83 | 84 | protected PublishResult failure(final String description, 85 | final String token){ 86 | final ApiMap.ApiMapDescriptorImpl descImpl = (ApiMap.ApiMapDescriptorImpl) Jenkins.getInstance().getDescriptorByName(ApiMap.class.getName()); 87 | 88 | if (descImpl.updateBuildStatus()) { 89 | getContext().setResult(Result.FAILURE); 90 | getContext().onFailure(new IOException(description)); 91 | } 92 | 93 | return new PublishResult(PublishResult.Status.FAILED, description, token); 94 | } 95 | 96 | protected PublishResult success(final String description, 97 | final String token, 98 | final MutableBoolean isApiCreate){ 99 | final ApiMap.ApiMapDescriptorImpl descImpl = (ApiMap.ApiMapDescriptorImpl) Jenkins.getInstance().getDescriptorByName(ApiMap.class.getName()); 100 | 101 | PublishResult returnValue; 102 | 103 | if(isApiCreate.isTrue()) { 104 | returnValue = new PublishResult(PublishResult.Status.CREATED, description, token); 105 | }else{ 106 | returnValue = new PublishResult(PublishResult.Status.UPDATED, description); 107 | } 108 | 109 | if(descImpl.updateBuildStatus()) { 110 | getContext().setResult(Result.SUCCESS); 111 | getContext().onSuccess(returnValue); 112 | } 113 | 114 | return returnValue; 115 | } 116 | 117 | @Override 118 | protected PublishResult run() throws Exception { 119 | /* 120 | * Global 121 | */ 122 | final ApiMap.ApiMapDescriptorImpl descImpl = (ApiMap.ApiMapDescriptorImpl) Jenkins.getInstance().getDescriptorByName(ApiMap.class.getName()); 123 | 124 | final FilePath path = getContext().get(FilePath.class); 125 | if(path == null) { return failure(FILEPATH_IS_A_NULL_OBJECT, null); } 126 | 127 | final RestClientConfiguration configuration; 128 | 129 | LOGGER.log(Level.FINER, "Reading metadata file"); 130 | 131 | final MutableBoolean isApiCreated = new MutableBoolean(false); 132 | 133 | LOGGER.log(Level.FINER, "Creating rest client configuration"); 134 | configuration = RestClientUtil.configuration(this.step.getToken()); 135 | 136 | /* 137 | * Metadata 138 | */ 139 | 140 | final MetadataFile metadataFile; 141 | 142 | try { 143 | metadataFile = FileReader.metadataFile(FileReader.filePath(path, this.step.getMetadataFile())); 144 | if (metadataFile == null) { 145 | return failure(METADATA_FILE_MISSING_ERROR, configuration.getToken()); 146 | } 147 | 148 | LOGGER.log(Level.FINER, "Uploading metadata content"); 149 | final MetadataDataRestEntity metadataReturnObject = uploadMetadata(metadataFile, configuration, isApiCreated); 150 | if (metadataReturnObject == null) { 151 | return failure(UNABLE_TO_UPLOAD_METADATA_ERROR_MESSAGE, configuration.getToken()); 152 | } 153 | } catch (FileNotFoundException e){ 154 | LOGGER.log(Level.FINE, e.getMessage()); 155 | return failure(METADATA_FILE_MISSING_ERROR, configuration.getToken()); 156 | } catch (IOException e) { 157 | LOGGER.log(Level.FINE, e.getMessage()); 158 | return failure(UNABLE_TO_UPLOAD_METADATA_ERROR_MESSAGE, configuration.getToken()); 159 | } catch (IncorrectTokenException e) { 160 | LOGGER.log(Level.FINE, e.getMessage()); 161 | return failure(MISSING_OR_INVALID_API_TOKEN_ERROR_MESSAGE, configuration.getToken()); 162 | } catch (PublishErrorException e){ 163 | LOGGER.log(Level.FINE, e.getMessage()); 164 | return failure(e.getMessage(), configuration.getToken()); 165 | } 166 | 167 | /* 168 | * Taxonomy 169 | */ 170 | 171 | LOGGER.log(Level.FINER, "Reading taxonomy file"); 172 | 173 | try { 174 | final TaxonomyFile taxonomyFile = FileReader.taxonomyFile(FileReader.filePath(path, this.step.getTaxonomyFile())); 175 | if (taxonomyFile == null) { return failure(TAXONOMY_FILE_MISSING_ERROR, configuration.getToken()); } 176 | 177 | LOGGER.log(Level.FINER, "Uploading taxonomy content"); 178 | final ClassificationRootRestEntity classificationReturnObject = uploadTaxonomy( 179 | metadataFile.getData().getName(), 180 | metadataFile.getData().getApiVersion(), 181 | taxonomyFile, 182 | configuration 183 | ); 184 | if (classificationReturnObject == null) { return failure(UNABLE_TO_UPLOAD_TAXONOMY_ERROR_MESSAGE, configuration.getToken()); } 185 | } catch (FileNotFoundException e){ 186 | LOGGER.log(Level.FINE, e.getMessage()); 187 | return failure(TAXONOMY_FILE_MISSING_ERROR, configuration.getToken()); 188 | } catch (IncorrectTokenException e) { 189 | LOGGER.log(Level.FINE, e.getMessage()); 190 | return failure(MISSING_OR_INVALID_API_TOKEN_ERROR_MESSAGE, configuration.getToken()); 191 | } catch (Exception e) { 192 | LOGGER.log(Level.FINE, e.getMessage()); 193 | return failure(UNABLE_TO_UPLOAD_TAXONOMY_ERROR_MESSAGE, configuration.getToken()); 194 | } 195 | 196 | /* 197 | * Readme.md 198 | */ 199 | 200 | if(descImpl.isAllowReadmeUpload() && this.step.getReadmeFile() != null && !this.step.getReadmeFile().isEmpty()){ 201 | try{ 202 | final String readme = FileReader.readDocument(FileReader.filePath(path, this.step.getReadmeFile())); 203 | if (readme == null) { return failure(README_FILE_MISSING_ERROR, configuration.getToken()); } 204 | 205 | LOGGER.log(Level.FINER, "Uploading README.md content"); 206 | final String readmeReturnObject = uploadReadme( 207 | metadataFile.getData().getName(), 208 | metadataFile.getData().getApiVersion(), 209 | readme, 210 | configuration 211 | ); 212 | if (readmeReturnObject == null) { return failure(UNABLE_TO_UPLOAD_README_ERROR_MESSAGE, configuration.getToken()); } 213 | } catch (IncorrectFileTypeException e){ 214 | LOGGER.log(Level.FINE, e.getMessage()); 215 | return failure(MARKDOWN_FILE_FORMAT_REQUIRED, configuration.getToken()); 216 | } catch (FileNotFoundException e){ 217 | LOGGER.log(Level.FINE, e.getMessage()); 218 | return failure(README_FILE_MISSING_ERROR, configuration.getToken()); 219 | } catch (IncorrectTokenException e) { 220 | LOGGER.log(Level.FINE, e.getMessage()); 221 | return failure(MISSING_OR_INVALID_API_TOKEN_ERROR_MESSAGE, configuration.getToken()); 222 | } catch (Exception e) { 223 | LOGGER.log(Level.FINE, e.getMessage()); 224 | return failure(UNABLE_TO_UPLOAD_README_ERROR_MESSAGE, configuration.getToken()); 225 | } 226 | } 227 | 228 | /* 229 | * Changelog.md 230 | */ 231 | 232 | if(descImpl.isAllowChangelogUpload() && this.step.getChangelogFile() != null && !this.step.getChangelogFile().isEmpty()){ 233 | try{ 234 | final String changelog = FileReader.readDocument(FileReader.filePath(path, this.step.getChangelogFile())); 235 | if (changelog == null) { return failure(README_FILE_MISSING_ERROR, configuration.getToken()); } 236 | 237 | LOGGER.log(Level.FINER, "Uploading CHANGELOG.md content"); 238 | final String readmeReturnObject = uploadChangelog( 239 | metadataFile.getData().getName(), 240 | metadataFile.getData().getApiVersion(), 241 | changelog, 242 | configuration 243 | ); 244 | if (readmeReturnObject == null) { return failure(UNABLE_TO_UPLOAD_CHANGELOG_ERROR_MESSAGE, configuration.getToken()); } 245 | } catch (IncorrectFileTypeException e){ 246 | LOGGER.log(Level.FINE, e.getMessage()); 247 | return failure(MARKDOWN_FILE_FORMAT_REQUIRED, configuration.getToken()); 248 | } catch (FileNotFoundException e){ 249 | LOGGER.log(Level.FINE, e.getMessage()); 250 | return failure(CHANGELOG_FILE_MISSING_ERROR, configuration.getToken()); 251 | } catch (IncorrectTokenException e) { 252 | LOGGER.log(Level.FINE, e.getMessage()); 253 | return failure(MISSING_OR_INVALID_API_TOKEN_ERROR_MESSAGE, configuration.getToken()); 254 | } catch (Exception e) { 255 | LOGGER.log(Level.FINE, e.getMessage()); 256 | return failure(UNABLE_TO_UPLOAD_CHANGELOG_ERROR_MESSAGE, configuration.getToken()); 257 | } 258 | } 259 | 260 | return success(STEP_COMPLETED_SUCCESSFULLY, configuration.getToken(), isApiCreated); 261 | } 262 | 263 | protected MetadataDataRestEntity uploadMetadata(final MetadataFile metadataFile, 264 | final RestClientConfiguration configuration, 265 | final MutableBoolean isApiCreated) throws IOException, InterruptedException, IncorrectTokenException, PublishErrorException { 266 | /* Assemble REST entities */ 267 | LOGGER.log(Level.FINER, "Assembling REST entities"); 268 | 269 | final MetadataDataRestEntity metadataDataApiEntity = new MetadataDataRestEntity( 270 | metadataFile.getData().getName(), 271 | metadataFile.getData().getDescription(), 272 | metadataFile.getData().getVisibility(), 273 | metadataFile.getData().getApiVersion(), 274 | metadataFile.getData().getReleaseStatus(), 275 | metadataFile.getData().getInterfaceSpecification(), 276 | metadataFile.getData().getInterfaceDescriptionLanguage(), 277 | metadataFile.getData().getArchitectureLayer(), 278 | metadataFile.getData().getBusinessUnit(), 279 | metadataFile.getData().getSystemIdentifier(), 280 | metadataFile.getData().getDocumentation() 281 | ); 282 | 283 | final ApiDataRestEntity apiDataApiEntity = new ApiDataRestEntity( 284 | metadataFile.getData().getName(), 285 | this.step.getRepositoryURL() 286 | ); 287 | 288 | final ApiVersionDataRestEntity apiVersionDataApiEntity = new ApiVersionDataRestEntity( 289 | metadataDataApiEntity.getApiVersion() 290 | ); 291 | 292 | /* Setup callback methods */ 293 | LOGGER.log(Level.FINER, "Creating callback methods"); 294 | 295 | final Consumer apiCreatedCallback = content -> { 296 | LOGGER.log(Level.FINER, "Setting token " + ((ApiDataRestEntity) content).getMeta().getToken()); 297 | configuration.setToken(((ApiDataRestEntity) content).getMeta().getToken()); 298 | isApiCreated.setValue(true); 299 | }; 300 | 301 | final Consumer apiVersionCreatedCallback = content -> { 302 | LOGGER.log(Level.FINER, content.toString()); 303 | }; 304 | 305 | final AtomicReference errorMessage = new AtomicReference<>(); 306 | final Consumer errorHandlerCallback = content -> { 307 | if(content != null) errorMessage.set(content); 308 | }; 309 | 310 | /* Performing REST calls */ 311 | LOGGER.log(Level.FINER, "Performing REST calls"); 312 | 313 | final MetadataDataRestEntity object = IRestClient.withConfiguration(configuration) 314 | .withErrorHandler(errorHandlerCallback) 315 | .followCollection(JsonApiRestResponseWrapper.API_COLLECTION) 316 | .followCollection(metadataDataApiEntity.getName(), JsonApiRestResponseWrapper.VERSION_COLLECTION) 317 | .onMissingCreate(metadataDataApiEntity.getName(), apiDataApiEntity, apiCreatedCallback) 318 | .followResource(metadataDataApiEntity.getApiVersion()) 319 | .onMissingCreate(metadataDataApiEntity.getApiVersion(), apiVersionDataApiEntity, apiVersionCreatedCallback) 320 | .followCollection(JsonApiRestResponseWrapper.METADATA_COLLECTION) 321 | .createOrUpdateResource(metadataDataApiEntity, ContentType.APPLICATION_JSON); 322 | 323 | if(errorMessage.get() != null){ 324 | throw new PublishErrorException(errorMessage.get()); 325 | } 326 | 327 | return object; 328 | } 329 | 330 | protected ClassificationRootRestEntity uploadTaxonomy(final String apiName, 331 | final String apiVersion, 332 | final TaxonomyFile taxonomyFile, 333 | final RestClientConfiguration configuration) throws IOException, IncorrectTokenException, PublishErrorException { 334 | /* Assemble REST entities */ 335 | LOGGER.log(Level.FINER, "Assembling REST entities"); 336 | 337 | final ClassificationRootRestEntity classificationRootApiEntity = new ClassificationRootRestEntity( 338 | taxonomyFile 339 | .getData() 340 | .getClassifications() 341 | .stream() 342 | .map(e -> new ClassificationDataRestEntity(e, taxonomyFile.getVersion())) 343 | .collect(Collectors.toCollection(ArrayList::new)) 344 | ); 345 | 346 | /* Setup callback methods */ 347 | LOGGER.log(Level.FINER, "Creating callback methods"); 348 | 349 | final AtomicReference errorMessage = new AtomicReference<>(); 350 | final Consumer errorHandlerCallback = content -> { 351 | if(content != null) errorMessage.set(content.toString()); 352 | }; 353 | 354 | /* Performing REST calls */ 355 | LOGGER.log(Level.FINER, "Performing REST calls"); 356 | 357 | final ClassificationRootRestEntity returnValue = IRestClient.withConfiguration(configuration) 358 | .withErrorHandler(errorHandlerCallback) 359 | .followCollection(JsonApiRestResponseWrapper.API_COLLECTION) 360 | .followCollection(apiName, JsonApiRestResponseWrapper.VERSION_COLLECTION) 361 | .followResource(apiVersion) 362 | .followCollection(JsonApiRestResponseWrapper.CLASSIFICATION_COLLECTION) 363 | .createOrUpdateResource(classificationRootApiEntity, ContentType.APPLICATION_JSON); 364 | 365 | if(errorMessage.get() != null){ 366 | throw new PublishErrorException(errorMessage.get()); 367 | } 368 | 369 | return returnValue; 370 | } 371 | 372 | protected String uploadReadme(final String apiName, 373 | final String apiVersion, 374 | final String readme, 375 | final RestClientConfiguration configuration) throws IOException, IncorrectTokenException, PublishErrorException { 376 | LOGGER.log(Level.FINER, "Uploading README.md"); 377 | 378 | /* Setup callback methods */ 379 | LOGGER.log(Level.FINER, "Creating callback methods"); 380 | 381 | final AtomicReference errorMessage = new AtomicReference<>(); 382 | final Consumer errorHandlerCallback = content -> { 383 | if(content != null) errorMessage.set(content.toString()); 384 | }; 385 | 386 | /* Performing REST calls */ 387 | LOGGER.log(Level.FINER, "Performing REST calls"); 388 | final String returnObject = IRestClient.withConfiguration(configuration) 389 | .withErrorHandler(errorHandlerCallback) 390 | .followCollection(JsonApiRestResponseWrapper.API_COLLECTION) 391 | .followCollection(apiName, JsonApiRestResponseWrapper.VERSION_COLLECTION) 392 | .followResource(apiVersion) 393 | .followCollection(JsonApiRestResponseWrapper.README_ELEMENT) 394 | .createOrUpdateResource(readme, ContentType.create("text/markdown")); 395 | 396 | if(errorMessage.get() != null){ 397 | throw new PublishErrorException(errorMessage.get()); 398 | } 399 | 400 | return returnObject; 401 | } 402 | 403 | protected String uploadChangelog(final String apiName, 404 | final String apiVersion, 405 | final String changelog, 406 | final RestClientConfiguration configuration) throws IOException, IncorrectTokenException, PublishErrorException { 407 | LOGGER.log(Level.FINER, "Uploading CHANGELOG.md"); 408 | 409 | /* Setup callback methods */ 410 | LOGGER.log(Level.FINER, "Creating callback methods"); 411 | 412 | final AtomicReference errorMessage = new AtomicReference<>(); 413 | final Consumer errorHandlerCallback = content -> { 414 | if(content != null) errorMessage.set(content.toString()); 415 | }; 416 | 417 | /* Performing REST calls */ 418 | LOGGER.log(Level.FINER, "Performing REST calls"); 419 | final String returnObject = IRestClient.withConfiguration(configuration) 420 | .withErrorHandler(errorHandlerCallback) 421 | .followCollection(JsonApiRestResponseWrapper.API_COLLECTION) 422 | .followCollection(apiName, JsonApiRestResponseWrapper.VERSION_COLLECTION) 423 | .followResource(apiVersion) 424 | .followCollection(JsonApiRestResponseWrapper.CHANGELOG_ELEMENT) 425 | .createOrUpdateResource(changelog, ContentType.create("text/markdown")); 426 | 427 | if(errorMessage.get() != null){ 428 | throw new PublishErrorException(errorMessage.get()); 429 | } 430 | 431 | return returnObject; 432 | } 433 | } 434 | --------------------------------------------------------------------------------