├── webapp
├── src
│ ├── react-app-env.d.ts
│ ├── Contants.ts
│ ├── index.tsx
│ ├── hooks
│ │ └── useStores.ts
│ ├── components
│ │ ├── TableCell.tsx
│ │ ├── DeleteButton.tsx
│ │ ├── Button.tsx
│ │ ├── Header.tsx
│ │ ├── formComponents
│ │ │ ├── Checkbox.tsx
│ │ │ ├── TextArea.tsx
│ │ │ ├── FormList.tsx
│ │ │ ├── RPMLimitationForm.tsx
│ │ │ ├── TextInput.tsx
│ │ │ ├── Select.tsx
│ │ │ ├── MultiSelect.tsx
│ │ │ ├── FileRequirementsForm.tsx
│ │ │ ├── AddComponent.tsx
│ │ │ ├── LimitationForm.tsx
│ │ │ ├── PlatformProviderForm.tsx
│ │ │ └── JDKVersionSelectForm.tsx
│ │ ├── ConfirmDialog.tsx
│ │ └── TreeNode.tsx
│ ├── App.test.tsx
│ ├── styles
│ │ ├── Button.css
│ │ ├── Forms.css
│ │ └── Layout.css
│ ├── index.css
│ ├── utils
│ │ ├── createVariantMap.ts
│ │ └── createJobName.ts
│ ├── stores
│ │ └── index.ts
│ ├── App.tsx
│ └── logo.svg
├── public
│ ├── robots.txt
│ ├── favicon.ico
│ ├── logo192.png
│ ├── logo512.png
│ └── index.html
├── tsconfig.json
└── package.json
├── fake-koji
└── src
│ ├── main
│ ├── resources
│ │ └── jenkins-templates
│ │ │ ├── providers.xml
│ │ │ ├── nested-view-columns.xml
│ │ │ ├── shell-script.xml
│ │ │ ├── trigger.xml
│ │ │ ├── post-build-task-plugin.xml
│ │ │ ├── provider.xml
│ │ │ ├── view-columns.xml
│ │ │ ├── fakekoji-xml-rpc-api.xml
│ │ │ ├── koji-xml-rpc-api.xml
│ │ │ ├── nested-view.xml
│ │ │ ├── post-build-task-plugin-analyse.xml
│ │ │ ├── timeoutedshell-script.xml
│ │ │ ├── post-build-task-plugin-destroyvm.xml
│ │ │ ├── view.xml
│ │ │ ├── task-job.xml
│ │ │ ├── pull-job.xml
│ │ │ └── update-vm-job.xml
│ └── java
│ │ └── org
│ │ └── fakekoji
│ │ ├── jobmanager
│ │ ├── model
│ │ │ ├── NamesProvider.java
│ │ │ ├── JobBump.java
│ │ │ ├── PlatformBumpVariant.java
│ │ │ ├── JobCollisionAction.java
│ │ │ ├── JobConfiguration.java
│ │ │ ├── Product.java
│ │ │ ├── TestJobConfiguration.java
│ │ │ ├── JobUpdateResult.java
│ │ │ ├── TaskConfig.java
│ │ │ ├── BuildPlatformConfig.java
│ │ │ ├── PlatformConfig.java
│ │ │ └── JDKTestProject.java
│ │ ├── Parser.java
│ │ ├── ManagementException.java
│ │ ├── Manager.java
│ │ ├── OToolUtils.java
│ │ ├── ManagementUtils.java
│ │ ├── ManagementResult.java
│ │ ├── JobUpdater.java
│ │ ├── bumpers
│ │ │ └── BumpResult.java
│ │ ├── views
│ │ │ └── VersionlessPlatform.java
│ │ └── manager
│ │ │ ├── JDKVersionManager.java
│ │ │ ├── BuildProviderManager.java
│ │ │ ├── TaskManager.java
│ │ │ └── PlatformManager.java
│ │ ├── storage
│ │ ├── StorageException.java
│ │ └── Storage.java
│ │ ├── core
│ │ ├── DummyMain.java
│ │ └── utils
│ │ │ ├── matrix
│ │ │ ├── cell
│ │ │ │ ├── Cell.java
│ │ │ │ ├── TitleCell.java
│ │ │ │ ├── UpperCornerCell.java
│ │ │ │ ├── MultiUrlCell.java
│ │ │ │ ├── UrlCell.java
│ │ │ │ └── CellGroup.java
│ │ │ ├── TestEqualityFilter.java
│ │ │ ├── BuildEqualityFilter.java
│ │ │ ├── EqualityFilter.java
│ │ │ ├── formatter
│ │ │ │ ├── Formatter.java
│ │ │ │ └── PlainTextFormatter.java
│ │ │ ├── TestSpec.java
│ │ │ └── BuildSpec.java
│ │ │ ├── DirFilter.java
│ │ │ └── FileFileFilter.java
│ │ ├── api
│ │ └── http
│ │ │ ├── rest
│ │ │ ├── OToolError.java
│ │ │ ├── args
│ │ │ │ ├── RemoveTaskVariantArgs.java
│ │ │ │ └── BumpArgs.java
│ │ │ └── RestUtils.java
│ │ │ └── filehandling
│ │ │ └── FileDownloadService.java
│ │ ├── functional
│ │ ├── Tuple.java
│ │ └── Result.java
│ │ └── model
│ │ ├── JDKVersion.java
│ │ ├── BuildProvider.java
│ │ └── TaskVariantValue.java
│ └── test
│ ├── resources
│ └── org
│ │ └── fakekoji
│ │ ├── jobmanager
│ │ └── simple_job
│ │ └── core
│ │ └── utils
│ │ └── matrix
│ │ └── filtered_matrix
│ └── java
│ └── org
│ └── fakekoji
│ └── jobmanager
│ └── project
│ ├── JDKProjectParserTest.java
│ └── ReverseJDKProjectParserTest.java
├── jenkins-scm-koji-plugin
└── src
│ └── main
│ ├── resources
│ ├── hudson
│ │ └── plugins
│ │ │ └── scm
│ │ │ └── koji
│ │ │ ├── KojiSCM
│ │ │ ├── help-maxPreviousBuilds.html
│ │ │ ├── help-dirPerNvr.html
│ │ │ ├── help-downloadDir.html
│ │ │ ├── help-cleanDownloadDir.html
│ │ │ ├── global.jelly
│ │ │ ├── help-KojiSCMConfig_skipPoolingIfJobRuns.html
│ │ │ ├── help-KojiSCMConfig_requireWorkspace.html
│ │ │ └── config.jelly
│ │ │ ├── RealKojiXmlRpcApi
│ │ │ ├── help-arch.html
│ │ │ ├── help-tag.html
│ │ │ ├── help-subpackageBlacklist.html
│ │ │ ├── help-subpackageWhitelist.html
│ │ │ ├── help-packageName.html
│ │ │ └── config.jelly
│ │ │ ├── KojiBuildProvider
│ │ │ ├── help-downloadUrl.html
│ │ │ ├── help-topUrl.html
│ │ │ └── config.jelly
│ │ │ ├── KojiScmRe
│ │ │ └── index.jelly
│ │ │ ├── FakeKojiXmlRpcApi
│ │ │ └── config.jelly
│ │ │ └── KojiChangeLogSet
│ │ │ ├── index.jelly
│ │ │ └── digest.jelly
│ └── index.jelly
│ └── java
│ └── hudson
│ └── plugins
│ └── scm
│ └── koji
│ ├── KojiRepositoryBrowser.java
│ ├── KojiRevisionState.java
│ ├── KojiChangeLogParser.java
│ ├── KojiRevisionFromBuild.java
│ ├── model
│ └── KojiBuildDownloadResult.java
│ ├── KojiXmlRpcApiType.java
│ ├── LoggerHelp.java
│ ├── client
│ └── FakeKojiBuildMatcher.java
│ ├── KojiScmRe.java
│ ├── KojiXmlRpcApi.java
│ ├── KojiEnvVarsAction.java
│ └── BuildsSerializer.java
├── koji-scm-lib
├── src
│ ├── main
│ │ └── java
│ │ │ ├── hudson
│ │ │ └── plugins
│ │ │ │ └── scm
│ │ │ │ └── koji
│ │ │ │ ├── client
│ │ │ │ ├── TaskListenerLogTransporter.java
│ │ │ │ └── GlobPredicate.java
│ │ │ │ └── model
│ │ │ │ └── BuildProvider.java
│ │ │ └── org
│ │ │ └── fakekoji
│ │ │ └── xmlrpc
│ │ │ └── server
│ │ │ ├── expensiveobjectscache
│ │ │ ├── OriginalObjectProvider.java
│ │ │ └── CachableRequest.java
│ │ │ ├── JavaServerConstants.java
│ │ │ ├── xmlrpcresponse
│ │ │ ├── PackageId.java
│ │ │ ├── FakeBuildDetail.java
│ │ │ ├── XmlRpcResponse.java
│ │ │ ├── FakeBuildList.java
│ │ │ ├── TagSet.java
│ │ │ ├── ArchiveList.java
│ │ │ └── RPMList.java
│ │ │ └── xmlrpcrequestparams
│ │ │ ├── ListRPMs.java
│ │ │ ├── ListArchives.java
│ │ │ ├── XmlRpcRequestUtils.java
│ │ │ ├── GetPackageId.java
│ │ │ ├── XmlRpcRequestParams.java
│ │ │ ├── GetBuildDetail.java
│ │ │ ├── ListTags.java
│ │ │ ├── ListBuilds.java
│ │ │ ├── ListArtefacts.java
│ │ │ └── GetBuildList.java
│ └── test
│ │ └── java
│ │ └── hudson
│ │ └── plugins
│ │ └── scm
│ │ └── koji
│ │ └── LocalDateTimeWithDateTimeFormatterTest.java
└── pom.xml
├── .gitignore
├── LICENSE
├── .github
└── workflows
│ └── maven.yml
└── pom.xml
/webapp/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/webapp/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 |
--------------------------------------------------------------------------------
/webapp/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/jenkins-scm-koji-plugin/master/webapp/public/favicon.ico
--------------------------------------------------------------------------------
/webapp/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/jenkins-scm-koji-plugin/master/webapp/public/logo192.png
--------------------------------------------------------------------------------
/webapp/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/jenkins-scm-koji-plugin/master/webapp/public/logo512.png
--------------------------------------------------------------------------------
/webapp/src/Contants.ts:
--------------------------------------------------------------------------------
1 | const Constants = {
2 | TREE_PADDING_OFFSET: 30
3 | };
4 |
5 | export default Constants;
6 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/providers.xml:
--------------------------------------------------------------------------------
1 |
2 | %{BUILD_PROVIDERS}
3 |
4 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/nested-view-columns.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/webapp/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import ReactDOM from "react-dom"
3 |
4 | import "./index.css"
5 | import App from "./App"
6 |
7 | ReactDOM.render( , document.getElementById("root"))
8 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/KojiSCM/help-maxPreviousBuilds.html:
--------------------------------------------------------------------------------
1 |
2 | Max number of previous builds to check, in case there are more old builds available.
3 |
4 |
--------------------------------------------------------------------------------
/webapp/src/hooks/useStores.ts:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { stores } from "../stores"
3 |
4 | const useStores = () => React.useContext(React.createContext(stores))
5 | export default useStores
6 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/RealKojiXmlRpcApi/help-arch.html:
--------------------------------------------------------------------------------
1 |
2 | Only use builds containing RPMs for specified arches. May be empty. Coma-separated list is expected.
3 |
4 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/hudson/plugins/scm/koji/client/TaskListenerLogTransporter.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.scm.koji.client;
2 |
3 | public interface TaskListenerLogTransporter {
4 | public void println(String s);
5 | }
6 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/KojiSCM/help-dirPerNvr.html:
--------------------------------------------------------------------------------
1 |
2 | Create subdirectory under the download dir, where name of the directory will be the NVR of the RPM package.
3 |
4 |
5 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/model/NamesProvider.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.model;
2 |
3 | public interface NamesProvider {
4 |
5 | public String getName();
6 | public String getShortName();
7 | }
8 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/shell-script.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #!/bin/bash
4 | %{EXPORTED_VARIABLES}
5 | bash %{RUN_SCRIPT} '%{TASK_SCRIPT}'
6 |
7 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/KojiSCM/help-downloadDir.html:
--------------------------------------------------------------------------------
1 |
2 | Directory inside workspace to download RPM packages to. If empty the RPMs will be downloaded directly into workspace.
3 |
4 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/Parser.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager;
2 |
3 | import org.fakekoji.storage.StorageException;
4 |
5 | public interface Parser {
6 |
7 | U parse(T t) throws ManagementException, StorageException;
8 | }
9 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/storage/StorageException.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.storage;
2 |
3 |
4 | public class StorageException extends Exception {
5 |
6 | public StorageException(String message) {
7 | super(message);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/trigger.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | %{SCM_POLL_SCHEDULE}
4 | false
5 |
6 |
7 |
--------------------------------------------------------------------------------
/webapp/src/components/TableCell.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { TableCell as MUITableCell } from "@material-ui/core"
3 |
4 | const TableCell: React.FC = ({ children }) => {
5 | return {children}
6 | }
7 |
8 | export default TableCell
9 |
--------------------------------------------------------------------------------
/webapp/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render( , div);
8 | ReactDOM.unmountComponentAtNode(div);
9 | });
10 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/post-build-task-plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | %{POST_BUILD_TASK_PLUGIN_DESTROYVM}
4 | %{POST_BUILD_TASK_PLUGIN_ANALYSE}
5 |
6 |
7 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/provider.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | %{BUILD_PROVIDER_TOP_URL}
4 | %{BUILD_PROVIDER_DOWNLOAD_URL}
5 |
6 |
7 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/DummyMain.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.core;
2 |
3 | //Please do not delete this, untill we make yarn to work in contianer
4 |
5 | public class DummyMain {
6 | public static void main(String[] args) {
7 | System.out.println("Fake koji is on classapth");
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/api/http/rest/OToolError.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.api.http.rest;
2 |
3 | public class OToolError {
4 | final String message;
5 | final int code;
6 |
7 | public OToolError(String message, int code) {
8 | this.message = message;
9 | this.code = code;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/index.jelly:
--------------------------------------------------------------------------------
1 |
2 |
3 | This is plugin able to pull binaries to jenkins from koji-like services.
4 | By default it contains api for http://koji.fedoraproject.org/ and for internal fake-koji server (which have its own api on top of real-koji like api)
5 |
6 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/KojiBuildProvider/help-downloadUrl.html:
--------------------------------------------------------------------------------
1 |
2 | URL for RPM download. For example:
3 | http://koji.fedoraproject.org/packages/ :
4 | http://custom.koji:DPORT/
5 |
6 |
7 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/KojiSCM/help-cleanDownloadDir.html:
--------------------------------------------------------------------------------
1 |
2 | Remove all the contents of the download directory before the download.
3 | NOTE: this option is ignored if Download directory field is empty and subdirectory for NVR is not checked.
4 |
5 |
6 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/expensiveobjectscache/OriginalObjectProvider.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.expensiveobjectscache;
2 |
3 | import org.fakekoji.xmlrpc.server.xmlrpcrequestparams.XmlRpcRequestParams;
4 |
5 | public interface OriginalObjectProvider {
6 |
7 | Object obtainOriginal(String url, XmlRpcRequestParams params);
8 | }
9 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/utils/matrix/cell/Cell.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.core.utils.matrix.cell;
2 |
3 | public interface Cell {
4 | default boolean isEmpty() {
5 | return false;
6 | }
7 |
8 | default int getSpan() {
9 | return 1;
10 | }
11 |
12 | default int size() {
13 | return 1;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/expensiveobjectscache/CachableRequest.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.expensiveobjectscache;
2 |
3 | /**
4 | * This object can be cached in maps. Thus hashcode and equals are superimportant
5 | */
6 | public interface CachableRequest {
7 |
8 | boolean equals(Object o);
9 |
10 | int hashCode();
11 | }
12 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/view-columns.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/webapp/src/styles/Button.css:
--------------------------------------------------------------------------------
1 | .button {
2 | border: none;
3 | color: #fff;
4 | cursor: pointer;
5 | padding: 12px 16px;
6 | }
7 |
8 | .button-red {
9 | background-color: #d23;
10 | }
11 |
12 | .button-green {
13 | background-color: #2d3;
14 | }
15 |
16 | .button-blue {
17 | background-color: #23d
18 | }
19 |
20 | .button-gray {
21 | background-color: #999;
22 | }
23 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/fakekoji-xml-rpc-api.xml:
--------------------------------------------------------------------------------
1 |
2 | FAKE_KOJI
3 | %{PROJECT_NAME}
4 | %{BUILD_VARIANTS}
5 | %{PLATFORM}
6 | %{IS_BUILT}
7 |
8 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/KojiBuildProvider/help-topUrl.html:
--------------------------------------------------------------------------------
1 |
2 | URL of kojihub or brewhub. For example:
3 | http://koji.fedoraproject.org/kojihub :
4 | In case of more providers, first found first served.
5 | http://custom.koji:XPORT/RPC2/
6 |
7 |
--------------------------------------------------------------------------------
/webapp/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/utils/matrix/TestEqualityFilter.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.core.utils.matrix;
2 |
3 | public class TestEqualityFilter extends EqualityFilter{
4 |
5 | public final boolean suite;
6 |
7 | public TestEqualityFilter(boolean os, boolean arch, boolean provider, boolean suite, boolean variants) {
8 | super(os, arch, provider, variants);
9 | this.suite = suite;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/RealKojiXmlRpcApi/help-tag.html:
--------------------------------------------------------------------------------
1 |
2 | Use only builds containing specified tag.
3 | May be empty to match all the builds.
4 | Supports space separated regex patterns
5 |
test page spec
6 |
7 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/koji-xml-rpc-api.xml:
--------------------------------------------------------------------------------
1 |
2 | REAL_KOJI
3 | %{PACKAGE_NAME}
4 | %{ARCH}
5 | %{TAGS}
6 | %{SUBPACKAGE_BLACKLIST}
7 | %{SUBPACKAGE_WHITELIST}
8 |
9 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/JavaServerConstants.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server;
2 |
3 | public class JavaServerConstants {
4 | public static final int DFAULT_RP2C_PORT = 9848;
5 | public static final int DFAULT_DWNLD_PORT = DFAULT_RP2C_PORT + 1;
6 | public static final int DFAULT_SCP_PORT = 9822;
7 | public static final int DFAULT_WEBAP_PORT = 8888;
8 | public static final String FAKE_KOJI_LOGGER = "Fake-Koji";
9 | }
10 |
--------------------------------------------------------------------------------
/webapp/src/utils/createVariantMap.ts:
--------------------------------------------------------------------------------
1 | import { TaskVariant } from "../stores/model"
2 |
3 | const createTaskVariantsMap = (
4 | taskVariants: TaskVariant[],
5 | filter: (variant: TaskVariant) => boolean
6 | ): { [key: string]: string } =>
7 | taskVariants.filter(filter).reduce((map, taskVariant) => {
8 | map[taskVariant.id] = taskVariant.defaultValue
9 | return map
10 | }, {} as { [key: string]: string })
11 |
12 | export default createTaskVariantsMap
13 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/storage/Storage.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.storage;
2 |
3 | import java.util.List;
4 |
5 | public interface Storage {
6 |
7 | void store(String id, T t) throws StorageException;
8 |
9 | void delete(String id) throws StorageException;
10 |
11 | T load(String id, Class valueType) throws StorageException;
12 |
13 | List loadAll(Class valueType) throws StorageException;
14 |
15 | boolean contains(String id);
16 | }
17 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/ManagementException.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager;
2 |
3 | public class ManagementException extends Exception {
4 |
5 | public ManagementException(String message) {
6 | super(message);
7 | }
8 |
9 | public ManagementException(Exception exception) {
10 | super(exception);
11 | }
12 |
13 | public ManagementException(String message, Exception exception) {
14 | super(message, exception);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/java/hudson/plugins/scm/koji/KojiRepositoryBrowser.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.scm.koji;
2 |
3 | import hudson.scm.ChangeLogSet;
4 | import hudson.scm.RepositoryBrowser;
5 | import java.io.IOException;
6 | import java.net.URL;
7 |
8 | public class KojiRepositoryBrowser extends RepositoryBrowser {
9 |
10 | @Override
11 | public URL getChangeSetLink(ChangeLogSet.Entry changeSet) throws IOException {
12 | // TODO implement
13 | return null;
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/nested-view.xml:
--------------------------------------------------------------------------------
1 |
2 | %{VIEW_NAME}
3 | true
4 | true
5 |
6 |
7 | %{SUBVIEWS}
8 |
9 |
10 |
11 | %{NESTEDVIEW_COLUMNS}
12 |
13 |
14 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/RealKojiXmlRpcApi/help-subpackageBlacklist.html:
--------------------------------------------------------------------------------
1 |
2 | space separated Regex patterns for subpackages not to download. This is applied first, before whitelist. For example:
3 |
.*debug.* .*accessibility.* .*src.* .*demo.*
4 |
test page spec
5 |
6 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/utils/matrix/BuildEqualityFilter.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.core.utils.matrix;
2 |
3 | public class BuildEqualityFilter extends EqualityFilter {
4 |
5 | public final boolean project;
6 | public final boolean jdk;
7 |
8 |
9 | public BuildEqualityFilter(boolean os, boolean arch, boolean provider, boolean project, boolean jdk, boolean variants) {
10 | super(os, arch, provider, variants);
11 | this.project = project;
12 | this.jdk = jdk;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/RealKojiXmlRpcApi/help-subpackageWhitelist.html:
--------------------------------------------------------------------------------
1 |
2 | space separated Regex patterns for subpackages to download. This is applied last, after exclude list. This has no effect when empty. For
3 | example:
4 |
*.x86_64.win.zip$
5 |
test page spec
6 |
7 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/utils/matrix/EqualityFilter.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.core.utils.matrix;
2 |
3 | abstract class EqualityFilter {
4 |
5 | public final boolean os;
6 | public final boolean arch;
7 | public final boolean provider;
8 | public final boolean variants;
9 |
10 | public EqualityFilter(boolean os, boolean arch, boolean provider, boolean variants) {
11 | this.os = os;
12 | this.arch = arch;
13 | this.provider = provider;
14 | this.variants = variants;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/webapp/src/stores/index.ts:
--------------------------------------------------------------------------------
1 | import { createBrowserHistory } from "history"
2 |
3 | import { ConfigStore } from "./ConfigStore"
4 | import ConfigService from "./services/ConfigService"
5 | import { ViewStore } from "./ViewStore"
6 |
7 | const history = createBrowserHistory()
8 | const url = window.location.origin
9 |
10 | const service = new ConfigService(url)
11 |
12 | const configStore = new ConfigStore(service)
13 | const viewStore = new ViewStore(history, configStore)
14 |
15 | export const stores = {
16 | configStore,
17 | viewStore
18 | }
19 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/RealKojiXmlRpcApi/help-packageName.html:
--------------------------------------------------------------------------------
1 |
2 | Exact package name to watch, or space delimited list of packages to match
3 | Note, that multi-package works only for old api, and may not work as expected.
4 | the builds of all space split packages are obtained and fitlered, and the logic is applied to the merged list.
5 | So for eg "A B" if package A have 10 very old builds, and package B ten very new builds, only builds of B will be processed.
6 | If you suddenly build A, then it willbe of course pulled.
7 |
8 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/java/hudson/plugins/scm/koji/KojiRevisionState.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.scm.koji;
2 |
3 | import hudson.plugins.scm.koji.model.Build;
4 | import hudson.scm.SCMRevisionState;
5 |
6 | public class KojiRevisionState extends SCMRevisionState {
7 |
8 | private final Build build;
9 |
10 | public KojiRevisionState(Build build) {
11 | this.build = build;
12 | }
13 |
14 | public Build getBuild() {
15 | return build;
16 | }
17 |
18 | @Override
19 | public String toString() {
20 | return "KojiRevisionState[nvr=" + build + "]";
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/target/
2 | /nbproject/
3 | .idea/
4 | *.iml
5 | /koji-scm-lib/target/
6 | /jenkins-scm-koji-plugin/target/
7 | /fake-koji/target/
8 | /jenkins-scm-koji-plugin/work
9 |
10 | # webapp
11 | # dependencies
12 | webapp/node_modules
13 | webapp/.pnp
14 | webapp/.pnp.js
15 |
16 | # testing
17 | webapp/coverage
18 |
19 | # production
20 | webapp/build
21 |
22 | # maven
23 | webapp/node
24 |
25 | # misc
26 | webapp/.DS_Store
27 | webapp/.env.local
28 | webapp/.env.development.local
29 | webapp/.env.test.local
30 | webapp/.env.production.local
31 |
32 | webapp/npm-debug.log*
33 | webapp/yarn-debug.log*
34 | webapp/yarn-error.log*
35 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/Manager.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager;
2 |
3 | import org.fakekoji.storage.StorageException;
4 |
5 | import java.util.List;
6 |
7 | public interface Manager {
8 |
9 | T create(T t) throws StorageException, ManagementException;
10 |
11 | T read(String id) throws StorageException, ManagementException;
12 |
13 | List readAll() throws StorageException;
14 |
15 | T update(String id, T t) throws StorageException, ManagementException;
16 |
17 | T delete(String id) throws StorageException, ManagementException;
18 |
19 | boolean contains(String id);
20 | }
21 |
--------------------------------------------------------------------------------
/fake-koji/src/test/resources/org/fakekoji/jobmanager/simple_job:
--------------------------------------------------------------------------------
1 |
2 |
3 | created by java test
4 | false
5 |
6 |
7 | true
8 | false
9 | false
10 | false
11 |
12 | false
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/KojiSCM/global.jelly:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/KojiScmRe/index.jelly:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hello!
6 | Unluckily this - via root action - do not work for now. It must be done via build-targeted action, whcihc somehow takes (our nvr)build as parameter, and then acts
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/webapp/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "experimentalDecorators": true,
13 | "allowSyntheticDefaultImports": true,
14 | "strict": true,
15 | "forceConsistentCasingInFileNames": true,
16 | "module": "esnext",
17 | "moduleResolution": "node",
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "noEmit": true,
21 | "jsx": "react"
22 | },
23 | "include": [
24 | "src"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/post-build-task-plugin-analyse.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | .*
5 | OR
6 |
7 |
8 | false
9 | false
10 |
11 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/timeoutedshell-script.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | %{TIMEOUT_MINUTES}
4 |
5 |
6 |
7 | #!/bin/bash
8 | %{EXPORTED_VARIABLES}
9 | bash %{RUN_SCRIPT} '%{TASK_SCRIPT}'
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcresponse/PackageId.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcresponse;
2 |
3 | public class PackageId implements XmlRpcResponse {
4 |
5 | private final Integer packageId;
6 |
7 | public PackageId(Integer packageId) {
8 | this.packageId = packageId;
9 | }
10 |
11 | @Override
12 | public Object toObject() {
13 | return packageId;
14 | }
15 |
16 | @Override
17 | public Integer getValue() {
18 | return packageId;
19 | }
20 |
21 | public static PackageId create(Object object) {
22 | return new PackageId((Integer) object);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/webapp/src/components/DeleteButton.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { IconButton } from "@material-ui/core"
3 | import { Delete } from "@material-ui/icons"
4 |
5 | import useStores from "../hooks/useStores"
6 |
7 | interface DeleteButtonProps {
8 | onClick: () => void
9 | }
10 |
11 | const DeleteButton: React.FC = ({ onClick }) => {
12 | const { viewStore } = useStores()
13 | const { confirm } = viewStore
14 | const _onClick = () => confirm("Are you sure to delete?", onClick)
15 | return (
16 |
17 |
18 |
19 | )
20 | }
21 |
22 | export default DeleteButton
23 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/post-build-task-plugin-destroyvm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | .*
5 | OR
6 |
7 |
8 | true
9 | false
10 |
11 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcresponse/FakeBuildDetail.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcresponse;
2 |
3 | import hudson.plugins.scm.koji.model.Build;
4 |
5 | public class FakeBuildDetail implements XmlRpcResponse {
6 |
7 | private final Build build;
8 |
9 | public FakeBuildDetail(Build build) {
10 | this.build = build;
11 | }
12 |
13 | @Override
14 | public Object toObject() {
15 | return this;
16 | }
17 |
18 | @Override
19 | public Build getValue() {
20 | return build;
21 | }
22 |
23 | public static FakeBuildDetail create(Object object) {
24 | return (FakeBuildDetail) object;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/utils/matrix/formatter/Formatter.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.core.utils.matrix.formatter;
2 |
3 | import org.fakekoji.core.utils.matrix.cell.CellGroup;
4 | import org.fakekoji.core.utils.matrix.cell.TitleCell;
5 | import org.fakekoji.core.utils.matrix.cell.UpperCornerCell;
6 |
7 | public interface Formatter {
8 | String rowStart();
9 |
10 | String rowEnd();
11 |
12 | String tableStart();
13 |
14 | String tableEnd();
15 |
16 | String edge(final TitleCell titleCell, int span);
17 |
18 | String cells(final CellGroup cellGroup, int maxInColumn, final String rowTitle, final String colTitle);
19 |
20 | String upperCorner(final UpperCornerCell cell);
21 |
22 | String lowerCorner(int total, int i, int span);
23 | }
24 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/model/JobBump.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.model;
2 |
3 | public class JobBump {
4 | public final Job from;
5 | public final Job to;
6 | public final boolean isCollision;
7 |
8 | public JobBump(Job from, Job to, boolean isCollision) {
9 | this.from = from;
10 | this.to = to;
11 | this.isCollision = isCollision;
12 | }
13 |
14 | @Override
15 | public String toString() {
16 | return "JobBump{" +
17 | "from=" + from +
18 | ", to=" + to +
19 | ", isCollision=" + isCollision +
20 | '}';
21 | }
22 |
23 | public String toNiceString() {
24 | return to + " (from:" + to + "/" + isCollision + ")";
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/java/hudson/plugins/scm/koji/KojiChangeLogParser.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.scm.koji;
2 |
3 | import hudson.model.Run;
4 | import hudson.plugins.scm.koji.model.Build;
5 | import hudson.scm.ChangeLogParser;
6 | import hudson.scm.ChangeLogSet;
7 | import hudson.scm.RepositoryBrowser;
8 | import java.io.File;
9 | import java.io.IOException;
10 | import org.xml.sax.SAXException;
11 |
12 | public class KojiChangeLogParser extends ChangeLogParser {
13 |
14 | @Override
15 | public ChangeLogSet extends ChangeLogSet.Entry> parse(Run run, RepositoryBrowser> browser, File changelogFile) throws IOException, SAXException {
16 | Build build = new BuildsSerializer().read(changelogFile);
17 | return new KojiChangeLogSet(build, run, browser);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/FakeKojiXmlRpcApi/config.jelly:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/java/hudson/plugins/scm/koji/KojiRevisionFromBuild.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.scm.koji;
2 |
3 | import hudson.FilePath;
4 | import hudson.plugins.scm.koji.model.Build;
5 | import hudson.remoting.VirtualChannel;
6 | import java.io.File;
7 | import java.io.IOException;
8 | import org.jenkinsci.remoting.RoleChecker;
9 |
10 | public class KojiRevisionFromBuild implements FilePath.FileCallable {
11 |
12 | @Override
13 | public Build invoke(File workspace, VirtualChannel channel) throws IOException, InterruptedException {
14 | Build build = new BuildsSerializer().read(new File(workspace, "changelog.xml"));
15 | return build;
16 | }
17 |
18 | @Override
19 | public void checkRoles(RoleChecker checker) throws SecurityException {
20 | // TODO maybe implement?
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/view.xml:
--------------------------------------------------------------------------------
1 |
2 | %{VIEW_NAME}
3 |
10 | true
11 | true
12 |
13 |
14 |
15 |
16 |
17 |
18 | %{COLUMNS}
19 |
20 | %{VIEW_REGEX}
21 | false
22 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcresponse/XmlRpcResponse.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcresponse;
2 |
3 | public interface XmlRpcResponse {
4 |
5 |
6 | /**
7 | * This method converts POJO to maps of objects or a simple object based on xml-rpc method it is used for. This
8 | * method is used in fake-koji xml-rpc api to send responses.
9 | *
10 | * @see RPMList
11 | * @see PackageId
12 | *
13 | * @return map of objects as Object
14 | */
15 | Object toObject();
16 |
17 | /**
18 | * This method converts a simple object or map of objects to POJO. It is reverse toXmlRpcParams method. This method is
19 | * used in xml-rpc client to receive responses
20 | *
21 | * @see RPMList
22 | * @see PackageId
23 | *
24 | * @return instance of requested type
25 | */
26 | T getValue();
27 | }
28 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/utils/matrix/cell/TitleCell.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.core.utils.matrix.cell;
2 |
3 | import java.util.Objects;
4 |
5 | public class TitleCell implements Cell {
6 |
7 | private final String title;
8 |
9 | public TitleCell(final String title) {
10 | this.title = title;
11 | }
12 |
13 | public String getTitle() {
14 | return title;
15 | }
16 |
17 | @Override
18 | public boolean equals(Object o) {
19 | if (this == o) return true;
20 | if (!(o instanceof TitleCell)) return false;
21 | TitleCell titleCell = (TitleCell) o;
22 | return Objects.equals(title, titleCell.title);
23 | }
24 |
25 | @Override
26 | public int hashCode() {
27 | return Objects.hash(title);
28 | }
29 |
30 | @Override
31 | public String toString() {
32 | return getTitle();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcrequestparams/ListRPMs.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcrequestparams;
2 |
3 | import hudson.plugins.scm.koji.Constants;
4 |
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | import static org.fakekoji.xmlrpc.server.xmlrpcrequestparams.XmlRpcRequestUtils.toMap;
9 |
10 | public class ListRPMs extends ListArtefacts {
11 |
12 | public ListRPMs(Integer buildId, List archs) {
13 | super(buildId, archs);
14 | }
15 |
16 | @Override
17 | public String getMethodName() {
18 | return Constants.listRPMs;
19 | }
20 |
21 | public static ListRPMs create(Object object) {
22 | final Map map = toMap(object);
23 | return new ListRPMs(
24 | (Integer) map.get(Constants.buildID),
25 | getArchs(map.get(Constants.arches))
26 | );
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/functional/Tuple.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.functional;
2 |
3 | import java.util.Objects;
4 |
5 | public class Tuple {
6 | public final X x;
7 | public final Y y;
8 |
9 | public Tuple(X x, Y y) {
10 | this.x = x;
11 | this.y = y;
12 | }
13 |
14 | @Override
15 | public boolean equals(Object o) {
16 | if (this == o) return true;
17 | if (!(o instanceof Tuple)) return false;
18 | Tuple, ?> tuple = (Tuple, ?>) o;
19 | return Objects.equals(x, tuple.x) &&
20 | Objects.equals(y, tuple.y);
21 | }
22 |
23 | @Override
24 | public int hashCode() {
25 | return Objects.hash(x, y);
26 | }
27 |
28 | @Override
29 | public String toString() {
30 | return "Tuple{" +
31 | "x=" + x +
32 | ", y=" + y +
33 | '}';
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/RealKojiXmlRpcApi/config.jelly:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/OToolUtils.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager;
2 |
3 | import java.io.File;
4 |
5 | public class OToolUtils {
6 |
7 | public static String createArchiveName(
8 | final File packageDir,
9 | final File versionDir,
10 | final File buildDir,
11 | final File archiveDir
12 | ) {
13 | return createArchiveName(packageDir.getName(), versionDir.getName(), buildDir.getName(), archiveDir.getName());
14 | }
15 |
16 | public static String createArchiveName(
17 | final String packageName,
18 | final String version,
19 | final String build,
20 | final String archive
21 | ) {
22 | return String.join(
23 | "-",
24 | packageName,
25 | version,
26 | build + "." + archive + ".tarxz"
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcrequestparams/ListArchives.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcrequestparams;
2 |
3 | import hudson.plugins.scm.koji.Constants;
4 |
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | import static org.fakekoji.xmlrpc.server.xmlrpcrequestparams.XmlRpcRequestUtils.toMap;
9 |
10 | public class ListArchives extends ListArtefacts {
11 |
12 | public ListArchives(Integer buildId, List archs) {
13 | super(buildId, archs);
14 | }
15 |
16 | @Override
17 | public String getMethodName() {
18 | return Constants.listArchives;
19 | }
20 |
21 | public static ListArchives create(Object object) {
22 | final Map map = toMap(object);
23 | return new ListArchives(
24 | (Integer) map.get(Constants.buildID),
25 | getArchs(map.get(Constants.arches))
26 | );
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/api/http/rest/args/RemoveTaskVariantArgs.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.api.http.rest.args;
2 |
3 | import org.fakekoji.api.http.rest.OToolError;
4 | import org.fakekoji.functional.Result;
5 |
6 | import java.util.List;
7 | import java.util.Map;
8 |
9 | import static org.fakekoji.api.http.rest.RestUtils.extractMandatoryParamValue;
10 |
11 | public class RemoveTaskVariantArgs extends BumpArgs {
12 | public final String name;
13 |
14 | RemoveTaskVariantArgs(final BumpArgs bumpArgs, final String name) {
15 | super(bumpArgs);
16 | this.name = name;
17 | }
18 |
19 | public static Result parse(final Map> params) {
20 | return parseBumpArgs(params).flatMap(bumpArgs -> extractMandatoryParamValue(params, "name").flatMap(name ->
21 | Result.ok(new RemoveTaskVariantArgs(bumpArgs, name))
22 | ));
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/java/hudson/plugins/scm/koji/model/KojiBuildDownloadResult.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.scm.koji.model;
2 |
3 | import java.util.List;
4 |
5 | public class KojiBuildDownloadResult implements java.io.Serializable {
6 |
7 | private final Build build;
8 | private final String rpmsDirectory;
9 | private final List rpmFiles;
10 |
11 | public KojiBuildDownloadResult(Build build, String rpmsDirectory, List rpmFiles) {
12 | this.build = build;
13 | this.rpmsDirectory = rpmsDirectory;
14 | this.rpmFiles = rpmFiles;
15 | }
16 |
17 | public boolean isEmpty() {
18 | return build == null || rpmFiles == null || rpmFiles.isEmpty();
19 | }
20 |
21 | public Build getBuild() {
22 | return build;
23 | }
24 |
25 | public String getRpmsDirectory() {
26 | return rpmsDirectory;
27 | }
28 |
29 | public List getRpmFiles() {
30 | return rpmFiles;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/hudson/plugins/scm/koji/model/BuildProvider.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.scm.koji.model;
2 |
3 | import jakarta.xml.bind.annotation.XmlAccessType;
4 | import jakarta.xml.bind.annotation.XmlAccessorType;
5 | import jakarta.xml.bind.annotation.XmlElement;
6 |
7 | @XmlAccessorType(XmlAccessType.FIELD)
8 | public class BuildProvider implements java.io.Serializable {
9 |
10 | @XmlElement(name = "topUrl")
11 | private final String topUrl;
12 |
13 | @XmlElement(name = "downloadUrl")
14 | private final String downloadUrl;
15 |
16 | public BuildProvider() {
17 | topUrl = null;
18 | downloadUrl = null;
19 | }
20 |
21 | public BuildProvider(String topUrl, String downloadUrl) {
22 | this.topUrl = topUrl;
23 | this.downloadUrl = downloadUrl;
24 | }
25 |
26 | public String getTopUrl() {
27 | return topUrl;
28 | }
29 |
30 | public String getDownloadUrl() {
31 | return downloadUrl;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/java/hudson/plugins/scm/koji/KojiXmlRpcApiType.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.scm.koji;
2 |
3 | import java.io.Serializable;
4 |
5 | public enum KojiXmlRpcApiType implements Serializable {
6 |
7 | REAL_KOJI("realKoji"),
8 | FAKE_KOJI("fakeKoji");
9 |
10 | private final String name;
11 |
12 | KojiXmlRpcApiType(final String xmlRpcApiName) {
13 | name = xmlRpcApiName;
14 | }
15 |
16 | @Override
17 | public String toString() {
18 | return getName();
19 | }
20 |
21 | public String getName() {
22 | return name;
23 | }
24 |
25 | public static KojiXmlRpcApiType getType(final String value) {
26 | for (KojiXmlRpcApiType type : KojiXmlRpcApiType.values()) {
27 | if (type.getName().equals(value)) {
28 | return type;
29 | }
30 | }
31 | throw new IllegalArgumentException("Invalid type (" + value + ") requested for "
32 | + KojiXmlRpcApiType.class.getName());
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/KojiSCM/help-KojiSCMConfig_skipPoolingIfJobRuns.html:
--------------------------------------------------------------------------------
1 |
2 |
If checked, the pooling is skipped (returning no chnages found) if jobs currently runs
3 |
4 | By default it is not selected
5 | It do not have much sense to have enabled both "require worksapce" and this
6 | it of course kill the can run in parallel feature
7 | General usecase is:
8 |
9 | do not enable run in parallel with this feature
10 | all the troubels are with archiving of build.xml, it match with build nvr and usage of archved build.xml to rerun the nvr
11 | with worksapce on, soemtimes the poling got stuck, waiting for wrkscpae for hours
12 | this is avoiding this problem, but may have other consequences
13 |
14 |
15 | this option is not exactly best tested, as is new
16 |
17 |
18 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/utils/matrix/cell/UpperCornerCell.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.core.utils.matrix.cell;
2 |
3 | import java.util.List;
4 | import java.util.Objects;
5 |
6 | public class UpperCornerCell implements Cell {
7 |
8 | private final List projectCells;
9 |
10 | public UpperCornerCell(final List projectCells) {
11 | this.projectCells = projectCells;
12 | }
13 |
14 | public List projectCells() {
15 | return this.projectCells;
16 | }
17 |
18 | @Override
19 | public int getSpan() {
20 | return projectCells.size();
21 | }
22 |
23 | @Override
24 | public boolean equals(Object o) {
25 | if (this == o) return true;
26 | if (!(o instanceof UpperCornerCell)) return false;
27 | UpperCornerCell that = (UpperCornerCell) o;
28 | return Objects.equals(projectCells, that.projectCells);
29 | }
30 |
31 | @Override
32 | public int hashCode() {
33 | return Objects.hash(projectCells);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcrequestparams/XmlRpcRequestUtils.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcrequestparams;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | public class XmlRpcRequestUtils {
9 |
10 | // this parameter allows XML-RPC contain non primitive data like maps
11 | static final String starStarLabel = "__starstar";
12 |
13 | static Map toMap(Object object) {
14 | return (Map) object;
15 | }
16 |
17 | public static List> toMaps(Object object) {
18 | final Object[] objectArray = (Object[]) object;
19 | if (objectArray == null) {
20 | return null;
21 | }
22 | final List objects = Arrays.asList(objectArray);
23 | final List> maps = new ArrayList<>(objects.size());
24 | for (Object o : objects) {
25 | maps.add(toMap(o));
26 | }
27 | return maps;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/task-job.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 |
6 |
7 | %{BUILD_PROVIDERS}
8 | %{XML_RPC_API}
9 | rpms
10 | true
11 | false
12 | 10
13 |
14 | %{NODES}
15 | false
16 | false
17 | false
18 | false
19 | %{TRIGGER}
20 | false
21 |
22 | %{BUILDER}
23 |
24 |
25 | %{POST_BUILD_TASKS}
26 | %{POST_BUILD_TASK_PLUGIN}
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/utils/matrix/cell/MultiUrlCell.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.core.utils.matrix.cell;
2 |
3 | import java.util.List;
4 | import java.util.Objects;
5 |
6 | public class MultiUrlCell extends TitleCell {
7 |
8 | private final List urls;
9 |
10 | public MultiUrlCell(final String title, final List urls) {
11 | super(title);
12 | this.urls = urls;
13 | }
14 |
15 | public List getUrls() {
16 | return urls;
17 | }
18 |
19 | @Override
20 | public int getSpan() {
21 | return this.urls.size();
22 | }
23 |
24 | @Override
25 | public boolean equals(Object o) {
26 | if (this == o) return true;
27 | if (!(o instanceof MultiUrlCell)) return false;
28 | MultiUrlCell that = (MultiUrlCell) o;
29 | return Objects.equals(urls, that.urls);
30 | }
31 |
32 | @Override
33 | public int hashCode() {
34 | return Objects.hash(urls);
35 | }
36 |
37 | @Override
38 | public String toString() {
39 | return getTitle() + " " + urls;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/webapp/src/components/Button.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 |
3 | import "../styles/Button.css"
4 |
5 | type ButtonColor = "red" | "green" | "gray" | "blue"
6 |
7 | type ButtonPropsOptional = {
8 | children: string | string[] | number | number[]
9 | onClick: () => void
10 | color: ButtonColor
11 | }
12 |
13 | type ButtonPropsRequired = {
14 |
15 | }
16 |
17 | type ButtonProps = ButtonPropsOptional & ButtonPropsRequired
18 |
19 | class Button extends React.PureComponent {
20 |
21 | static defaultProps: ButtonPropsOptional = {
22 | children: "",
23 | onClick: () => { },
24 | color: "blue"
25 | }
26 |
27 | onClick = (event: React.MouseEvent) => {
28 | event.stopPropagation()
29 | this.props.onClick()
30 | }
31 |
32 | render() {
33 | const { children, color } = this.props
34 | return (
35 |
38 | {children}
39 |
40 | )
41 | }
42 | }
43 |
44 | export default Button
45 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/KojiBuildProvider/config.jelly:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
32 |
33 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Stanislav Baiduzhyi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/model/PlatformBumpVariant.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.model;
2 |
3 | import org.fakekoji.functional.Result;
4 |
5 | import java.util.Arrays;
6 | import java.util.stream.Collectors;
7 |
8 | public enum PlatformBumpVariant {
9 | BUILD_ONLY("build_only"),
10 | TEST_ONLY("test_only"),
11 | BOTH("both");
12 |
13 | public final String value;
14 |
15 | PlatformBumpVariant(final String value) {
16 | this.value = value;
17 | }
18 |
19 | public static String stringValues(final String delimiter) {
20 | return Arrays.stream(PlatformBumpVariant.values())
21 | .map(variant -> variant.value)
22 | .collect(Collectors.joining(delimiter));
23 | }
24 |
25 | public static Result parse(final String value) {
26 | try {
27 | return Result.ok(PlatformBumpVariant.valueOf(value.toUpperCase()));
28 | } catch (IllegalArgumentException e) {
29 | return Result.err("Invalid platform bump variant: " + value + ". Valid options are: " + stringValues(", "));
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/model/JobCollisionAction.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.model;
2 |
3 | import org.fakekoji.functional.Result;
4 |
5 | import java.util.Arrays;
6 | import java.util.stream.Collectors;
7 |
8 | public enum JobCollisionAction {
9 | STOP("stop"),
10 | KEEP_EXISTING("keep_existing"),
11 | KEEP_BUMPED("keep_bumped");
12 |
13 | public final String value;
14 |
15 | JobCollisionAction(final String value) {
16 | this.value = value;
17 | }
18 |
19 | public static String stringValues(final String delimiter) {
20 | return Arrays.stream(JobCollisionAction.values())
21 | .map(variant -> variant.value)
22 | .collect(Collectors.joining(delimiter));
23 | }
24 |
25 | public static Result parse(final String value) {
26 | try {
27 | return Result.ok(JobCollisionAction.valueOf(value.toUpperCase()));
28 | } catch (IllegalArgumentException e) {
29 | return Result.err("Invalid job collision action: " + value + ". Valid options are: " + stringValues(", "));
30 | }
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/utils/matrix/cell/UrlCell.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.core.utils.matrix.cell;
2 |
3 | import java.util.Objects;
4 | import java.util.Optional;
5 |
6 | public class UrlCell extends TitleCell {
7 | private final String url;
8 |
9 | public UrlCell(final String title) {
10 | super(title);
11 | url = null;
12 | }
13 |
14 | public UrlCell(final String title, final String url) {
15 | super(title);
16 | this.url = url;
17 | }
18 |
19 | public Optional getUrl() {
20 | return Optional.ofNullable(url);
21 | }
22 |
23 | @Override
24 | public boolean equals(Object o) {
25 | if (this == o) return true;
26 | if (!(o instanceof UrlCell)) return false;
27 | if (!super.equals(o)) return false;
28 | UrlCell urlCell = (UrlCell) o;
29 | return Objects.equals(url, urlCell.url);
30 | }
31 |
32 | @Override
33 | public int hashCode() {
34 | return Objects.hash(super.hashCode(), url);
35 | }
36 |
37 | @Override
38 | public String toString() {
39 | return getUrl().orElse(getTitle());
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/webapp/src/components/Header.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { useObserver } from "mobx-react"
3 |
4 | import { AppBar, Tabs, Tab, Toolbar } from "@material-ui/core"
5 | import useStores from "../hooks/useStores"
6 |
7 | const Header: React.FC = () => {
8 | const { configStore, viewStore } = useStores()
9 |
10 | return useObserver(() => {
11 | const { selectedConfigGroupId } = configStore
12 | const { goToConfigList } = viewStore
13 | return (
14 |
15 |
16 |
17 | {configStore.configGroups.map(({ id }, index) => (
18 | goToConfigList(id)}
20 | key={index}
21 | label={id}
22 | value={id}
23 | />
24 | ))}
25 |
26 |
27 |
28 |
29 | )
30 | })
31 | }
32 |
33 | export default Header
34 |
--------------------------------------------------------------------------------
/webapp/src/components/formComponents/Checkbox.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { FormControl, FormControlLabel, Checkbox as CheckboxMaterial } from "@material-ui/core";
3 |
4 | type CheckboxPropsRequired = {
5 | label: string
6 | }
7 |
8 | type CheckboxPropsOptional = {
9 | onChange: (value: boolean) => void
10 | value: boolean
11 | }
12 |
13 | type CheckboxProps = CheckboxPropsRequired & CheckboxPropsOptional
14 |
15 | class Checkbox extends React.PureComponent {
16 |
17 | static defaultProps: CheckboxPropsOptional = {
18 | onChange: _ => null,
19 | value: false
20 | }
21 |
22 | onChange = (event: React.ChangeEvent) => {
23 | this.props.onChange(event.target.checked)
24 | }
25 |
26 | render() {
27 | const { label, value } = this.props
28 | return (
29 |
30 | }
35 | label={label} />
36 |
37 | )
38 | }
39 | }
40 |
41 | export default Checkbox
42 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/ManagementUtils.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager;
2 |
3 | import org.fakekoji.storage.Storage;
4 |
5 | import java.util.function.BiConsumer;
6 | import java.util.function.Consumer;
7 |
8 | public class ManagementUtils {
9 |
10 | public static void checkID(String id, Storage storage) throws ManagementException {
11 | checkID(id, storage, true);
12 | }
13 |
14 | public static void checkID(String id, Storage storage, boolean shouldExist) throws ManagementException {
15 | if (storage.contains(id) != shouldExist) {
16 | throw new ManagementException("Resource with ID " + id +
17 | (shouldExist ? " does not exist" : " already exists") + '!'
18 | );
19 | }
20 | }
21 |
22 | public static Consumer managementConsumerWrapper(ManagementConsumer consumer) {
23 | return i -> {
24 | try {
25 | consumer.accept(i);
26 | } catch (ManagementException e) {
27 | throw new RuntimeException(e);
28 | }
29 | };
30 | }
31 |
32 | public interface ManagementConsumer {
33 |
34 | void accept(T t) throws ManagementException;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcresponse/FakeBuildList.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcresponse;
2 |
3 | import hudson.plugins.scm.koji.model.Build;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 | import java.util.LinkedList;
8 | import java.util.List;
9 | import java.util.function.Supplier;
10 | import java.util.stream.Collectors;
11 | import java.util.stream.Stream;
12 |
13 | public class FakeBuildList implements XmlRpcResponse> {
14 |
15 | private final List buildList;
16 |
17 | public FakeBuildList(List buildList) {
18 | this.buildList = buildList;
19 | }
20 |
21 | @Override
22 | public Object toObject() {
23 | return buildList;
24 | }
25 |
26 | @Override
27 | public List getValue() {
28 | return buildList;
29 | }
30 |
31 | @SuppressWarnings("unchecked")
32 | public static FakeBuildList create(Object object) {
33 | final Object[] array = (Object[]) object;
34 | final List builds = Stream.of(array)
35 | .filter(obj -> obj instanceof Build)
36 | .map(obj -> (Build) obj)
37 | .collect(Collectors.toList());
38 | return new FakeBuildList(builds);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/model/JobConfiguration.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.model;
2 |
3 | import org.fakekoji.Utils;
4 |
5 | import java.util.Collections;
6 | import java.util.Objects;
7 | import java.util.Set;
8 |
9 | public class JobConfiguration {
10 |
11 | private final Set platforms;
12 |
13 | public JobConfiguration() {
14 | platforms = Collections.emptySet();
15 | }
16 |
17 | public JobConfiguration(Set platforms) {
18 | this.platforms = platforms != null ? platforms : Collections.emptySet();
19 | }
20 |
21 | public Set getPlatforms() {
22 | return platforms;
23 | }
24 |
25 | @Override
26 | public boolean equals(Object o) {
27 | if (this == o) return true;
28 | if (!(o instanceof JobConfiguration)) return false;
29 | JobConfiguration that = (JobConfiguration) o;
30 | return Utils.areEqual(platforms, that.platforms);
31 | }
32 |
33 | @Override
34 | public int hashCode() {
35 | return Objects.hash(platforms);
36 | }
37 |
38 | @Override
39 | public String toString() {
40 | return "JobConfiguration{" +
41 | "platforms=" + platforms +
42 | '}';
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/model/Product.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.model;
2 |
3 | import java.util.Objects;
4 |
5 | public class Product {
6 |
7 | private final String jdk;
8 | private final String packageName;
9 |
10 | public Product() {
11 | jdk = null;
12 | packageName = null;
13 | }
14 |
15 | public Product(String jdk, String packageName) {
16 | this.jdk = jdk;
17 | this.packageName = packageName;
18 | }
19 |
20 | public String getJdk() {
21 | return jdk;
22 | }
23 |
24 | public String getPackageName() {
25 | return packageName;
26 | }
27 |
28 | @Override
29 | public boolean equals(Object o) {
30 | if (this == o) return true;
31 | if (!(o instanceof Product)) return false;
32 | Product product = (Product) o;
33 | return Objects.equals(jdk, product.jdk) &&
34 | Objects.equals(packageName, product.packageName);
35 | }
36 |
37 | @Override
38 | public int hashCode() {
39 | return Objects.hash(jdk, packageName);
40 | }
41 |
42 | @Override
43 | public String toString() {
44 | return "Product{" +
45 | "jdk='" + jdk + '\'' +
46 | ", packageName='" + packageName + '\'' +
47 | '}';
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/model/TestJobConfiguration.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.model;
2 |
3 | import org.fakekoji.Utils;
4 |
5 | import java.util.Collections;
6 | import java.util.Objects;
7 | import java.util.Set;
8 |
9 | public class TestJobConfiguration {
10 |
11 | private final Set platforms;
12 |
13 | public TestJobConfiguration() {
14 | platforms = Collections.emptySet();
15 | }
16 |
17 | public TestJobConfiguration(Set platforms) {
18 | this.platforms = platforms != null ? platforms : Collections.emptySet();
19 | }
20 |
21 | public Set getPlatforms() {
22 | return platforms;
23 | }
24 |
25 | @Override
26 | public boolean equals(Object o) {
27 | if (this == o) return true;
28 | if (!(o instanceof TestJobConfiguration)) return false;
29 | TestJobConfiguration that = (TestJobConfiguration) o;
30 | return Utils.areEqual(platforms, that.platforms);
31 | }
32 |
33 | @Override
34 | public int hashCode() {
35 | return Objects.hash(platforms);
36 | }
37 |
38 | @Override
39 | public String toString() {
40 | return "TestJobConfiguration{" +
41 | "platforms=" + platforms +
42 | '}';
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/webapp/src/components/formComponents/TextArea.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { FormControl, FormLabel, TextareaAutosize } from "@material-ui/core";
3 |
4 | type TextAreaPropsOptional = {
5 | onChange: (value: string) => void
6 | placeholder: string
7 | value: string
8 | }
9 |
10 | type TextAreaPropsRequired = {
11 | label: string
12 | }
13 |
14 | type TextAreaProps = TextAreaPropsRequired & TextAreaPropsOptional
15 |
16 | class TextArea extends React.PureComponent {
17 |
18 | static defaultProps: TextAreaPropsOptional = {
19 | onChange: _ => { },
20 | placeholder: "",
21 | value: ""
22 | }
23 |
24 | onChange = (event: React.ChangeEvent) => {
25 | this.props.onChange(event.target.value)
26 | }
27 |
28 | render() {
29 | const { label, placeholder, value } = this.props
30 | return (
31 |
32 |
33 | {label}
34 |
35 |
39 |
40 | )
41 | }
42 | }
43 |
44 | export default TextArea;
45 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/functional/Result.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.functional;
2 |
3 | import java.util.function.Function;
4 |
5 | public class Result {
6 | private final V value;
7 | private final E error;
8 |
9 | private Result(V value, E error) {
10 | this.value = value;
11 | this.error = error;
12 | }
13 |
14 | public static Result ok(T value) {
15 | return new Result<>(value, null);
16 | }
17 |
18 | public static Result err(U error) {
19 | return new Result<>(null, error);
20 | }
21 |
22 | public Result flatMap(Function> mapper) {
23 | if (isError()) {
24 | return Result.err(error);
25 | }
26 | return mapper.apply(value);
27 | }
28 |
29 | public Result map(Function mapper) {
30 | if (isError()) {
31 | return Result.err(error);
32 | }
33 | return Result.ok(mapper.apply(value));
34 | }
35 |
36 | public boolean isOk() {
37 | return !isError();
38 | }
39 |
40 | public boolean isError() {
41 | return this.error != null;
42 | }
43 |
44 | public V getValue() {
45 | return this.value;
46 | }
47 |
48 | public E getError() {
49 | return this.error;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/webapp/src/components/formComponents/FormList.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { useObserver } from "mobx-react"
3 | import { FormControl, FormLabel, IconButton } from "@material-ui/core"
4 | import { Add, } from "@material-ui/icons"
5 | import DeleteButton from "../DeleteButton"
6 |
7 | interface FormListProps {
8 | data: any[]
9 | label: string
10 | onAdd: () => any
11 | renderItem: (item: any, index: number) => React.ReactNode
12 | }
13 |
14 | const FormList: React.FC = props => {
15 | return useObserver(() => {
16 | const { data, label, onAdd, renderItem } = props
17 | return (
18 |
19 |
20 | {label}
21 | {data.map((item, index) => (
22 |
23 | {renderItem(item, index)}
24 | data.splice(index, 1)} />
25 |
26 | ))}
27 |
28 |
data.push(onAdd())}>
29 |
30 |
31 |
32 | )
33 | })
34 | }
35 |
36 | export default FormList
37 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/utils/matrix/cell/CellGroup.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.core.utils.matrix.cell;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Objects;
6 |
7 | public class CellGroup implements Cell {
8 |
9 | private final List cells;
10 |
11 | public CellGroup() {
12 | cells = new ArrayList<>();
13 | }
14 |
15 | public CellGroup(final List cells) {
16 | this.cells = cells;
17 | }
18 |
19 | public void add(final TitleCell cell) {
20 | cells.add(cell);
21 | }
22 |
23 | public boolean isEmpty() {
24 | return cells.isEmpty();
25 | }
26 |
27 | @Override
28 | public int getSpan() {
29 | return cells.stream().map(Cell::getSpan).reduce(0, Integer::sum);
30 | }
31 |
32 | public int size() {
33 | return cells.size();
34 | }
35 |
36 | public List getCells() {
37 | return cells;
38 | }
39 |
40 | @Override
41 | public boolean equals(Object o) {
42 | if (this == o) return true;
43 | if (!(o instanceof CellGroup)) return false;
44 | CellGroup cellGroup = (CellGroup) o;
45 | return Objects.equals(cells, cellGroup.cells);
46 | }
47 |
48 | @Override
49 | public int hashCode() {
50 | return Objects.hash(cells);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/webapp/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import Header from "./components/Header"
3 | import ConfigForm from "./components/configForms/ConfigForm"
4 | import ConfirmDialog from "./components/ConfirmDialog"
5 | import ResultDialog from "./components/ResultDialog"
6 | import { useObserver } from "mobx-react"
7 |
8 | import { Grid } from "@material-ui/core"
9 | import useStores from "./hooks/useStores"
10 | import List from "./components/List"
11 |
12 | const App: React.FC = () => {
13 | const { configStore, viewStore } = useStores()
14 |
15 | React.useEffect(() => {
16 | configStore.fetchJenkinsUrl()
17 | configStore.fetchConfigs()
18 | }, [configStore])
19 |
20 | const content = useObserver(() => {
21 | const { currentView } = viewStore
22 | switch (currentView) {
23 | case "form":
24 | return
25 | case "list":
26 | return
27 | }
28 | })
29 |
30 | return (
31 |
32 |
33 |
34 |
35 | {content}
36 |
37 |
38 |
39 |
40 |
41 | )
42 | }
43 |
44 | export default App
45 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/ManagementResult.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager;
2 |
3 | import org.fakekoji.jobmanager.model.JobUpdateResults;
4 |
5 | import java.util.Objects;
6 |
7 | public class ManagementResult {
8 |
9 | public final C config;
10 | public final JobUpdateResults jobUpdateResults;
11 |
12 | public ManagementResult(C config, JobUpdateResults jobUpdateResults) {
13 | this.config = config;
14 | this.jobUpdateResults = jobUpdateResults;
15 | }
16 |
17 | public ManagementResult(C config) {
18 | this.config = config;
19 | this.jobUpdateResults = new JobUpdateResults();
20 | }
21 |
22 | @Override
23 | public boolean equals(Object o) {
24 | if (this == o) return true;
25 | if (!(o instanceof ManagementResult)) return false;
26 | ManagementResult that = (ManagementResult) o;
27 | return Objects.equals(config, that.config) &&
28 | Objects.equals(jobUpdateResults, that.jobUpdateResults);
29 | }
30 |
31 | @Override
32 | public int hashCode() {
33 | return Objects.hash(config, jobUpdateResults);
34 | }
35 |
36 | @Override
37 | public String toString() {
38 | return "ManagementResult{" +
39 | "config=" + config +
40 | ", jobupdateResults=" + jobUpdateResults +
41 | '}';
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcrequestparams/GetPackageId.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcrequestparams;
2 |
3 | import java.util.Objects;
4 |
5 | import hudson.plugins.scm.koji.Constants;
6 |
7 | public class GetPackageId implements XmlRpcRequestParams {
8 |
9 | private final String packageName;
10 |
11 | public GetPackageId(String packageName) {
12 | this.packageName = packageName;
13 | }
14 |
15 | @Override
16 | public Object[] toXmlRpcParams() {
17 | return new Object[]{packageName};
18 | }
19 |
20 | @Override
21 | public String getMethodName() {
22 | return Constants.getPackageID;
23 | }
24 |
25 | public String getPackageName() {
26 | return packageName;
27 | }
28 |
29 | public static GetPackageId create(Object object) {
30 | return new GetPackageId((String) object);
31 | }
32 |
33 | @Override
34 | public boolean equals(Object o) {
35 | if (this == o) return true;
36 | if (o == null || getClass() != o.getClass()) return false;
37 | GetPackageId that = (GetPackageId) o;
38 | return Objects.equals(packageName, that.packageName) &&
39 | Objects.equals(getMethodName(), that.getMethodName());
40 | }
41 |
42 | @Override
43 | public int hashCode() {
44 | return Objects.hash(getMethodName(), packageName);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/fake-koji/src/test/resources/org/fakekoji/core/utils/matrix/filtered_matrix:
--------------------------------------------------------------------------------
1 | all projects el7.x86_64.?-build el7.x86_64.?-jtreg-? el7.x86_64.?-tck-? f29.x86_64.?-build f29.x86_64.?-tck-? all projects
2 | el7.x86_64.?-jdk8-projectName-?0 0 0 0 0 el7.x86_64.?-jdk8-projectName-?
3 | el7.x86_64.?-jdk8-testProject-?1 1 2 0 2 el7.x86_64.?-jdk8-testProject-?
4 | el7.x86_64.?-jdk8-uName-? 1 0 4 0 0 el7.x86_64.?-jdk8-uName-?
5 | f29.x86_64.?-jdk8-uName-? 0 0 0 1 4 f29.x86_64.?-jdk8-uName-?
6 | 16/2904 el7.x86_64.?-build el7.x86_64.?-jtreg-? el7.x86_64.?-tck-? f29.x86_64.?-build f29.x86_64.?-tck-? 16/2904
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcrequestparams/XmlRpcRequestParams.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcrequestparams;
2 |
3 | import org.fakekoji.xmlrpc.server.expensiveobjectscache.CachableRequest;
4 |
5 | import java.io.Serializable;
6 | import java.util.Arrays;
7 | import java.util.stream.Collectors;
8 |
9 |
10 | public interface XmlRpcRequestParams extends Serializable, CachableRequest {
11 |
12 | /**
13 | * This method converts POJO to a map of objects with additional parameters based on XML-RPC method it is used for.
14 | * This method is used by XML-RPC client for sending XML-RPC requests.
15 | *
16 | * @return map of objects as Object
17 | * @see ListRPMs
18 | * @see GetPackageId
19 | */
20 | Object[] toXmlRpcParams();
21 |
22 | /**
23 | * This method returns name of the XML-RPC method that this class represents parameters of.
24 | *
25 | * @return XML-RPC method name
26 | */
27 | String getMethodName();
28 |
29 | public static String toNiceString(XmlRpcRequestParams o) {
30 | if (o == null) {
31 | return "null";
32 | }
33 | if (o.toXmlRpcParams() == null || o.toXmlRpcParams().length == 0) {
34 | return o.getMethodName() + "()";
35 | }
36 | return o.getMethodName()+"("+ Arrays.stream(o.toXmlRpcParams()).map(Object::toString).collect(Collectors.joining(","))+")";
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/webapp/src/components/formComponents/RPMLimitationForm.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { Grid } from "@material-ui/core"
3 | import { useObserver } from "mobx-react"
4 |
5 | import { RPMLimitation } from "../../stores/model"
6 | import TextInput from "./TextInput"
7 |
8 | interface Props {
9 | rpmLimitation: RPMLimitation
10 | }
11 |
12 | const RPMLimitationForm: React.FunctionComponent = ({ rpmLimitation }) => {
13 |
14 | const onRPMLimitationBlacklistChange = (value: string) => {
15 | rpmLimitation.blacklist = value.split(" ")
16 | }
17 |
18 | const onRPMLimitationWhitelistChange = (value: string) => {
19 | rpmLimitation.whitelist = value.split(" ")
20 | }
21 |
22 | return useObserver(() => {
23 | return (
24 |
25 |
26 |
30 |
34 |
35 |
36 |
37 | )
38 | })
39 | }
40 |
41 | export default RPMLimitationForm
42 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/java/hudson/plugins/scm/koji/LoggerHelp.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 | package hudson.plugins.scm.koji;
23 |
24 | public interface LoggerHelp{
25 |
26 | public void log(String s);
27 |
28 | public void log(String s, Object o);
29 |
30 | public void log(String s, Object... o);
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/webapp/src/components/formComponents/TextInput.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { useObserver } from "mobx-react"
3 | import { TextField } from "@material-ui/core"
4 | import { BasicValidation } from "../../utils/validators"
5 | import { TextFieldProps } from "@material-ui/core/TextField"
6 |
7 | type TextInputPropsRequired = {
8 | label: string
9 | }
10 |
11 | type TextInputPropsOptional = {
12 | onChange: (value: string) => void
13 | validation?: BasicValidation
14 | value?: string
15 | }
16 |
17 | type TextInputProps = TextInputPropsRequired & TextInputPropsOptional
18 |
19 | const TextInput: React.FC = props =>
20 | useObserver(() => {
21 | const { label, validation, value } = props
22 |
23 | const onChange = (event: React.ChangeEvent) => {
24 | props.onChange(event.target.value)
25 | }
26 |
27 | const errorProps: TextFieldProps =
28 | (validation &&
29 | validation !== "ok" && {
30 | error: true,
31 | helperText: validation
32 | }) ||
33 | {}
34 | return (
35 |
43 | )
44 | })
45 |
46 | export default TextInput
47 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/model/JobUpdateResult.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.model;
2 |
3 | import java.util.Objects;
4 |
5 | public class JobUpdateResult {
6 |
7 | public final String jobName;
8 | public final boolean success;
9 | public final String message;
10 |
11 | public JobUpdateResult(String jobName, boolean success, String message) {
12 | this.jobName = jobName;
13 | this.success = success;
14 | this.message = message;
15 | }
16 |
17 | public JobUpdateResult(String jobName, boolean success) {
18 | this.jobName = jobName;
19 | this.success = success;
20 | this.message = "";
21 | }
22 |
23 | @Override
24 | public boolean equals(Object o) {
25 | if (this == o) return true;
26 | if (!(o instanceof JobUpdateResult)) return false;
27 | JobUpdateResult that = (JobUpdateResult) o;
28 | return success == that.success &&
29 | Objects.equals(jobName, that.jobName) &&
30 | Objects.equals(message, that.message);
31 | }
32 |
33 | @Override
34 | public int hashCode() {
35 | return Objects.hash(jobName, success, message);
36 | }
37 |
38 | @Override
39 | public String toString() {
40 | return "JobUpdateResult{" +
41 | "jobName='" + jobName + '\'' +
42 | ", success=" + success +
43 | ", message='" + message + '\'' +
44 | '}';
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/model/TaskConfig.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.model;
2 |
3 | import org.fakekoji.Utils;
4 |
5 | import java.util.Collections;
6 | import java.util.Objects;
7 | import java.util.Set;
8 |
9 | public class TaskConfig {
10 |
11 | private final String id;
12 | private final Set variants;
13 |
14 | public TaskConfig() {
15 | id = null;
16 | variants = Collections.emptySet();
17 | }
18 |
19 | public TaskConfig(final String id, Set variants) {
20 | this.id = id;
21 | this.variants = variants != null ? variants : Collections.emptySet();
22 | }
23 |
24 | public String getId() {
25 | return id;
26 | }
27 |
28 | public Set getVariants() {
29 | return variants;
30 | }
31 |
32 | @Override
33 | public boolean equals(Object o) {
34 | if (this == o) return true;
35 | if (!(o instanceof TaskConfig)) return false;
36 | TaskConfig that = (TaskConfig) o;
37 | return Objects.equals(id, that.id) &&
38 | Utils.areEqual(variants, that.variants);
39 | }
40 |
41 | @Override
42 | public int hashCode() {
43 | return Objects.hash(id, variants);
44 | }
45 |
46 | @Override
47 | public String toString() {
48 | return "TaskConfig{" +
49 | "id='" + id + '\'' +
50 | ", variants=" + variants +
51 | '}';
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/utils/matrix/formatter/PlainTextFormatter.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.core.utils.matrix.formatter;
2 |
3 | import org.fakekoji.core.utils.matrix.cell.CellGroup;
4 | import org.fakekoji.core.utils.matrix.cell.TitleCell;
5 | import org.fakekoji.core.utils.matrix.cell.UpperCornerCell;
6 |
7 | public class PlainTextFormatter implements Formatter {
8 |
9 | @Override
10 | public String upperCorner(final UpperCornerCell cell) {
11 | if (cell.projectCells().size() > 1) {
12 | return cell.projectCells().size() + " projects";
13 | }
14 | return cell.projectCells().get(0).getTitle();
15 | }
16 |
17 | @Override
18 | public String lowerCorner(int found, int all, int span) {
19 | return found + "/" + all;
20 | }
21 |
22 | @Override
23 | public String rowStart() {
24 | return "";
25 | }
26 |
27 | @Override
28 | public String rowEnd() {
29 | return "\n";
30 | }
31 |
32 | @Override
33 | public String tableStart() {
34 | return "";
35 | }
36 |
37 | @Override
38 | public String tableEnd() {
39 | return "";
40 | }
41 |
42 | @Override
43 | public String edge(final TitleCell titleCell, final int span) {
44 | return titleCell.getTitle();
45 | }
46 |
47 | @Override
48 | public String cells(final CellGroup cellGroup, int maxInColumn, final String rowTitle, final String colTitle) {
49 | return "" + cellGroup.size();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/JobUpdater.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager;
2 |
3 | import org.fakekoji.functional.Tuple;
4 | import org.fakekoji.jobmanager.model.Job;
5 | import org.fakekoji.jobmanager.model.JobBump;
6 | import org.fakekoji.jobmanager.model.JobCollisionAction;
7 | import org.fakekoji.jobmanager.model.JobUpdateResults;
8 | import org.fakekoji.jobmanager.model.Project;
9 | import org.fakekoji.model.Platform;
10 | import org.fakekoji.model.Task;
11 | import org.fakekoji.storage.StorageException;
12 |
13 | import java.util.Set;
14 | import java.util.function.Function;
15 |
16 | public interface JobUpdater {
17 |
18 | JobUpdateResults update(Project oldProject, Project newProject) throws StorageException, ManagementException;
19 |
20 | JobUpdateResults regenerate(Project project, String whitelist) throws StorageException, ManagementException;
21 |
22 | JobUpdateResults regenerateAll(
23 | String projectId,
24 | Manager projectManager,
25 | String whitelist
26 | ) throws StorageException, ManagementException;
27 |
28 | JobUpdateResults update(Platform platform) throws StorageException;
29 |
30 | JobUpdateResults update(Task task) throws StorageException;
31 |
32 | Function, JobBump> getCollisionCheck();
33 |
34 | Set> findCollisions(final Set> jobTuples);
35 |
36 | JobUpdateResults bump(final Set jobTuple, final JobCollisionAction action);
37 | }
38 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/KojiSCM/help-KojiSCMConfig_requireWorkspace.html:
--------------------------------------------------------------------------------
1 |
2 |
If checked, then KojiSCM plugin requires workspace for pooling.
3 |
4 | By default not-selected
5 | If KojiSCM requires workspace, then the single exact job can not be run in parallel
6 | If KojiSCM don't requires workspace, then the single exact job can be run in parallel
7 | if you unselect it (so it don't require workspace ), you may run the same job in parallel
8 | In that case, be sure, that next pooling is invoked after the checkout is finished, otherwise you end with same build in queue
9 | General usecase is:
10 |
11 | some long job is running, but otherwise the host is bored
12 | everything else is done except next this job
13 | in desired project select "Execute concurrent builds if necessary"
14 | unselect this
15 | schedule/let schedule another job and wait until it is in execution (in parallel)
16 | select this
17 | in desired project unselect "Execute concurrent builds if necessary"
18 | after its checkout is done, verify processed.txt in job's folder
19 |
20 | this option unselected is not exactly well tested
21 |
22 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/test/java/hudson/plugins/scm/koji/LocalDateTimeWithDateTimeFormatterTest.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.scm.koji;
2 |
3 | import org.junit.Test;
4 |
5 | import java.time.LocalDateTime;
6 |
7 | import static org.junit.Assert.*;
8 |
9 | public class LocalDateTimeWithDateTimeFormatterTest {
10 | @Test
11 | public void testDTFOptionalWithMicros() {
12 | assertEquals(LocalDateTime.of(2018, 12, 31, 12, 34, 56, 123456000),
13 | LocalDateTime.parse("2018-12-31 12:34:56.123456", Constants.DTF));
14 | }
15 |
16 | @Test
17 | public void testDTFOptionalWithoutMicros() {
18 | // Brew started sending datetime without microseconds for some builds and this format caused an issue with our
19 | // DateTimeFormatter. It is fixed now with optional microseconds.
20 | assertEquals(LocalDateTime.of(2018, 12, 31, 12, 34, 56),
21 | LocalDateTime.parse("2018-12-31 12:34:56", Constants.DTF));
22 | }
23 |
24 | @Test
25 | public void testDTFOptionalToStringWithoutMicros() {
26 | LocalDateTime expectedTime = LocalDateTime.of(2018, 12, 31, 12, 34, 56);
27 |
28 | assertEquals("2018-12-31 12:34:56.0", Constants.DTF.format(expectedTime));
29 | }
30 |
31 | @Test
32 | public void testDTFOptionalToStringWithMicros() {
33 | LocalDateTime expectedTime = LocalDateTime.of(2018, 12, 31, 12, 34, 56, 123456000);
34 |
35 | assertEquals("2018-12-31 12:34:56.123456", Constants.DTF.format(expectedTime));
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/webapp/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "otool",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@babel/core": "^7.17.2",
7 | "@babel/plugin-syntax-flow": "^7.16.7",
8 | "@babel/plugin-transform-react-jsx": "^7.16.7",
9 | "@material-ui/core": "^4.12.3",
10 | "@material-ui/icons": "^4.11.2",
11 | "@types/history": "^5.0.0",
12 | "@types/jest": "27.4.0",
13 | "@types/node": "17.0.16",
14 | "@types/react": "17.0.39",
15 | "@types/react-dom": "17.0.11",
16 | "acorn": "^8.7.0",
17 | "autoprefixer": "^10.4.2",
18 | "browserslist": "^4.19.1",
19 | "history": "^5.2.0",
20 | "kind-of": "^6.0.3",
21 | "minimist": "^1.2.6",
22 | "mobx": "6.3.13",
23 | "mobx-react": "7.2.1",
24 | "path-to-regexp": "^6.3.0",
25 | "postcss": "^8.4.31",
26 | "react": "17.0.2",
27 | "react-dom": "17.0.2",
28 | "react-scripts": "5.0.0",
29 | "serialize-javascript": "^6.0.0",
30 | "typescript": "4.5.5"
31 | },
32 | "scripts": {
33 | "start": "react-scripts start",
34 | "build": "react-scripts build",
35 | "test": "react-scripts test",
36 | "eject": "react-scripts eject"
37 | },
38 | "eslintConfig": {
39 | "extends": "react-app"
40 | },
41 | "browserslist": {
42 | "production": [
43 | ">0.2%",
44 | "not dead",
45 | "not op_mini all"
46 | ],
47 | "development": [
48 | "last 1 chrome version",
49 | "last 1 firefox version",
50 | "last 1 safari version"
51 | ]
52 | },
53 | "devDependencies": {}
54 | }
55 |
--------------------------------------------------------------------------------
/webapp/src/components/ConfirmDialog.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { Dialog, DialogTitle, DialogActions, Button } from "@material-ui/core"
3 | import { useObserver } from "mobx-react"
4 |
5 | import useStores from "../hooks/useStores"
6 |
7 | interface ConfirmDialogProps {}
8 |
9 | const ConfirmDialog: React.FC = () => {
10 | const { viewStore } = useStores()
11 | const yesButton = React.useRef(null)
12 |
13 | const onEnter = React.useCallback(() => {
14 | if (!viewStore.dialog.open) {
15 | return
16 | }
17 | if (!yesButton.current) {
18 | return
19 | }
20 | yesButton.current.focus()
21 | }, [viewStore.dialog.open])
22 |
23 | return useObserver(() => {
24 | const { closeDialog, dialog } = viewStore
25 | const onYesClick = () => {
26 | closeDialog()
27 | dialog.action()
28 | }
29 | const onNoClick = () => {
30 | closeDialog()
31 | }
32 | return (
33 |
34 | {dialog.label}
35 |
36 |
37 | yes
38 |
39 | cancel
40 |
41 |
42 | )
43 | })
44 | }
45 |
46 | export default ConfirmDialog
47 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/model/BuildPlatformConfig.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.model;
2 |
3 | import org.fakekoji.Utils;
4 |
5 | import java.util.Collections;
6 | import java.util.List;
7 | import java.util.Objects;
8 | import java.util.Set;
9 |
10 | public class BuildPlatformConfig {
11 |
12 | private final String id;
13 | private final Set variants;
14 |
15 | public BuildPlatformConfig() {
16 | id = null;
17 | variants = Collections.emptySet();
18 | }
19 |
20 | public BuildPlatformConfig(String id, Set variants) {
21 | this.id = id;
22 | this.variants = variants != null ? variants : Collections.emptySet();
23 | }
24 |
25 | public String getId() {
26 | return id;
27 | }
28 |
29 | public Set getVariants() {
30 | return variants;
31 | }
32 |
33 | @Override
34 | public boolean equals(Object o) {
35 | if (this == o) return true;
36 | if (!(o instanceof BuildPlatformConfig)) return false;
37 | BuildPlatformConfig that = (BuildPlatformConfig) o;
38 | return Objects.equals(id, that.id) &&
39 | Utils.areEqual(variants, that.variants);
40 | }
41 |
42 | @Override
43 | public int hashCode() {
44 | return Objects.hash(id, variants);
45 | }
46 |
47 | @Override
48 | public String toString() {
49 | return "BuildPlatformConfig{" +
50 | "id='" + id + '\'' +
51 | ", variants=" + variants +
52 | '}';
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/utils/DirFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2015 user.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package org.fakekoji.core.utils;
25 |
26 | import java.io.File;
27 | import java.io.FileFilter;
28 |
29 | public class DirFilter implements FileFilter {
30 |
31 | public DirFilter() {
32 | }
33 |
34 | @Override
35 | public boolean accept(File pathname) {
36 | return pathname.isDirectory();
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/utils/FileFileFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2015 user.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package org.fakekoji.core.utils;
25 |
26 | import java.io.File;
27 | import java.io.FileFilter;
28 |
29 | public class FileFileFilter implements FileFilter {
30 |
31 | public FileFileFilter() {
32 | }
33 |
34 | @Override
35 | public boolean accept(File pathname) {
36 | return !pathname.isDirectory();
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/koji-scm-lib/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 |
6 | fake-koji
7 | koji-scm
8 | 2.2-SNAPSHOT
9 |
10 |
11 | koji-scm-lib
12 | jar
13 |
14 | Koji SCM Lib
15 |
16 |
17 |
18 | org.apache.xmlrpc
19 | xmlrpc-client
20 |
21 |
22 | org.slf4j
23 | slf4j-jdk14
24 | 1.7.33
25 |
26 |
27 | com.github.spotbugs
28 | spotbugs-annotations
29 | 4.5.3
30 |
31 |
32 | jakarta.xml.bind
33 | jakarta.xml.bind-api
34 | 3.0.1
35 |
36 |
37 | com.sun.xml.bind
38 | jaxb-impl
39 | 2.3.3
40 | runtime
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/utils/matrix/TestSpec.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.core.utils.matrix;
2 |
3 | import org.fakekoji.model.Platform;
4 | import org.fakekoji.model.Task;
5 |
6 | import java.util.Collections;
7 | import java.util.List;
8 |
9 | class TestSpec extends Spec {
10 | private final Task task;
11 |
12 |
13 | public TestSpec(
14 | final Platform platform,
15 | final Platform.Provider provider,
16 | final Task task,
17 | final List variants,
18 | final TestEqualityFilter viewFilter
19 | ) {
20 | super(platform, provider, viewFilter, variants);
21 | this.task = task;
22 | }
23 |
24 | public TestSpec(
25 | final Platform platform,
26 | final Platform.Provider provider,
27 | final Task task,
28 | final TestEqualityFilter viewFilter
29 | ) {
30 | super(platform, provider, viewFilter, Collections.emptyList());
31 | this.task = task;
32 | }
33 |
34 | public Task getTask() {
35 | return task;
36 | }
37 |
38 | private TestEqualityFilter getViewFilter() {
39 | return (TestEqualityFilter) viewFilter;
40 | }
41 |
42 | @Override
43 | public String toString() {
44 | String tsk = task.getId();
45 | if (!getViewFilter().suite) {
46 | tsk = "?";
47 | }
48 | return getPlatformString()+
49 | "-" + tsk + getVariantsString();
50 | }
51 |
52 | public boolean matchSuite(String id){
53 | return !getViewFilter().suite || task.getId().equals(id);
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcrequestparams/GetBuildDetail.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcrequestparams;
2 |
3 | import java.util.Objects;
4 |
5 | import hudson.plugins.scm.koji.Constants;
6 |
7 | public class GetBuildDetail implements XmlRpcRequestParams {
8 |
9 | private final String nvr;
10 | public final String n;
11 | public final String v;
12 | public final String r;
13 |
14 | public GetBuildDetail(String n, String v, String r) {
15 | this.nvr = n + "-" + v + "-" + r;
16 | this.n = n;
17 | this.v = v;
18 | this.r = r;
19 | }
20 |
21 | @Override
22 | public Object[] toXmlRpcParams() {
23 | return new Object[]{this};
24 | }
25 |
26 | @Override
27 | public boolean equals(Object o) {
28 | if (this == o) return true;
29 | if (o == null || getClass() != o.getClass()) return false;
30 | GetBuildDetail that = (GetBuildDetail) o;
31 | return Objects.equals(n, that.n) &&
32 | Objects.equals(v, that.v) &&
33 | Objects.equals(r, that.r) &&
34 | Objects.equals(getMethodName(), that.getMethodName());
35 | }
36 |
37 | @Override
38 | public int hashCode() {
39 | return Objects.hash(getMethodName(), n, v, r);
40 | }
41 |
42 | @Override
43 | public String getMethodName() {
44 | return Constants.getBuildDetail;
45 | }
46 |
47 | public String getNvr() {
48 | return nvr;
49 | }
50 |
51 | public static GetBuildDetail create(Object object) {
52 | return (GetBuildDetail) object;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcresponse/TagSet.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcresponse;
2 |
3 | import hudson.plugins.scm.koji.Constants;
4 |
5 | import java.util.ArrayList;
6 | import java.util.HashMap;
7 | import java.util.HashSet;
8 | import java.util.List;
9 | import java.util.Map;
10 | import java.util.Set;
11 |
12 | import static org.fakekoji.xmlrpc.server.xmlrpcrequestparams.XmlRpcRequestUtils.toMaps;
13 |
14 | public class TagSet implements XmlRpcResponse> {
15 |
16 | private final Set tags;
17 |
18 | public TagSet(Set tags) {
19 | this.tags = tags;
20 | }
21 |
22 | @Override
23 | public Object toObject() {
24 | return parseTags();
25 | }
26 |
27 | @Override
28 | public Set getValue() {
29 | return tags;
30 | }
31 |
32 | private static Set parseTagMaps(List> maps) {
33 | final Set tags = new HashSet<>();
34 | for (Map tagMap : maps) {
35 | tags.add((String) tagMap.get(Constants.name));
36 | }
37 | return tags;
38 | }
39 |
40 | private List> parseTags() {
41 | List> maps = new ArrayList<>();
42 | for (String tag : tags) {
43 | Map tagMap = new HashMap<>();
44 | tagMap.put(Constants.name, tag);
45 | maps.add(tagMap);
46 | }
47 | return maps;
48 | }
49 |
50 | public static TagSet create(Object object) {
51 | return new TagSet(parseTagMaps(toMaps(object)));
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/api/http/rest/args/BumpArgs.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.api.http.rest.args;
2 |
3 | import org.fakekoji.api.http.rest.OToolError;
4 | import org.fakekoji.api.http.rest.RestUtils;
5 | import org.fakekoji.functional.Result;
6 | import org.fakekoji.jobmanager.model.JobCollisionAction;
7 |
8 | import java.util.List;
9 | import java.util.Map;
10 |
11 | import static org.fakekoji.api.http.rest.BumperAPI.EXECUTE;
12 | import static org.fakekoji.api.http.rest.BumperAPI.JOB_COLLISION_ACTION;
13 |
14 | public class BumpArgs {
15 | public final JobCollisionAction action;
16 | public boolean execute;
17 |
18 | public BumpArgs(final JobCollisionAction action, final boolean execute) {
19 | this.action = action;
20 | this.execute = execute;
21 | }
22 |
23 | BumpArgs(final BumpArgs bumpArgs) {
24 | this(bumpArgs.action, bumpArgs.execute);
25 | }
26 |
27 | public static Result parseBumpArgs(final Map> paramsMap) {
28 | final String executeParam = RestUtils.extractParamValue(paramsMap, EXECUTE).orElse("false");
29 | final boolean execute = Boolean.parseBoolean(executeParam);
30 | final Result actionResult = RestUtils.extractParamValue(paramsMap, JOB_COLLISION_ACTION)
31 | .map(JobCollisionAction::parse)
32 | .orElse(Result.ok(JobCollisionAction.STOP));
33 | if (actionResult.isError()) {
34 | return Result.err(new OToolError(actionResult.getError(), 400));
35 | }
36 | return Result.ok(new BumpArgs(actionResult.getValue(), execute));
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/webapp/src/components/formComponents/Select.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import {
3 | FormControl,
4 | InputLabel,
5 | Select as MaterialSelect,
6 | MenuItem,
7 | FormHelperText
8 | } from "@material-ui/core"
9 | import { BasicValidation } from "../../utils/validators"
10 |
11 | type SelectPropsRequired = {
12 | options: string[]
13 | }
14 |
15 | type SelectPropsOptional = {
16 | label?: string
17 | onChange: (value: string) => void
18 | validation?: BasicValidation
19 | value?: string
20 | }
21 |
22 | type SelectProps = SelectPropsRequired & SelectPropsOptional
23 |
24 | const Select: React.FC = props => {
25 | const { label, options, validation, value } = props
26 |
27 | const onChange = (
28 | event: React.ChangeEvent<{ name?: string | undefined; value: unknown }>
29 | ) => {
30 | props.onChange(event.target.value as string)
31 | }
32 |
33 | const isError = validation && validation !== "ok"
34 |
35 | return (
36 |
37 | {label && {label} }
38 |
41 | None
42 | {options.map(option => (
43 |
44 | {option}
45 |
46 | ))}
47 |
48 | {isError && {validation} }
49 |
50 | )
51 | }
52 |
53 | export default Select
54 |
--------------------------------------------------------------------------------
/webapp/src/styles/Forms.css:
--------------------------------------------------------------------------------
1 | fieldset {
2 | border: none;
3 | }
4 |
5 | form {
6 | padding: 12px;
7 | }
8 |
9 | label {
10 | padding: 12px 12px 12px 0;
11 | display: inline-block;
12 | }
13 |
14 | input[type=text], select, textarea {
15 | width: 100%;
16 | padding: 12px;
17 | border: 1px solid #ccc;
18 | border-radius: 4px;
19 | resize: vertical;
20 | }
21 |
22 | .dropdown {
23 | display: inline-block;
24 | position: relative;
25 | }
26 |
27 | .dropdown:hover:hover .dropdown-button {
28 | background-color: #ddd;
29 | }
30 |
31 | .dropdown:hover .dropdown-content {
32 | display: block;
33 | }
34 |
35 | .dropdown-button {
36 | background-color: #ccc;
37 | border: none;
38 | color: #000;
39 | cursor: pointer;
40 | font-size: 16px;
41 | padding: 16px;
42 | }
43 |
44 | .dropdown-content {
45 | background-color: #ccc;
46 | box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
47 | display: none;
48 | min-width: 160px;
49 | position: absolute;
50 | z-index: 1;
51 | }
52 |
53 | .dropdown-content span {
54 | color: black;
55 | cursor: pointer;
56 | display: block;
57 | padding: 12px 16px;
58 | text-decoration: none;
59 | }
60 |
61 | .dropdown-content span:hover {
62 | background-color: #f1f1f1;
63 | }
64 |
65 | .field-container {
66 | display: grid;
67 | grid-template-columns: 1fr 3fr;
68 | }
69 |
70 | .label-container {
71 | margin-top: 6px;
72 | }
73 |
74 | .value-container {
75 | margin-top: 6px;
76 | }
77 |
78 | .error-container {
79 | background-color: #e33021;
80 | color: #fff;
81 | display: grid;
82 | grid-template-columns: 3fr 1fr;
83 | padding: 10px;
84 | }
85 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/bumpers/BumpResult.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.bumpers;
2 |
3 | import org.fakekoji.jobmanager.BuildDirUpdater;
4 | import org.fakekoji.jobmanager.model.JobUpdateResults;
5 |
6 | import java.util.Optional;
7 |
8 | public class BumpResult {
9 | private final JobUpdateResults jobResults;
10 | private final BuildDirUpdater.BuildUpdateSummary buildUpdateSummary;
11 | private final String message;
12 |
13 | public BumpResult(
14 | final JobUpdateResults jobResults,
15 | final BuildDirUpdater.BuildUpdateSummary buildUpdateSummary,
16 | final String message
17 | ) {
18 | this.jobResults = jobResults;
19 | this.buildUpdateSummary = buildUpdateSummary;
20 | this.message = message == null ? "" : message;
21 | }
22 |
23 | public BumpResult(JobUpdateResults jobResults) {
24 | this(jobResults, null, null);
25 | }
26 |
27 | public BumpResult(
28 | final JobUpdateResults jobResults,
29 | final BuildDirUpdater.BuildUpdateSummary buildUpdateSummary
30 | ) {
31 | this(jobResults, buildUpdateSummary, null);
32 | }
33 |
34 | public BumpResult(
35 | final JobUpdateResults jobResults,
36 | final String message
37 | ) {
38 | this(jobResults, null, message);
39 | }
40 |
41 |
42 | public JobUpdateResults getJobResults() {
43 | return jobResults;
44 | }
45 |
46 | public Optional getBuildUpdateSummary() {
47 | return Optional.ofNullable(buildUpdateSummary);
48 | }
49 |
50 | public String getMessage() {
51 | return message;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcresponse/ArchiveList.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcresponse;
2 |
3 | import hudson.plugins.scm.koji.Constants;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Collections;
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | import static org.fakekoji.xmlrpc.server.xmlrpcrequestparams.XmlRpcRequestUtils.toMaps;
11 |
12 | public class ArchiveList implements XmlRpcResponse> {
13 |
14 | private final List archives;
15 |
16 | public ArchiveList(List archives) {
17 | this.archives = archives;
18 | }
19 |
20 | @Override
21 | public Object toObject() {
22 | /*
23 | Normally, it should return array of maps (as array of objects),
24 | but it is not implemented in fake-koji so I return empty array
25 | */
26 | return new Object[]{};
27 | }
28 |
29 | @Override
30 | public List getValue() {
31 | return archives;
32 | }
33 |
34 | private static List parseArchiveMaps(List> maps) {
35 | if (maps == null) {
36 | return Collections.emptyList();
37 | }
38 | final List archives = new ArrayList<>(maps.size());
39 | for (Map map : maps) {
40 | archives.add(parseArchiveMap(map));
41 | }
42 | return archives;
43 | }
44 |
45 | private static String parseArchiveMap(Map map) {
46 | return (String) map.get(Constants.filename);
47 | }
48 |
49 | public static ArchiveList create(Object object) {
50 | return new ArchiveList(parseArchiveMaps(toMaps(object)));
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/views/VersionlessPlatform.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.views;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | import java.util.Objects;
6 |
7 | public class VersionlessPlatform implements CharSequence, Comparable {
8 | private final String os;
9 | private final String arch;
10 |
11 | @Override
12 | public boolean equals(Object o) {
13 | if (this == o) return true;
14 | if (o == null || getClass() != o.getClass()) return false;
15 | VersionlessPlatform that = (VersionlessPlatform) o;
16 | return Objects.equals(os, that.os) &&
17 | Objects.equals(arch, that.arch);
18 | }
19 |
20 | @Override
21 | public int hashCode() {
22 | return Objects.hash(os, arch);
23 | }
24 |
25 | public VersionlessPlatform(String os, String arch) {
26 | this.os = os;
27 | this.arch = arch;
28 | }
29 |
30 | public String getOs() {
31 | return os;
32 | }
33 |
34 | public String getArch() {
35 | return arch;
36 | }
37 |
38 | public String getId() {
39 | return os + JenkinsViewTemplateBuilderFactory.getMinorDelimiter() + arch;
40 | }
41 |
42 | @Override
43 | public int length() {
44 | return getId().length();
45 | }
46 |
47 | @Override
48 | public char charAt(int index) {
49 | return getId().charAt(index);
50 | }
51 |
52 | @Override
53 | public CharSequence subSequence(int start, int end) {
54 | return getId().subSequence(start, end);
55 | }
56 |
57 | @Override
58 | public int compareTo(@NotNull VersionlessPlatform o) {
59 | return getId().compareTo(o.getId());
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/model/JDKVersion.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.model;
2 |
3 | import java.util.List;
4 | import java.util.Objects;
5 |
6 | public class JDKVersion {
7 |
8 | private final String id;
9 | private final String label;
10 | private final String version;
11 | private final List packageNames;
12 |
13 | public JDKVersion() {
14 | id = null;
15 | label = null;
16 | version = null;
17 | packageNames = null;
18 | }
19 |
20 | public JDKVersion(
21 | String id,
22 | String label,
23 | String version,
24 | List packageNames
25 | ) {
26 | this.id = id;
27 | this.label = label;
28 | this.version = version;
29 | this.packageNames = packageNames;
30 | }
31 |
32 | public String getId() {
33 | return id;
34 | }
35 |
36 | public String getLabel() {
37 | return label;
38 | }
39 |
40 | public String getVersion() {
41 | return version;
42 | }
43 |
44 | public List getPackageNames() {
45 | return packageNames;
46 | }
47 |
48 | @Override
49 | public boolean equals(Object o) {
50 | if (this == o) return true;
51 | if (!(o instanceof JDKVersion)) return false;
52 | JDKVersion product = (JDKVersion) o;
53 | return Objects.equals(id, product.id) &&
54 | Objects.equals(label, product.label) &&
55 | Objects.equals(version, product.version) &&
56 | Objects.equals(packageNames, product.packageNames);
57 | }
58 |
59 | @Override
60 | public int hashCode() {
61 | return Objects.hash(id, label, version, packageNames);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/java/hudson/plugins/scm/koji/client/FakeKojiBuildMatcher.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.scm.koji.client;
2 |
3 | import hudson.plugins.scm.koji.FakeKojiXmlRpcApi;
4 | import hudson.plugins.scm.koji.KojiBuildProvider;
5 | import hudson.plugins.scm.koji.LoggerHelp;
6 | import hudson.plugins.scm.koji.model.Build;
7 | import hudson.plugins.scm.koji.model.BuildProvider;
8 | import org.fakekoji.xmlrpc.server.xmlrpcrequestparams.GetBuildList;
9 | import org.fakekoji.xmlrpc.server.xmlrpcresponse.FakeBuildList;
10 |
11 | import java.util.List;
12 | import java.util.function.Predicate;
13 |
14 | class FakeKojiBuildMatcher extends BuildMatcher {
15 |
16 | private final FakeKojiXmlRpcApi xmlRpcApi;
17 |
18 | public FakeKojiBuildMatcher(
19 | List buildProviders,
20 | Predicate notProcessedNvrPredicate,
21 | int maxBuilds,
22 | FakeKojiXmlRpcApi xmlRpcApi,
23 | LoggerHelp logger
24 | ) {
25 | super(buildProviders, notProcessedNvrPredicate, maxBuilds, logger);
26 | this.xmlRpcApi = xmlRpcApi;
27 | }
28 |
29 | @Override
30 | List getBuilds(BuildProvider buildProvider) {
31 | final GetBuildList getBuildListParams = new GetBuildList(
32 | xmlRpcApi.getProjectName(),
33 | xmlRpcApi.getBuildVariants(),
34 | xmlRpcApi.getBuildPlatform(),
35 | xmlRpcApi.isBuilt()
36 | );
37 | final FakeBuildList buildList = FakeBuildList.create(execute(buildProvider.getTopUrl(), getBuildListParams));
38 | return buildList.getValue();
39 | }
40 |
41 | @Override
42 | Build getBuild(Build build) {
43 | return build;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/core/utils/matrix/BuildSpec.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.core.utils.matrix;
2 |
3 | import org.fakekoji.jobmanager.model.Product;
4 | import org.fakekoji.jobmanager.model.Project;
5 | import org.fakekoji.model.Platform;
6 |
7 | import java.util.List;
8 |
9 | class BuildSpec extends Spec {
10 |
11 | private final String projectName;
12 | private final Product product;
13 |
14 | public BuildSpec(
15 | final Platform platform,
16 | final Platform.Provider provider,
17 | final Project project,
18 | final List variants,
19 | final BuildEqualityFilter viewFilter) {
20 | this(platform, provider, project.getId(), project.getProduct(), variants, viewFilter);
21 | }
22 |
23 | public BuildSpec(
24 | final Platform platform,
25 | final Platform.Provider provider,
26 | final String projectName,
27 | final Product product,
28 | final List variants,
29 | final BuildEqualityFilter viewFilter) {
30 | super(platform, provider, viewFilter, variants);
31 | this.projectName = projectName;
32 | this.product = product;
33 | }
34 |
35 | private BuildEqualityFilter getViewFilter() {
36 | return (BuildEqualityFilter) viewFilter;
37 | }
38 |
39 | @Override
40 | public String toString() {
41 | String jdk= product.getJdk();
42 | if (!getViewFilter().jdk){
43 | jdk = "?";
44 | }
45 |
46 | String prj = projectName;
47 | if (!getViewFilter().project){
48 | prj = "?";
49 | }
50 | return getPlatformString()+
51 | "-" + jdk + "-" + prj +
52 | getVariantsString();
53 |
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/model/PlatformConfig.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.model;
2 |
3 | import org.fakekoji.Utils;
4 |
5 | import java.util.Collections;
6 | import java.util.Objects;
7 | import java.util.Set;
8 |
9 | public class PlatformConfig {
10 |
11 | private final String id;
12 | private final Set tasks;
13 | private final String provider;
14 |
15 | public PlatformConfig() {
16 | id = null;
17 | tasks = Collections.emptySet();
18 | provider = null;
19 | }
20 |
21 | public PlatformConfig(String id, Set tasks, String provider) {
22 | this.id = id;
23 | this.tasks = tasks != null ? tasks : Collections.emptySet();
24 | this.provider = provider;
25 | }
26 |
27 | public String getId() {
28 | return id;
29 | }
30 |
31 | public Set getTasks() {
32 | return tasks;
33 | }
34 |
35 | public String getProvider() {
36 | return provider;
37 | }
38 |
39 | @Override
40 | public boolean equals(Object o) {
41 | if (this == o) return true;
42 | if (!(o instanceof PlatformConfig)) return false;
43 | PlatformConfig that = (PlatformConfig) o;
44 | return Objects.equals(id, that.id) &&
45 | Utils.areEqual(tasks, that.tasks) &&
46 | Objects.equals(provider, that.provider);
47 | }
48 |
49 | @Override
50 | public int hashCode() {
51 | return Objects.hash(id, tasks, provider);
52 | }
53 |
54 | @Override
55 | public String toString() {
56 | return "PlatformConfig{" +
57 | "id='" + id + '\'' +
58 | ", tasks=" + tasks +
59 | ", provider='" + provider + '\'' +
60 | '}';
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcrequestparams/ListTags.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcrequestparams;
2 |
3 | import hudson.plugins.scm.koji.Constants;
4 |
5 | import java.util.HashMap;
6 | import java.util.Map;
7 | import java.util.Objects;
8 |
9 | import static org.fakekoji.xmlrpc.server.xmlrpcrequestparams.XmlRpcRequestUtils.starStarLabel;
10 | import static org.fakekoji.xmlrpc.server.xmlrpcrequestparams.XmlRpcRequestUtils.toMap;
11 |
12 | public class ListTags implements XmlRpcRequestParams {
13 |
14 | private final Integer buildId;
15 |
16 | public ListTags(Integer buildId) {
17 | this.buildId = buildId;
18 | }
19 |
20 | @Override
21 | public Object[] toXmlRpcParams() {
22 | final Map map = new HashMap<>();
23 | map.put(Constants.build, buildId);
24 | map.put(starStarLabel, Boolean.TRUE);
25 | return new Object[]{map};
26 | }
27 |
28 | @Override
29 | public String getMethodName() {
30 | return Constants.listTags;
31 | }
32 |
33 | public Integer getBuildId() {
34 | return buildId;
35 | }
36 |
37 | public static ListTags create(Object object) {
38 | final Map map = toMap(object);
39 | return new ListTags((Integer) map.get(Constants.build));
40 | }
41 |
42 | @Override
43 | public boolean equals(Object o) {
44 | if (this == o) return true;
45 | if (o == null || getClass() != o.getClass()) return false;
46 | ListTags listTags = (ListTags) o;
47 | return Objects.equals(buildId, listTags.buildId) &&
48 | Objects.equals(getMethodName(), listTags.getMethodName());
49 | }
50 |
51 | @Override
52 | public int hashCode() {
53 | return Objects.hash(getMethodName(), buildId);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/java/hudson/plugins/scm/koji/KojiScmRe.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2016 user.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.plugins.scm.koji;
25 |
26 | import hudson.Extension;
27 | import hudson.model.RootAction;
28 |
29 | @Extension
30 | //accessible via http://...:1234/kojiScmRe/
31 | public class KojiScmRe implements RootAction {
32 |
33 | @Override
34 | public String getIconFileName() {
35 | return "clipboard.png";
36 | }
37 |
38 | @Override
39 | public String getDisplayName() {
40 | return "koji-scm plugin re-run api gate";
41 | }
42 |
43 | @Override
44 | public String getUrlName() {
45 | return "kojiScmRe";
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/webapp/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | OTool
28 |
29 |
30 | You need to enable JavaScript to run this app.
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/webapp/src/components/TreeNode.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | interface TitleProps {
4 | children: React.ReactNode;
5 | }
6 |
7 | interface NodeInfoProps {
8 | children: React.ReactNode;
9 | }
10 |
11 | interface OptionsProps {
12 | children: React.ReactNode;
13 | }
14 |
15 | interface ChildNodesProps {
16 | children: React.ReactNode;
17 | }
18 |
19 | const Title = (props: TitleProps): JSX.Element => (
20 |
21 | {props.children}
22 |
23 | );
24 |
25 | const NodeInfo = (props: NodeInfoProps): JSX.Element => (
26 |
27 | {props.children}
28 |
29 | );
30 |
31 | const Options = (props: OptionsProps): JSX.Element => (
32 |
33 | {props.children}
34 |
35 | );
36 |
37 | const ChildNodes = (props: ChildNodesProps): JSX.Element => (
38 |
39 | {props.children}
40 |
41 | );
42 |
43 | interface Props {
44 | children: [
45 | React.ReactElement,
46 | React.ReactElement,
47 | React.ReactElement,
48 | React.ReactElement
49 | ];
50 | }
51 |
52 | class TreeNode extends React.PureComponent {
53 |
54 | static Title: typeof Title = Title;
55 | static NodeInfo: typeof NodeInfo = NodeInfo;
56 | static Options: typeof Options = Options;
57 | static ChildNodes: typeof ChildNodes = ChildNodes;
58 |
59 | render() {
60 | const [title, nodeInfo, options, childNodes] = this.props.children;
61 | return (
62 |
63 | {title}
64 | {nodeInfo}
65 | {options}
66 | {childNodes}
67 |
68 | );
69 | }
70 | }
71 |
72 | export default TreeNode;
73 |
--------------------------------------------------------------------------------
/.github/workflows/maven.yml:
--------------------------------------------------------------------------------
1 | name: Java CI with Maven
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - name: Download repo
15 | uses: actions/checkout@v2
16 |
17 | - name: Set up JDK 17
18 | uses: actions/setup-java@v1
19 | with:
20 | java-version: 17
21 |
22 | - name: Cache Maven repository
23 | uses: actions/cache@v4
24 | with:
25 | path: ~/.m2/repository
26 | key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
27 |
28 | - name: Build with Maven
29 | run: |
30 | export MAVEN_OPTS="-Xmx4G"
31 | mvn install -DskipTests
32 |
33 | - name: test koji-scm-lib
34 | run: |
35 | export MAVEN_OPTS="-Xmx4G"
36 | cd koji-scm-lib
37 | mvn test
38 |
39 | - name: test fake-koji
40 | run: |
41 | export MAVEN_OPTS="-Xmx4G"
42 | cd fake-koji
43 | mvn test -Dheadless=true #the webapp takes long and was created in original full build and we do not clean
44 |
45 | - name: test jenkins-scm-koji-plugin
46 | run: |
47 | export MAVEN_OPTS="-Xmx4G"
48 | cd jenkins-scm-koji-plugin
49 | mvn test || echo "This fails now because of duplicate netty on class-path. It seems plugin works fine, but it is worthy to check those test resulsts manually"
50 |
51 | - name: Store artifacts
52 | run: |
53 | mkdir archives
54 | cp fake-koji/target/fake-koji-jar-with-dependencies.jar archives/
55 | cp jenkins-scm-koji-plugin/target/jenkins-scm-koji-plugin.hpi archives/
56 | shell: bash
57 |
58 | - name: Upload artifacts
59 | uses: actions/upload-artifact@v4
60 | with:
61 | name: Archives
62 | path: archives
63 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/manager/JDKVersionManager.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.manager;
2 |
3 | import org.fakekoji.jobmanager.ManagementException;
4 | import org.fakekoji.jobmanager.Manager;
5 | import org.fakekoji.model.JDKVersion;
6 | import org.fakekoji.storage.Storage;
7 | import org.fakekoji.storage.StorageException;
8 |
9 | import java.util.List;
10 |
11 | public class JDKVersionManager implements Manager {
12 |
13 | private final Storage storage;
14 |
15 | public JDKVersionManager(final Storage storage) {
16 | this.storage = storage;
17 | }
18 |
19 | @Override
20 | public JDKVersion create(JDKVersion jdkVersion) throws StorageException, ManagementException {
21 | if (storage.contains(jdkVersion.getId())) {
22 | throw new ManagementException("JDK version with id " + jdkVersion.getId() + " already exists");
23 | }
24 | storage.store(jdkVersion.getId(), jdkVersion);
25 | return null;
26 | }
27 |
28 | @Override
29 | public JDKVersion read(String id) throws StorageException, ManagementException {
30 | if (!storage.contains(id)) {
31 | throw new ManagementException("No JDK version with id: " + id);
32 | }
33 | return storage.load(id, JDKVersion.class);
34 | }
35 |
36 | @Override
37 | public List readAll() throws StorageException {
38 | return storage.loadAll(JDKVersion.class);
39 | }
40 |
41 | @Override
42 | public JDKVersion update(String id, JDKVersion product) throws StorageException, ManagementException {
43 | return null;
44 | }
45 |
46 | @Override
47 | public JDKVersion delete(String id) throws StorageException, ManagementException {
48 | return null;
49 | }
50 |
51 | @Override
52 | public boolean contains(String id) {
53 | return storage.contains(id);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/java/hudson/plugins/scm/koji/KojiXmlRpcApi.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.scm.koji;
2 |
3 | import hudson.DescriptorExtensionList;
4 | import hudson.ExtensionPoint;
5 | import hudson.model.Describable;
6 | import hudson.model.Descriptor;
7 | import jenkins.model.Jenkins;
8 | import org.kohsuke.stapler.export.Exported;
9 |
10 | import javax.annotation.Nonnull;
11 | import java.io.Serializable;
12 |
13 | public abstract class KojiXmlRpcApi implements Describable, ExtensionPoint, Serializable {
14 |
15 | private static final long serialVersionUID = -1650617726812887577L;
16 |
17 | private final KojiXmlRpcApiType xmlRpcApiType;
18 |
19 | public KojiXmlRpcApi(final KojiXmlRpcApiType xmlRpcApiType) {
20 | this.xmlRpcApiType = xmlRpcApiType;
21 | }
22 |
23 | @Exported
24 | public KojiXmlRpcApiType getXmlRpcApiType() {
25 | return xmlRpcApiType;
26 | }
27 |
28 | @SuppressWarnings("unchecked")
29 | @Override
30 | public Descriptor getDescriptor() {
31 | return Jenkins.getActiveInstance().getDescriptorOrDie(getClass());
32 | }
33 |
34 | public static class KojiXmlRpcApiDescriptor extends Descriptor {
35 |
36 | private final String xmlRpcApiName;
37 |
38 | public KojiXmlRpcApiDescriptor(
39 | final Class extends KojiXmlRpcApi> clazz,
40 | final String xmlRpcApiName
41 | ) {
42 | super(clazz);
43 | this.xmlRpcApiName = xmlRpcApiName;
44 | }
45 |
46 | @Nonnull
47 | @Override
48 | public String getDisplayName() {
49 | return xmlRpcApiName;
50 | }
51 |
52 | public DescriptorExtensionList getKojiXmlRpxApiDescriptors() {
53 | return Jenkins.getActiveInstance().getDescriptorList(KojiXmlRpcApi.class);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/webapp/src/components/formComponents/MultiSelect.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { FormControl, FormLabel, FormGroup, FormControlLabel, Checkbox } from "@material-ui/core"
3 | import { useObserver } from "mobx-react"
4 |
5 | type MultiSelectPropsRequired = {
6 | options: string[]
7 | }
8 |
9 | type MultiSelectPropsOptional = {
10 | label?: string
11 | onChange: (values: string[]) => void
12 | values: string[]
13 | }
14 |
15 | type MultiSelectProps = MultiSelectPropsRequired & MultiSelectPropsOptional
16 |
17 | const MultiSelect: React.FC = ({ label, onChange, options, values, }) => {
18 |
19 | const handleChange = (id: string) => {
20 | const index = values.indexOf(id)
21 | if (index < 0) {
22 | values.splice(0, 0, id)
23 | } else {
24 | values.splice(index, 1)
25 | }
26 | onChange(values)
27 | }
28 |
29 | return useObserver(() => {
30 | const multiSelect = (
31 |
32 | {
33 | options.map((option, index) =>
34 | = 0}
39 | onChange={() => {
40 | handleChange(option)
41 | }}
42 | value={index} />
43 | }
44 | label={option} />
45 | )
46 | }
47 |
48 | )
49 |
50 | return (
51 |
52 | {label || ""}
53 | {multiSelect}
54 |
55 | )
56 | })
57 | }
58 |
59 | export default MultiSelect
60 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/manager/BuildProviderManager.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.manager;
2 |
3 | import org.fakekoji.jobmanager.ManagementException;
4 | import org.fakekoji.jobmanager.Manager;
5 | import org.fakekoji.model.BuildProvider;
6 | import org.fakekoji.storage.Storage;
7 | import org.fakekoji.storage.StorageException;
8 |
9 | import java.util.List;
10 |
11 | public class BuildProviderManager implements Manager {
12 |
13 | private final Storage storage;
14 |
15 | public BuildProviderManager(final Storage storage) {
16 | this.storage = storage;
17 | }
18 |
19 | @Override
20 | public BuildProvider create(BuildProvider buildProvider) throws StorageException, ManagementException {
21 | if (storage.contains(buildProvider.getId())) {
22 | throw new ManagementException("Build provider with id " + buildProvider.getId() + " already exists");
23 | }
24 | storage.store(buildProvider.getId(), buildProvider);
25 | return null;
26 | }
27 |
28 | @Override
29 | public BuildProvider read(String id) throws StorageException, ManagementException {
30 | if (!storage.contains(id)) {
31 | throw new ManagementException("No build provider with id: " + id);
32 | }
33 | return storage.load(id, BuildProvider.class);
34 | }
35 |
36 | @Override
37 | public List readAll() throws StorageException {
38 | return storage.loadAll(BuildProvider.class);
39 | }
40 |
41 | @Override
42 | public BuildProvider update(String id, BuildProvider platform) throws StorageException, ManagementException {
43 | return null;
44 | }
45 |
46 | @Override
47 | public BuildProvider delete(String id) throws StorageException, ManagementException {
48 | return null;
49 | }
50 |
51 | @Override
52 | public boolean contains(String id) {
53 | return storage.contains(id);
54 | }
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/webapp/src/components/formComponents/FileRequirementsForm.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { FormControl, FormLabel, FormGroup } from "@material-ui/core"
3 | import { useObserver } from "mobx-react"
4 |
5 | import Checkbox from "./Checkbox"
6 | import Select from "./Select"
7 |
8 | import { FileRequirements, BinaryRequirement } from "../../stores/model"
9 |
10 | interface Props {
11 | fileRequirements: FileRequirements
12 | }
13 |
14 | const FileRequirementsForm: React.FunctionComponent = (props) => {
15 |
16 | return useObserver(() => {
17 | const { fileRequirements } = props
18 |
19 | const onBinaryChange = (value: string) => {
20 | fileRequirements.binary = value as BinaryRequirement
21 | }
22 |
23 | const onSourcesChange = (value: boolean) => {
24 | fileRequirements.source = value
25 | }
26 |
27 | const onNoarchChange = (value: boolean) => {
28 | fileRequirements.noarch = value
29 | }
30 |
31 | return (
32 |
33 |
34 | file requirements
35 |
36 |
37 |
41 |
45 |
50 |
51 |
52 | )
53 | })
54 | }
55 |
56 | export default FileRequirementsForm
57 |
--------------------------------------------------------------------------------
/webapp/src/components/formComponents/AddComponent.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 |
3 | import { Tooltip, IconButton, Dialog, Button, DialogContent, DialogActions } from "@material-ui/core"
4 | import { Add, Check } from "@material-ui/icons"
5 |
6 | import { Item } from "../../stores/model"
7 |
8 | interface AddItem extends Item {
9 | marked?: boolean
10 | }
11 |
12 | interface Props {
13 | items: AddItem[]
14 | label: string
15 | onAdd: (id: string) => void
16 | }
17 |
18 | const AddComponent: React.FC = ({ items, label, onAdd }) => {
19 |
20 | const [open, setOpen] = React.useState(false)
21 |
22 | const closeDialog = () => {
23 | setOpen(false)
24 | }
25 |
26 | const dialog = (
27 |
33 |
34 | {
35 | items.map(({id, marked}) => (
36 | }
38 | key={id}
39 | onClick={() => {
40 | onAdd(id)
41 | closeDialog()
42 | }}>
43 | {id}
44 |
45 | ))
46 | }
47 |
48 |
49 | cancel
50 |
51 |
52 | )
53 |
54 | return (
55 |
56 |
57 | { setOpen(true) }}>
58 |
59 |
60 |
61 | {dialog}
62 |
63 | )
64 | }
65 |
66 | export default AddComponent
67 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/hudson/plugins/scm/koji/client/GlobPredicate.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.scm.koji.client;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collections;
5 | import java.util.List;
6 | import java.util.function.Predicate;
7 | import java.util.regex.Pattern;
8 |
9 | public class GlobPredicate implements Predicate, java.io.Serializable {
10 |
11 | private final List globPatterns;
12 | private final transient TaskListenerLogTransporter log;
13 | private static final long serialVersionUID = -402287815488043482L;
14 |
15 | public GlobPredicate(String globExpr, TaskListenerLogTransporter logger) {
16 | if (globExpr == null) {
17 | globExpr = "";
18 | }
19 |
20 | log = logger;
21 |
22 | String[] origs = globExpr.split("\\s+");
23 | List tofinal = new ArrayList<>(origs.length);
24 | for (int i = 0; i < origs.length; i++) {
25 | String orig = origs[i];
26 | if (!orig.trim().isEmpty()) {
27 | tofinal.add(Pattern.compile(orig));
28 | }
29 | }
30 | this.globPatterns = Collections.unmodifiableList(tofinal);
31 | }
32 |
33 | @Override
34 | public boolean test(CharSequence input) {
35 | if (globPatterns.isEmpty()) {
36 | logMessage("[KojiSCM] matched: " + input + " because of globPattern is empty");
37 | return true;
38 | }
39 | for (Pattern globPattern : globPatterns) {
40 | if (globPattern.matcher(input).matches()) {
41 | logMessage("[KojiSCM] matched: " + input + " because of globPattern: " + globPattern);
42 | return true;
43 | }
44 | }
45 | logMessage("[KojiSCM] not matched: " + input + " because this globPattern didn't match anything.");
46 | return false;
47 | }
48 |
49 | private void logMessage(String message) {
50 | if(log != null) {
51 | log.println(message);
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcrequestparams/ListBuilds.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcrequestparams;
2 |
3 | import hudson.plugins.scm.koji.Constants;
4 |
5 | import java.util.HashMap;
6 | import java.util.Map;
7 | import java.util.Objects;
8 |
9 | import static org.fakekoji.xmlrpc.server.xmlrpcrequestparams.XmlRpcRequestUtils.starStarLabel;
10 | import static org.fakekoji.xmlrpc.server.xmlrpcrequestparams.XmlRpcRequestUtils.toMap;
11 |
12 | public class ListBuilds implements XmlRpcRequestParams {
13 |
14 | // always is 1, that means we want successfully completed builds
15 | private static final String stateLabel = "state";
16 |
17 | private final Integer packageId;
18 |
19 | public ListBuilds(Integer packageId) {
20 | this.packageId = packageId;
21 | }
22 |
23 | @Override
24 | public Object[] toXmlRpcParams() {
25 | final Map map = new HashMap<>();
26 | map.put(Constants.packageID, packageId);
27 | map.put(starStarLabel, Boolean.TRUE);
28 | map.put(stateLabel, 1);
29 | return new Object[]{map};
30 | }
31 |
32 | @Override
33 | public String getMethodName() {
34 | return Constants.listBuilds;
35 | }
36 |
37 | public Integer getPackageId() {
38 | return packageId;
39 | }
40 |
41 | public static ListBuilds create(Object object) {
42 | final Map map = toMap(object);
43 | return new ListBuilds((Integer) map.get(Constants.packageID));
44 | }
45 |
46 | @Override
47 | public boolean equals(Object o) {
48 | if (this == o) return true;
49 | if (o == null || getClass() != o.getClass()) return false;
50 | ListBuilds that = (ListBuilds) o;
51 | return Objects.equals(packageId, that.packageId) &&
52 | Objects.equals(getMethodName(), that.getMethodName());
53 | }
54 |
55 | @Override
56 | public int hashCode() {
57 | return Objects.hash(getMethodName(), packageId);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/webapp/src/components/formComponents/LimitationForm.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { observer } from "mobx-react";
3 |
4 | import { Limitation, Item, LimitFlag } from "../../stores/model";
5 | import Select from "./Select";
6 | import MultiSelect from "./MultiSelect";
7 | import { FormControl, FormLabel, FormGroup } from "@material-ui/core";
8 |
9 | interface LimitationProps {
10 | label: string;
11 | limitation: Limitation;
12 | items: Item[];
13 | }
14 |
15 | class LimitationForm extends React.PureComponent {
16 |
17 | onDelete = (index: number) => {
18 | this.props.limitation.list.splice(index, 1);
19 | }
20 |
21 | onAdd = (id: string) => {
22 | this.props.limitation.list.push(id);
23 | }
24 |
25 | onFlagChange = (value: string) => {
26 | this.props.limitation.flag = value as LimitFlag
27 | }
28 |
29 | onListChange = (values: string[]) => {
30 | this.props.limitation.list = values
31 | }
32 |
33 | render() {
34 | const { label, limitation, items } = this.props;
35 | const flag = limitation && (limitation.flag || "NONE")
36 | return (
37 |
38 |
39 | {label}
40 |
41 |
42 |
47 | {
48 | (flag !== "NONE") &&
49 | item.id)}
52 | values={limitation.list} />
53 | }
54 |
55 |
56 | );
57 | }
58 | }
59 |
60 | export default observer(LimitationForm);
61 |
--------------------------------------------------------------------------------
/webapp/src/utils/createJobName.ts:
--------------------------------------------------------------------------------
1 | import {
2 | BuildConfigs,
3 | TaskVariant,
4 | PlatformConfig,
5 | TaskConfig,
6 | VariantsConfig,
7 | } from "../stores/model"
8 |
9 | type JenkinsJob = {
10 | name: string
11 | url: string
12 | }
13 |
14 | export const getJobNameGenerator = (
15 | variants: { [id: string]: TaskVariant },
16 | url: string | undefined,
17 | ): ((
18 | projectId: string,
19 | jdkId: string,
20 | platformConfig: PlatformConfig,
21 | taskConfig: TaskConfig | undefined,
22 | variantsConfig: VariantsConfig,
23 | buildConfigs: BuildConfigs | undefined,
24 | ) => JenkinsJob | null) => {
25 | if (!url) {
26 | return () => null
27 | }
28 | const variantsMap = Object.keys(variants).reduce((map, key) => {
29 | const variant = variants[key]
30 | map.set(key, variant)
31 | return map
32 | }, new Map())
33 | const sortVariants = (a: string, b: string): number => {
34 | const variantA = variantsMap.get(a)
35 | const variantB = variantsMap.get(b)
36 | if (!variantA || !variantB) {
37 | return 0
38 | }
39 | return variantA.order - variantB.order
40 | }
41 | const variantsToString = (config: VariantsConfig): string => {
42 | return Object.keys(config.map)
43 | .sort(sortVariants)
44 | .map(key => config.map[key])
45 | .join(".")
46 | }
47 | return (projectId, jdkId, platform, task, variants, buildConfigs) => {
48 | if (!task) {
49 | return null
50 | }
51 | const buildPart = !!buildConfigs
52 | ? `-${buildConfigs.platform.id}-${variantsToString(buildConfigs.taskVariants)}-`
53 | : "-"
54 | const name = `${task.id}-${jdkId}-${projectId}${buildPart}${platform.id}.${platform.provider}-${variantsToString(variants)}`
55 | const jobUrl = `${url}job/${name}`
56 | return {
57 | name,
58 | url: jobUrl,
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/fake-koji/src/test/java/org/fakekoji/jobmanager/project/JDKProjectParserTest.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.project;
2 |
3 | import org.fakekoji.DataGenerator;
4 | import org.fakekoji.core.AccessibleSettings;
5 | import org.fakekoji.jobmanager.ManagementException;
6 | import org.fakekoji.jobmanager.model.JDKProject;
7 | import org.fakekoji.jobmanager.model.JDKTestProject;
8 | import org.fakekoji.jobmanager.model.Job;
9 | import org.fakekoji.storage.StorageException;
10 | import org.junit.Assert;
11 | import org.junit.Before;
12 | import org.junit.Rule;
13 | import org.junit.Test;
14 | import org.junit.rules.TemporaryFolder;
15 |
16 | import java.io.IOException;
17 | import java.util.Set;
18 |
19 |
20 | public class JDKProjectParserTest {
21 |
22 | @Rule
23 | public final TemporaryFolder temporaryFolder = new TemporaryFolder();
24 |
25 | private AccessibleSettings settings;
26 |
27 | @Before
28 | public void setup() throws IOException {
29 | settings = DataGenerator.getSettings(DataGenerator.initFolders(temporaryFolder));
30 | }
31 |
32 | @Test
33 | public void parseJDKTestProject() throws StorageException, ManagementException {
34 | final JDKTestProject jdkTestProject = DataGenerator.getJDKTestProject();
35 | final JDKProjectParser parser = settings.getJdkProjectParser();
36 | final Set actualJobs = parser.parse(jdkTestProject);
37 | Assert.assertEquals(
38 | "ParsedProject should be equal",
39 | DataGenerator.getJDKTestProjectJobs(),
40 | actualJobs
41 | );
42 | }
43 |
44 | @Test
45 | public void parseJDKProject() throws StorageException, ManagementException {
46 | final JDKProject jdkProject = DataGenerator.getJDKProject();
47 | final JDKProjectParser parser = settings.getJdkProjectParser();
48 | final Set actualJobs = parser.parse(jdkProject);
49 | Assert.assertEquals(
50 | "ParsedProject should be equal",
51 | DataGenerator.getJDKProjectJobs(),
52 | actualJobs
53 | );
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/pull-job.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 |
6 |
7 | %{MASTER_LABEL}
8 | false
9 | false
10 | false
11 | false
12 | %{TRIGGER}
13 | false
14 |
15 |
16 | %{PULL_SCRIPT}
17 |
18 |
19 |
20 |
21 | **
22 | false
23 | false
24 | false
25 | true
26 | true
27 |
28 |
29 |
30 | ### CHANGES DETECTED ###
31 |
32 | false
33 | true
34 | false
35 | true
36 |
37 |
38 |
39 | nothing_ever
40 | ^future VR:
41 | false
42 | false
43 | false
44 | true
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/manager/TaskManager.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.manager;
2 |
3 | import org.fakekoji.jobmanager.ManagementException;
4 | import org.fakekoji.jobmanager.Manager;
5 | import org.fakekoji.model.Task;
6 | import org.fakekoji.storage.Storage;
7 | import org.fakekoji.storage.StorageException;
8 |
9 | import java.util.Collections;
10 | import java.util.List;
11 |
12 | public class TaskManager implements Manager {
13 |
14 | private final Storage taskStorage;
15 |
16 | public TaskManager(final Storage taskStorage) {
17 | this.taskStorage = taskStorage;
18 | }
19 |
20 | @Override
21 | public Task create(Task task) throws StorageException, ManagementException {
22 | if (taskStorage.contains(task.getId())) {
23 | throw new ManagementException("Task with id " + task.getId() + " already exists");
24 | }
25 | taskStorage.store(task.getId(), task);
26 | return task;
27 | }
28 |
29 | @Override
30 | public Task read(String id) throws StorageException, ManagementException {
31 | if (!taskStorage.contains(id)) {
32 | throw new ManagementException("No task with id: " + id);
33 | }
34 | return taskStorage.load(id, Task.class);
35 | }
36 |
37 | @Override
38 | public List readAll() throws StorageException {
39 | List l = taskStorage.loadAll(Task.class);
40 | Collections.sort(l);
41 | return l;
42 | }
43 |
44 | @Override
45 | public Task update(String id, Task task) throws StorageException, ManagementException {
46 | if (!taskStorage.contains(id)) {
47 | throw new ManagementException("No task with id: " + id);
48 | }
49 | taskStorage.store(id, task);
50 | return task;
51 | }
52 |
53 | @Override
54 | public Task delete(String id) throws StorageException, ManagementException {
55 | throw new ManagementException("Not supported");
56 | }
57 |
58 | @Override
59 | public boolean contains(String id) {
60 | return taskStorage.contains(id);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/webapp/src/components/formComponents/PlatformProviderForm.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { useObserver } from "mobx-react"
3 | import { Grid } from "@material-ui/core"
4 |
5 | import { PlatformProvider } from "../../stores/model"
6 | import TextInput from "./TextInput"
7 | import { PlatformProviderValidation } from "../../utils/validators"
8 |
9 | interface PlatformProviderFormProps {
10 | platformProvider: PlatformProvider
11 | validation?: PlatformProviderValidation
12 | }
13 |
14 | const PlatformProviderForm: React.FC = props =>
15 | useObserver(() => {
16 | const { platformProvider, validation } = props
17 |
18 | const onIdChange = (value: string) => {
19 | platformProvider.id = value
20 | }
21 |
22 | const onHwNodesChange = (value: string) => {
23 | platformProvider.hwNodes = value.split(" ")
24 | }
25 |
26 | const onVmNodesChange = (value: string) => {
27 | platformProvider.vmNodes = value.split(" ")
28 | }
29 |
30 | const { hwNodes, id, vmNodes } =
31 | validation || ({} as PlatformProviderValidation)
32 |
33 | return (
34 |
35 |
36 |
42 |
48 |
54 |
55 |
56 | )
57 | })
58 |
59 | export default PlatformProviderForm
60 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcrequestparams/ListArtefacts.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcrequestparams;
2 |
3 | import hudson.plugins.scm.koji.Constants;
4 |
5 | import java.util.ArrayList;
6 | import java.util.HashMap;
7 | import java.util.List;
8 | import java.util.Map;
9 | import java.util.Objects;
10 |
11 | import static org.fakekoji.xmlrpc.server.xmlrpcrequestparams.XmlRpcRequestUtils.starStarLabel;
12 |
13 | public abstract class ListArtefacts implements XmlRpcRequestParams {
14 |
15 | private final Integer buildId;
16 | private final List archs;
17 |
18 | ListArtefacts(Integer buildId, List archs) {
19 | this.buildId = buildId;
20 | this.archs = archs;
21 | }
22 |
23 | static List getArchs(Object object) {
24 | if (object == null) {
25 | return null;
26 | }
27 | final List archList = new ArrayList<>();
28 | final Object[] archs = (Object[]) object;
29 | for (final Object arch : archs)
30 | archList.add((String) arch);
31 | return archList;
32 | }
33 |
34 | @Override
35 | public Object[] toXmlRpcParams() {
36 | final Map map = new HashMap<>();
37 | map.put(Constants.buildID, buildId);
38 | map.put(starStarLabel, Boolean.TRUE);
39 | if (archs != null && !archs.isEmpty()) {
40 | map.put(Constants.arches, archs.toArray());
41 | }
42 | return new Object[]{map};
43 | }
44 |
45 | public Integer getBuildId() {
46 | return buildId;
47 | }
48 |
49 | public List getArchs() {
50 | return archs;
51 | }
52 |
53 | @Override
54 | public boolean equals(Object o) {
55 | if (this == o) return true;
56 | if (o == null || getClass() != o.getClass()) return false;
57 | ListArtefacts that = (ListArtefacts) o;
58 | return Objects.equals(buildId, that.buildId) &&
59 | Objects.equals(archs, that.archs) &&
60 | Objects.equals(getMethodName(), that.getMethodName());
61 | }
62 |
63 | @Override
64 | public int hashCode() {
65 | return Objects.hash(getMethodName(), buildId, archs);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/KojiChangeLogSet/index.jelly:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | No changes
6 |
7 |
8 |
9 |
10 |
11 | ${changeset.field}:
12 |
13 |
14 |
15 |
16 |
17 |
18 | ${hyperlink.displayedString}
19 |
20 |
21 |
22 | (${hyperlink.showSum()})
23 |
24 |
25 |
26 |
27 | ${hyperlink.displayedString}
28 |
29 |
30 |
31 |
32 |
33 | You must log in to use otool actions
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/KojiChangeLogSet/digest.jelly:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | No changes
6 |
7 |
8 |
9 |
10 |
11 | ${changeset.field}:
12 |
13 |
14 |
15 |
16 |
17 |
18 | ${hyperlink.displayedString}
19 |
20 |
21 |
22 | (${hyperlink.showSum()})
23 |
24 |
25 |
26 |
27 | ${hyperlink.displayedString}
28 |
29 |
30 |
31 |
32 |
33 | You must log in to use otool actions
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/manager/PlatformManager.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.manager;
2 |
3 | import org.fakekoji.jobmanager.ManagementException;
4 | import org.fakekoji.jobmanager.ManagementUtils;
5 | import org.fakekoji.jobmanager.Manager;
6 | import org.fakekoji.model.Platform;
7 | import org.fakekoji.storage.Storage;
8 | import org.fakekoji.storage.StorageException;
9 |
10 | import java.util.Collections;
11 | import java.util.List;
12 |
13 | public class PlatformManager implements Manager {
14 |
15 | private final Storage storage;
16 |
17 | public PlatformManager(final Storage storage) {
18 | this.storage = storage;
19 | }
20 |
21 | @Override
22 | public Platform create(Platform platform) throws StorageException, ManagementException {
23 | // as frontend doesn't generate platform's ID, this will create platform with the correct ID based on its
24 | // os, version, architecture and provider
25 | final Platform newPlatform = Platform.create(platform);
26 | ManagementUtils.checkID(newPlatform.getId(), storage, false);
27 | storage.store(newPlatform.getId(), newPlatform);
28 | return newPlatform;
29 | }
30 |
31 | @Override
32 | public Platform read(String id) throws StorageException, ManagementException {
33 | ManagementUtils.checkID(id, storage);
34 | return storage.load(id, Platform.class);
35 | }
36 |
37 | @Override
38 | public List readAll() throws StorageException {
39 | List l = storage.loadAll(Platform.class);
40 | Collections.sort(l);
41 | return l;
42 | }
43 |
44 | @Override
45 | public Platform update(String id, Platform platform) throws StorageException, ManagementException {
46 | ManagementUtils.checkID(id, storage);
47 | storage.store(id, platform);
48 | return platform;
49 | }
50 |
51 | @Override
52 | public Platform delete(String id) throws StorageException, ManagementException {
53 | ManagementUtils.checkID(id, storage);
54 | throw new ManagementException("Not supported");
55 | }
56 |
57 | @Override
58 | public boolean contains(String id) {
59 | return storage.contains(id);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.jenkins-ci.plugins
7 | plugin
8 | 4.87
9 |
10 |
11 | fake-koji
12 | koji-scm
13 | 2.2-SNAPSHOT
14 | pom
15 |
16 | Koji SCM
17 |
18 |
19 | MIT
20 | http://www.opensource.org/licenses/mit-license.php
21 |
22 |
23 |
24 |
25 | jenkins-scm-koji-plugin
26 | fake-koji
27 | koji-scm-lib
28 |
29 |
30 |
31 | 2.461
32 | ${jenkins.baseline}
33 | 3.1.3
34 |
35 |
36 |
37 |
38 |
39 | org.apache.xmlrpc
40 | xmlrpc-server
41 | ${xmlrpc.version}
42 |
43 |
44 | org.apache.xmlrpc
45 | xmlrpc-client
46 | ${xmlrpc.version}
47 |
48 |
49 |
50 |
51 |
52 |
53 | repo.jenkins-ci.org
54 | https://repo.jenkins-ci.org/public/
55 |
56 |
57 |
58 |
59 | repo.jenkins-ci.org
60 | https://repo.jenkins-ci.org/public/
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/resources/hudson/plugins/scm/koji/KojiSCM/config.jelly:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
9 |
13 |
14 |
15 |
16 |
19 |
20 |
24 |
25 |
30 |
31 |
34 |
37 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/webapp/src/styles/Layout.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | }
4 |
5 | *, *:before, *:after {
6 | box-sizing: inherit;
7 | }
8 |
9 | .app-container {
10 | display: grid;
11 | grid-template-columns: 2fr 5fr;
12 | grid-template-areas:
13 | "header header"
14 | "list form"
15 | }
16 |
17 | .header-container {
18 | display: flex;
19 | flex-direction: row;
20 | grid-area: header;
21 | }
22 |
23 | .header-container .header-item {
24 | cursor: pointer;
25 | padding: 20px 25px;
26 | }
27 |
28 | .header-container .header-item:hover {
29 | background-color: rgba(1, 1, 1, 0.1);
30 | }
31 |
32 | .list-container {
33 | grid-area: list
34 | }
35 |
36 | .list-container .header {
37 | display: flex;
38 | font-size: 30px;
39 | justify-content: space-between;
40 | padding: 20px 30px;
41 | }
42 |
43 | .list-container .body {
44 | display: flex;
45 | flex-direction: column
46 | }
47 |
48 | .list-container .list-item {
49 | align-items: center;
50 | background-color: rgba(1, 1, 1, 0.1);
51 | cursor: pointer;
52 | display: flex;
53 | justify-content: space-between;
54 | padding: 20px 25px;
55 | }
56 |
57 | .list-container .list-item:hover {
58 | background-color: rgba(1, 1, 1, 0.0);
59 | }
60 |
61 | .form-container {
62 | grid-area: form
63 | }
64 |
65 | .tree-node-wrapper {
66 | border-radius: 3px;
67 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 3px 10px 0 rgba(0, 0, 0, 0.19);
68 | display: grid;
69 | grid-template-areas:
70 | "title options"
71 | "node-info node-info"
72 | "nodes nodes";
73 | margin: 5px 10px 10px 25px;
74 | }
75 |
76 | .tree-node-title {
77 | align-items: flex-start;
78 | display: flex;
79 | flex-direction: column;
80 | grid-area: title;
81 | justify-content: center;
82 | padding: 7px;
83 | }
84 |
85 | .tree-node-options {
86 | align-items: flex-start;
87 | display: flex;
88 | flex-direction: row;
89 | grid-area: options;
90 | justify-content: flex-end;
91 | padding: 7px;
92 | }
93 |
94 | .tree-node-info {
95 | border-top: 1px solid #ccc;
96 | display: flex;
97 | flex-direction: row;
98 | grid-area: node-info;
99 | margin-top: 5px;
100 | padding: 10px 0 10px 25px;
101 | }
102 |
103 | .tree-node-nodes {
104 | grid-area: nodes;
105 | }
106 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/model/BuildProvider.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.model;
2 |
3 | import java.util.Objects;
4 |
5 | public class BuildProvider {
6 |
7 | private final String id;
8 | private final String label;
9 | private final String topUrl;
10 | private final String downloadUrl;
11 | private final String packageInfoUrl;
12 |
13 | public BuildProvider() {
14 | id = null;
15 | label = null;
16 | topUrl = null;
17 | downloadUrl = null;
18 | packageInfoUrl = null;
19 | }
20 |
21 | public BuildProvider(
22 | String id,
23 | String label,
24 | String topUrl,
25 | String downloadUrl,
26 | final String packageInfoUrl
27 | ) {
28 | this.id = id;
29 | this.label = label;
30 | this.topUrl = topUrl;
31 | this.downloadUrl = downloadUrl;
32 | this.packageInfoUrl = packageInfoUrl;
33 | }
34 |
35 | public String getId() {
36 | return id;
37 | }
38 |
39 | public String getLabel() {
40 | return label;
41 | }
42 |
43 | public String getTopUrl() {
44 | return topUrl;
45 | }
46 |
47 | public String getDownloadUrl() {
48 | return downloadUrl;
49 | }
50 |
51 | public String getPackageInfoUrl() {
52 | return packageInfoUrl;
53 | }
54 |
55 | @Override
56 | public boolean equals(Object o) {
57 | if (this == o) return true;
58 | if (!(o instanceof BuildProvider)) return false;
59 | BuildProvider that = (BuildProvider) o;
60 | return Objects.equals(id, that.id) &&
61 | Objects.equals(label, that.label) &&
62 | Objects.equals(topUrl, that.topUrl) &&
63 | Objects.equals(downloadUrl, that.downloadUrl) &&
64 | Objects.equals(packageInfoUrl, that.packageInfoUrl);
65 | }
66 |
67 | @Override
68 | public int hashCode() {
69 | return Objects.hash(id, label, topUrl, downloadUrl, packageInfoUrl);
70 | }
71 |
72 | @Override
73 | public String toString() {
74 | return "BuildProvider{" +
75 | "id='" + id + '\'' +
76 | ", label='" + label + '\'' +
77 | ", topUrl='" + topUrl + '\'' +
78 | ", downloadUrl='" + downloadUrl + '\'' +
79 | ", packageInfoUrl='" + packageInfoUrl + '\'' +
80 | '}';
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/api/http/filehandling/FileDownloadService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2018 .
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package org.fakekoji.api.http.filehandling;
25 |
26 | import com.sun.net.httpserver.HttpServer;
27 | import java.io.File;
28 | import java.io.IOException;
29 | import java.net.InetSocketAddress;
30 |
31 | /**
32 | * This class implements http server used as koji download server ( packages are
33 | * downloaded from here by jenkins koji plugin ).
34 | *
35 | * Based on code, which was originally in JavaServer class.
36 | */
37 | public class FileDownloadService {
38 |
39 | private File dbFileRoot;
40 | private int port;
41 | private HttpServer hs;
42 |
43 | public FileDownloadService(File dbFileRoot, int port) {
44 | this.dbFileRoot = dbFileRoot;
45 | this.port = port;
46 | }
47 |
48 | public int getPort() {
49 | return port;
50 | }
51 |
52 | public void start() throws IOException {
53 | if (hs == null) {
54 | hs = HttpServer.create(new InetSocketAddress(port), 0);
55 | hs.createContext("/", new FileReturningHandler(dbFileRoot));
56 | }
57 | hs.start();
58 | }
59 |
60 | public void stop() {
61 | if (hs != null) {
62 | hs.stop(10);
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/webapp/src/components/formComponents/JDKVersionSelectForm.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { FormControl, FormLabel, FormGroup } from "@material-ui/core"
3 | import { useObserver } from "mobx-react"
4 |
5 | import Select from "./Select"
6 | import { Product } from "../../stores/model"
7 | import useStores from "../../hooks/useStores"
8 | import { ProductValidation } from "../../utils/validators"
9 |
10 | interface Props {
11 | product: Product
12 | validation?: ProductValidation
13 | }
14 |
15 | const ProductSelectForm: React.FC = props => {
16 | const { configStore } = useStores()
17 |
18 | return useObserver(() => {
19 | const { product, validation } = props
20 | const { jdkVersions, getJDKVersion } = configStore
21 | const jdkVersion = getJDKVersion(product.jdk)
22 |
23 | const {
24 | jdk,
25 | packageName
26 | } = validation || {} as ProductValidation
27 |
28 | const onJDKVersionChange = (value: string) => {
29 | product.jdk = value
30 | const jdkVersion = getJDKVersion(product.jdk)
31 | if (jdkVersion) {
32 | const packageNames = jdkVersion.packageNames
33 | product.packageName =
34 | packageNames.length > 0 ? packageNames[0] : ""
35 | }
36 | }
37 |
38 | const onPackageNameChange = (value: string) => {
39 | product.packageName = value
40 | }
41 |
42 | return (
43 |
44 | Product
45 |
46 | v.id)}
50 | validation={jdk}
51 | value={product.jdk}
52 | />
53 | {jdkVersion && (
54 |
61 | )}
62 |
63 |
64 | )
65 | })
66 | }
67 |
68 | export default ProductSelectForm
69 |
--------------------------------------------------------------------------------
/fake-koji/src/main/resources/jenkins-templates/update-vm-job.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | false
6 |
7 |
8 | %{NODE}
9 | false
10 | false
11 | false
12 | false
13 |
14 | false
15 |
16 |
17 | #!/bin/sh
18 | # set EXCLUDE_KERNEL=ture, if you wont to skip kernel update
19 | # set ALLOW_ALPHAREPO=false when you dont want to update from alpha-testing openjdkQA internal repo. Such update and testruns must be observed carefully
20 | # it is recommended to run normal update as separate step before update with ALLOW_ALPHAREPO
21 | # ALLOW_ALPHAREPO shold be run for el 8.y.z and 9.y.z only (keep it in mind
22 | export VM_J_ID=%{PLATFORM_NAME}
23 | sh %{SCRIPTS_ROOT}/jenkins/%{PROVIDER}/updateBox.sh $VM_J_ID \
24 | "sudo EXCLUDE_KERNEL=false ALLOW_ALPHAREPO=true bash /mnt/shared/TckScripts/jenkins/%{PROVIDER}/update/update-command.sh"
25 | #"sudo dnf -y install kernel-modules-extra && sudo EXCLUDE_KERNEL=false ALLOW_ALPHAREPO=false bash /mnt/shared/TckScripts/jenkins/vagrant/update/update-command.sh"
26 | #"sudo dnf -y --enablerepo=rhel-8-buildroot upgrade libstdc++-static giflib-devel && sudo EXCLUDE_KERNEL=true ALLOW_ALPHAREPO=false bash /mnt/shared/TckScripts/jenkins/vagrant/update/update-command.sh"
27 | #"echo just repack"
28 | #"sudo dnf -y remove *photos* gnome-soft* PackageKit flatpak gnome-contac* gnome-box* gnome-w* *abrt* *clock*"
29 | #"sudo yum -y install *lcms*"
30 | #"sudo yum -y downgrade \"nss*\""
31 | #"sudo yum -y downgrade \"nspr*\""
32 |
33 |
34 |
35 |
36 | %{POST_BUILD_TASK_PLUGIN}
37 |
38 |
39 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcresponse/RPMList.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcresponse;
2 |
3 | import hudson.plugins.scm.koji.Constants;
4 | import hudson.plugins.scm.koji.model.RPM;
5 |
6 | import java.util.ArrayList;
7 | import java.util.Collections;
8 | import java.util.HashMap;
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | import static org.fakekoji.xmlrpc.server.xmlrpcrequestparams.XmlRpcRequestUtils.toMaps;
13 |
14 | public class RPMList implements XmlRpcResponse> {
15 |
16 | private final List rpms;
17 |
18 | public RPMList(List rpms) {
19 | this.rpms = rpms;
20 | }
21 |
22 | @Override
23 | public Object toObject() {
24 | return parseRpms();
25 | }
26 |
27 | @Override
28 | public List getValue() {
29 | return rpms;
30 | }
31 |
32 | private static List parseRpmMaps(List> maps) {
33 | if (maps == null) {
34 | return Collections.emptyList();
35 | }
36 | final List rpms = new ArrayList<>(maps.size());
37 | for (Map map : maps) {
38 | rpms.add(parseRpmMap(map));
39 | }
40 | return rpms;
41 | }
42 |
43 | private static RPM parseRpmMap(Map map) {
44 | return new RPM(
45 | (String) map.get(Constants.name),
46 | (String) map.get(Constants.version),
47 | (String) map.get(Constants.release),
48 | (String) map.get(Constants.nvr),
49 | (String) map.get(Constants.arch),
50 | (String) map.get(Constants.filename)
51 | );
52 | }
53 |
54 | private List> parseRpms() {
55 | List> maps = new ArrayList<>();
56 | for (RPM rpm : rpms) {
57 | maps.add(parseRpm(rpm));
58 | }
59 | return maps;
60 | }
61 |
62 | private Map parseRpm(RPM rpm) {
63 | Map map = new HashMap<>();
64 | map.put(Constants.release, rpm.getRelease());
65 | map.put(Constants.version, rpm.getVersion());
66 | map.put(Constants.name, rpm.getName());
67 | map.put(Constants.filename, rpm.getFilename(""));
68 | map.put(Constants.nvr, rpm.getNvr());
69 | map.put(Constants.arch, rpm.getArch());
70 | return map;
71 | }
72 |
73 | public static RPMList create(Object object) {
74 | return new RPMList(parseRpmMaps(toMaps(object)));
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/fake-koji/src/test/java/org/fakekoji/jobmanager/project/ReverseJDKProjectParserTest.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.project;
2 |
3 | import org.fakekoji.DataGenerator;
4 | import org.fakekoji.core.AccessibleSettings;
5 | import org.fakekoji.functional.Result;
6 | import org.fakekoji.jobmanager.model.Project;
7 | import org.junit.Assert;
8 | import org.junit.Before;
9 | import org.junit.Rule;
10 | import org.junit.Test;
11 | import org.junit.rules.TemporaryFolder;
12 |
13 | import java.io.IOException;
14 | import java.util.Arrays;
15 | import java.util.HashSet;
16 | import java.util.Optional;
17 | import java.util.Set;
18 |
19 | public class ReverseJDKProjectParserTest {
20 |
21 | @Rule
22 | public final TemporaryFolder temporaryFolder = new TemporaryFolder();
23 |
24 | private AccessibleSettings settings;
25 |
26 |
27 | @Before
28 | public void setup() throws IOException {
29 | settings = DataGenerator.getSettings(DataGenerator.initFolders(temporaryFolder));
30 | }
31 |
32 | @Test
33 | public void parseJDKTestProjectJobs() {
34 | final ReverseJDKProjectParser parser = settings.getReverseJDKProjectParser();
35 | final Result result = parser.parseJobs(DataGenerator.getJDKTestProjectJobs());
36 | Assert.assertEquals(
37 | DataGenerator.getJDKTestProject(),
38 | result.getValue()
39 | );
40 | }
41 |
42 | @Test
43 | public void parseJDKProjectJobs() {
44 | final ReverseJDKProjectParser parser = settings.getReverseJDKProjectParser();
45 | final Result result = parser.parseJobs(DataGenerator.getJDKProjectJobs());
46 | Assert.assertEquals(
47 | DataGenerator.getJDKProject(),
48 | result.getValue()
49 | );
50 | }
51 |
52 | @Test
53 | public void findOrCreateString() {
54 | final String a = "aaa";
55 | final String b = "bbb";
56 | final String c = "ccc";
57 | final Set strings = new HashSet<>(Arrays.asList(a, b));
58 |
59 | final Optional opt = ReverseJDKProjectParser.findConfig(strings, s -> s.equals(a));
60 | Assert.assertTrue(opt.isPresent());
61 | Assert.assertEquals(opt.get(), a);
62 |
63 | final Optional optEmpty = ReverseJDKProjectParser.findConfig(strings, s -> s.equals(c));
64 | Assert.assertFalse(optEmpty.isPresent());
65 |
66 | final String string = ReverseJDKProjectParser.findOrCreateConfig(strings, s -> s.equals(c), () -> c);
67 | Assert.assertEquals(string, c);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/java/hudson/plugins/scm/koji/KojiEnvVarsAction.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2016 user.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.plugins.scm.koji;
25 |
26 | import hudson.EnvVars;
27 | import hudson.model.AbstractBuild;
28 | import hudson.model.EnvironmentContributingAction;
29 |
30 | import static hudson.plugins.scm.koji.Constants.BUILD_ENV_NVR;
31 | import static hudson.plugins.scm.koji.Constants.BUILD_ENV_RPMS_DIR;
32 | import static hudson.plugins.scm.koji.Constants.BUILD_ENV_RPM_FILES;
33 |
34 | public class KojiEnvVarsAction implements EnvironmentContributingAction {
35 |
36 | private final String nvr;
37 | private final String rpmsDir;
38 | private final String rpmFiles;
39 |
40 | public KojiEnvVarsAction(String nvr, String rpmsDir, String rpmFiles) {
41 | this.nvr = nvr;
42 | this.rpmsDir = rpmsDir;
43 | this.rpmFiles = rpmFiles;
44 | }
45 |
46 | @Override
47 | public void buildEnvVars(AbstractBuild, ?> build, EnvVars env) {
48 | env.put(BUILD_ENV_NVR, nvr);
49 | env.put(BUILD_ENV_RPMS_DIR, rpmsDir);
50 | env.put(BUILD_ENV_RPM_FILES, rpmFiles);
51 | }
52 |
53 | @Override
54 | public String getIconFileName() {
55 | return null;
56 | }
57 |
58 | @Override
59 | public String getDisplayName() {
60 | return null;
61 | }
62 |
63 | @Override
64 | public String getUrlName() {
65 | return null;
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/webapp/src/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/koji-scm-lib/src/main/java/org/fakekoji/xmlrpc/server/xmlrpcrequestparams/GetBuildList.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.xmlrpc.server.xmlrpcrequestparams;
2 |
3 | import java.util.Objects;
4 |
5 | import hudson.plugins.scm.koji.Constants;
6 |
7 | public class GetBuildList implements XmlRpcRequestParams {
8 |
9 | private final String projectName;
10 | private final String buildVariants;
11 | private final String platforms;
12 | private final boolean isBuilt;
13 |
14 | public GetBuildList(
15 | String projectName,
16 | String buildVariants,
17 | String platforms,
18 | boolean isBuilt
19 | ) {
20 | this.projectName = projectName;
21 | this.buildVariants = buildVariants;
22 | this.platforms = platforms;
23 | this.isBuilt = isBuilt;
24 | }
25 |
26 | @Override
27 | public String toString() {
28 | return projectName + "; " + buildVariants + "; " + isBuilt;
29 | }
30 |
31 | @Override
32 | public Object[] toXmlRpcParams() {
33 | return new Object[]{this};
34 | }
35 |
36 | @Override
37 | public String getMethodName() {
38 | return Constants.getBuildList;
39 | }
40 |
41 | public String getProjectName() {
42 | return projectName;
43 | }
44 |
45 | public String getBuildVariants() {
46 | return buildVariants;
47 | }
48 |
49 | public String getPlatforms() {
50 | return platforms;
51 | }
52 |
53 | /**
54 | * true = if the built is already finished
55 | * false = the built is about to be build
56 | *
57 | * @return
58 | */
59 | public boolean isBuilt() {
60 | return isBuilt;
61 | }
62 |
63 | public boolean isSupposedToGetBuild() {
64 | return !isBuilt;
65 | }
66 |
67 | public static GetBuildList create(Object object) {
68 | return (GetBuildList) object;
69 | }
70 |
71 | @Override
72 | public boolean equals(Object o) {
73 | if (this == o) return true;
74 | if (o == null || getClass() != o.getClass()) return false;
75 | GetBuildList that = (GetBuildList) o;
76 | return isBuilt == that.isBuilt &&
77 | Objects.equals(projectName, that.projectName) &&
78 | Objects.equals(buildVariants, that.buildVariants) &&
79 | Objects.equals(platforms, that.platforms) &&
80 | Objects.equals(getMethodName(), that.getMethodName());
81 | }
82 |
83 | @Override
84 | public int hashCode() {
85 | return Objects.hash(getMethodName(), projectName, buildVariants, platforms, isBuilt);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/model/TaskVariantValue.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.model;
2 |
3 | import java.util.List;
4 | import java.util.Objects;
5 | import java.util.Optional;
6 |
7 | public class TaskVariantValue {
8 |
9 | private final String id;
10 | private final String label;
11 | private final List subpackageBlacklist;
12 | private final List subpackageWhitelist;
13 |
14 | public TaskVariantValue() {
15 | id = null;
16 | label = null;
17 | subpackageBlacklist = null;
18 | subpackageWhitelist = null;
19 | }
20 |
21 | public TaskVariantValue(String id, String label) {
22 | this.id = id;
23 | this.label = label;
24 | subpackageBlacklist = null;
25 | subpackageWhitelist = null;
26 | }
27 |
28 | public TaskVariantValue(
29 | String id,
30 | String label,
31 | List subpackageBlacklist,
32 | List subpackageWhitelist
33 | ) {
34 | this.id = id;
35 | this.label = label;
36 | this.subpackageBlacklist = subpackageBlacklist;
37 | this.subpackageWhitelist = subpackageWhitelist;
38 | }
39 |
40 | public String getId() {
41 | return id;
42 | }
43 |
44 | public String getLabel() {
45 | return label;
46 | }
47 |
48 | public Optional> getSubpackageBlacklist() {
49 | return Optional.ofNullable(subpackageBlacklist);
50 | }
51 |
52 | public Optional> getSubpackageWhitelist() {
53 | return Optional.ofNullable(subpackageWhitelist);
54 | }
55 |
56 | @Override
57 | public boolean equals(Object o) {
58 | if (this == o) return true;
59 | if (!(o instanceof TaskVariantValue)) return false;
60 | TaskVariantValue that = (TaskVariantValue) o;
61 | return Objects.equals(id, that.id) &&
62 | Objects.equals(label, that.label) &&
63 | Objects.equals(subpackageBlacklist, that.subpackageBlacklist) &&
64 | Objects.equals(subpackageWhitelist, that.subpackageWhitelist);
65 | }
66 |
67 | @Override
68 | public int hashCode() {
69 | return Objects.hash(id, label, subpackageBlacklist, subpackageWhitelist);
70 | }
71 |
72 | @Override
73 | public String toString() {
74 | return "TaskVariantValue{" +
75 | "id='" + id + '\'' +
76 | ", label='" + label + '\'' +
77 | ", subpackageBlacklist=" + subpackageBlacklist +
78 | ", subpackageWhitelist=" + subpackageWhitelist +
79 | '}';
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/api/http/rest/RestUtils.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.api.http.rest;
2 |
3 | import org.fakekoji.functional.Result;
4 | import org.fakekoji.functional.Tuple;
5 | import org.fakekoji.jobmanager.model.Product;
6 |
7 | import java.util.Arrays;
8 | import java.util.List;
9 | import java.util.Map;
10 | import java.util.Optional;
11 |
12 | public class RestUtils {
13 |
14 | public static Optional extractParamValue(Map> paramsMap, String param) {
15 | return Optional.ofNullable(paramsMap.get(param))
16 | .filter(list -> list.size() == 1)
17 | .map(list -> list.get(0));
18 | }
19 |
20 | public static Result extractMandatoryParamValue(Map> paramsMap, String param) {
21 | return extractParamValue(paramsMap, param).>map(Result::ok)
22 | .orElseGet(() -> Result.err(new OToolError(
23 | "Missing mandatory parameter: '" + param + "'!",
24 | 400
25 | )));
26 | }
27 |
28 | static Result, OToolError> extractProducts(final Map> paramsMap) {
29 | return extractMandatoryParamValue(paramsMap, "from").flatMap(fromValue ->
30 | extractProduct(fromValue).flatMap(fromProduct ->
31 | extractMandatoryParamValue(paramsMap, "to").flatMap(toValue ->
32 | extractProduct(toValue).flatMap(toProduct ->
33 | Result.ok(new Tuple<>(fromProduct, toProduct))
34 | )
35 | )
36 | )
37 | );
38 | }
39 |
40 | static Result extractProduct(final String paramValue) {
41 | final String[] split = paramValue.split(",");
42 | if (split.length != 2 || split[0].trim().isEmpty() || split[1].trim().isEmpty()) {
43 | return Result.err(new OToolError("Expected format jdkVersionId,packageName", 400));
44 | }
45 | return Result.ok(new Product(split[0], split[1]));
46 | }
47 |
48 | static Result, OToolError> extractProjectIds(Map> paramsMap) {
49 | final Optional projectIdsOptional = extractParamValue(paramsMap, "projects");
50 | return projectIdsOptional., OToolError>>map(s ->
51 | Result.ok(Arrays.asList(s.split(",")))
52 | ).orElseGet(() -> Result.err(new OToolError(
53 | "projects are mandatory. Use get/projects?as=list to get them all",
54 | 400
55 | )));
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/fake-koji/src/main/java/org/fakekoji/jobmanager/model/JDKTestProject.java:
--------------------------------------------------------------------------------
1 | package org.fakekoji.jobmanager.model;
2 |
3 | import org.fakekoji.model.OToolVariable;
4 |
5 | import java.util.List;
6 | import java.util.Objects;
7 | import java.util.Set;
8 |
9 | public class JDKTestProject extends Project {
10 |
11 | private final List subpackageBlacklist;
12 | private final List subpackageWhitelist;
13 | private final TestJobConfiguration jobConfiguration;
14 |
15 | public JDKTestProject() {
16 | this.subpackageBlacklist = null;
17 | this.subpackageWhitelist = null;
18 | this.jobConfiguration = null;
19 | }
20 |
21 | public JDKTestProject(
22 | String id,
23 | Product product,
24 | Set buildProviders,
25 | List subpackageBlacklist,
26 | List subpackageWhitelist,
27 | TestJobConfiguration jobConfiguration,
28 | List variables
29 | ) {
30 | super(id, product, ProjectType.JDK_TEST_PROJECT, buildProviders, variables);
31 | this.subpackageBlacklist = subpackageBlacklist;
32 | this.subpackageWhitelist = subpackageWhitelist;
33 | this.jobConfiguration = jobConfiguration;
34 | }
35 |
36 | public List getSubpackageBlacklist() {
37 | return subpackageBlacklist;
38 | }
39 |
40 | public List getSubpackageWhitelist() {
41 | return subpackageWhitelist;
42 | }
43 |
44 | public TestJobConfiguration getJobConfiguration() {
45 | return jobConfiguration;
46 | }
47 |
48 | @Override
49 | public boolean equals(Object o) {
50 | if (this == o) return true;
51 | if (!(o instanceof JDKTestProject)) return false;
52 | if (!super.equals(o)) return false;
53 | JDKTestProject that = (JDKTestProject) o;
54 | return Objects.equals(subpackageBlacklist, that.subpackageBlacklist) &&
55 | Objects.equals(subpackageWhitelist, that.subpackageWhitelist) &&
56 | Objects.equals(jobConfiguration, that.jobConfiguration);
57 | }
58 |
59 | @Override
60 | public int hashCode() {
61 | return Objects.hash(super.hashCode(), subpackageBlacklist, subpackageWhitelist, jobConfiguration);
62 | }
63 |
64 | @Override
65 | public String toString() {
66 | return "JDKTestProject{" +
67 | ", subpackageBlacklist='" + subpackageBlacklist + '\'' +
68 | ", subpackageWhitelist='" + subpackageWhitelist + '\'' +
69 | ", jobConfiguration=" + jobConfiguration +
70 | '}';
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/jenkins-scm-koji-plugin/src/main/java/hudson/plugins/scm/koji/BuildsSerializer.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.scm.koji;
2 |
3 | import hudson.plugins.scm.koji.model.Build;
4 | import hudson.plugins.scm.koji.model.RPM;
5 | import java.io.BufferedInputStream;
6 | import java.io.BufferedOutputStream;
7 | import java.io.File;
8 | import java.io.FileInputStream;
9 | import java.io.FileOutputStream;
10 | import java.io.InputStreamReader;
11 | import java.io.OutputStreamWriter;
12 | import java.io.Reader;
13 | import java.io.Writer;
14 | import java.lang.ref.SoftReference;
15 | import jakarta.xml.bind.JAXBContext;
16 | import jakarta.xml.bind.Marshaller;
17 |
18 | public class BuildsSerializer {
19 |
20 | private static SoftReference JAXB_CONTEXT_REFERENCE = new SoftReference<>(null);
21 |
22 | private static JAXBContext jaxbContext() {
23 | try {
24 | JAXBContext context = JAXB_CONTEXT_REFERENCE.get();
25 | if (context == null) {
26 | context = JAXBContext.newInstance(Build.class, RPM.class);
27 | JAXB_CONTEXT_REFERENCE = new SoftReference<>(context);
28 | }
29 | return context;
30 | } catch (Exception ex) {
31 | throw new RuntimeException("Exception while initializing JAXB context", ex);
32 | }
33 | }
34 |
35 | public Build read(File file) {
36 | if (!file.exists() || !file.isFile() || file.length() < 1) {
37 | return null;
38 | }
39 | try (Reader reader = new InputStreamReader(new BufferedInputStream(new FileInputStream(file)), "UTF-8")) {
40 | Object result = jaxbContext().createUnmarshaller().unmarshal(reader);
41 | if (result == null || result instanceof Build) {
42 | return (Build) result;
43 | }
44 | // if we are still here - something went wrong:
45 | throw new RuntimeException("Deserialization expected Build but got: " + result);
46 | } catch (Exception ex) {
47 | throw new RuntimeException("Exception while reading the build XML", ex);
48 | }
49 | }
50 |
51 | public void write(Build build, File file) {
52 | try (Writer writer = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(file)), "UTF-8")) {
53 | Marshaller marshaller = jaxbContext().createMarshaller();
54 | marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
55 | marshaller.marshal(build, writer);
56 | } catch (Exception ex) {
57 | throw new RuntimeException("Exception while writing the build to file", ex);
58 | }
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------