{"id":20314524,"url":"https://github.com/release-engineering/kojiji","last_synced_at":"2025-04-11T17:17:32.465Z","repository":{"id":4881944,"uuid":"49527329","full_name":"release-engineering/kojiji","owner":"release-engineering","description":"Koji Java Interface","archived":false,"fork":false,"pushed_at":"2025-04-06T05:28:04.000Z","size":2325,"stargazers_count":6,"open_issues_count":1,"forks_count":21,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-06T06:25:33.573Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/release-engineering.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-01-12T20:35:43.000Z","updated_at":"2025-04-06T05:28:08.000Z","dependencies_parsed_at":"2024-08-22T02:53:00.677Z","dependency_job_id":"45b5230f-e723-4894-b019-9412dd8157eb","html_url":"https://github.com/release-engineering/kojiji","commit_stats":null,"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/release-engineering%2Fkojiji","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/release-engineering%2Fkojiji/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/release-engineering%2Fkojiji/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/release-engineering%2Fkojiji/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/release-engineering","download_url":"https://codeload.github.com/release-engineering/kojiji/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248447600,"owners_count":21105140,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T18:15:42.965Z","updated_at":"2025-04-11T17:17:32.443Z","avatar_url":"https://github.com/release-engineering.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Koji Java Interface\n\nThis is a Java API for talking to [Koji](https://fedoraproject.org/wiki/Koji).\n\n## Dependencies\n\n* [jHTTPc](https://github.com/commonjava/jhttpc) (Apache httpclient wrapper with SSL certificate-handling improvements, etc.)\n* [RWX](https://github.com/commonjava/RWX) (XML-RPC libraries offering flexibility in client choice, annotation-based data binding, etc.)\n* [Atlas](https://github.com/commonjava/atlas) (Object model and related utilities for working with Maven artifacts)\n\n## Developing New Kojiji Commands\n\nCurrently, the best success I've had in implementing Koji commands within Kojiji uses the following method:\n\n### 1. Capture the Messages Involved\n\nRun the command using the Koji command-line client, with `--debug-xmlrpc` enabled, and save it to a log file:\n\n\n```\n$ koji --debug-xmlrpc list-tags 2\u003e\u00261 | tee list-tags.log\n\nsend: 'POST /kojihub HTTP/1.1\\r\\nHost: REDACTED\\r\\nAccept-Encoding: identity\\r\\nUser-Agent: koji/1.7\\r\\nContent-Type: text/xml\\r\\nContent-Length: 107\\r\\n\\r\\n'\nsend: \"\u003c?xml version='1.0'?\u003e\\n\u003cmethodCall\u003e\\n\u003cmethodName\u003egetAPIVersion\u003c/methodName\u003e\\n\u003cparams\u003e\\n\u003c/params\u003e\\n\u003c/methodCall\u003e\\n\"\nreply: 'HTTP/1.1 200 OK\\r\\n'\nheader: Date: Thu, 21 Jul 2016 20:36:29 GMT\nheader: Server: Apache/2.2.15 (Red Hat)\nheader: Strict-Transport-Security: max-age=63072000; includeSubDomains\nheader: Content-Length: 121\nheader: Connection: close\nheader: Content-Type: text/xml\nbody: \"\u003c?xml version='1.0'?\u003e\\n\u003cmethodResponse\u003e\\n\u003cparams\u003e\\n\u003cparam\u003e\\n\u003cvalue\u003e\u003cint\u003e1\u003c/int\u003e\u003c/value\u003e\\n\u003c/param\u003e\\n\u003c/params\u003e\\n\u003c/methodResponse\u003e\\n\"\nsend: 'POST /kojihub HTTP/1.1\\r\\nHost: REDACTED\\r\\nAccept-Encoding: identity\\r\\nUser-Agent: koji/1.7\\r\\nContent-Type: text/xml\\r\\nContent-Length: 178\\r\\n\\r\\n'\nsend: \"\u003c?xml version='1.0'?\u003e\\n\u003cmethodCall\u003e\\n\u003cmethodName\u003elistTags\u003c/methodName\u003e\\n\u003cparams\u003e\\n\u003cparam\u003e\\n\u003cvalue\u003e\u003cnil/\u003e\u003c/value\u003e\u003c/param\u003e\\n\u003cparam\u003e\\n\u003cvalue\u003e\u003cnil/\u003e\u003c/value\u003e\u003c/param\u003e\\n\u003c/params\u003e\\n\u003c/methodCall\u003e\\n\"\nreply: 'HTTP/1.1 200 OK\\r\\n'\nheader: Date: Thu, 21 Jul 2016 20:36:30 GMT\nheader: Server: Apache/2.2.15 (Red Hat)\nheader: Strict-Transport-Security: max-age=63072000; includeSubDomains\nheader: Content-Length: 5693545\nheader: Connection: close\nheader: Content-Type: text/xml\nbody: \"\u003c?xml version='1.0'?\u003e\\n\u003cmethodResponse\u003e\\n\n[...]\n```\n\n### 2. Split the Messages into Exchanges\n\nUse the `koji-output-tidy.py` helper script in `research/` to generate a series of message-exchange files in a new folder:\n\n\n```\n$ mkdir research/list-tags\n$ ./research/koji-output-tidy.py list-tags.log research/list-tags/list-tags\n\nOpening temp/list-tags-1.txt\nClosing temp/list-tags-1.txt (10 lines)\nOpening temp/list-tags-2.txt\nClosing temp/list-tags-2.txt (717 lines)\n```\n\n### 3. Redact Sensitive Information in Research Folder\n\nYour captured HTTP exchanges will contain server addresses and XML-RPC endpoint information. **Please take great care to redact this information, in order to avoid any sort of security problem with running systems.**\n\n### 4. Implement the Model Classes\n\nFor each file in the output directory, implement the appropriate object-model classes in the `com.redhat.red.build.koji.model.xmlrpc.messages` package, using the RWX bindings, to model the XML request and response. Here's part of an example message exchange file containing some of the `list-tags` result from above:\n\n\n```\n\u003c?xml version='1.0'?\u003e\n\u003cmethodCall\u003e\n\u003cmethodName\u003elistTags\u003c/methodName\u003e\n\u003cparams\u003e\n\u003cparam\u003e\n\u003cvalue\u003e\u003cnil/\u003e\u003c/value\u003e\u003c/param\u003e\n\u003cparam\u003e\n\u003cvalue\u003e\u003cnil/\u003e\u003c/value\u003e\u003c/param\u003e\n\u003c/params\u003e\n\u003c/methodCall\u003e\n\nHTTP/1.1 200 OK\n\nDate: Thu, 21 Jul 2016 20:36:30 GMT\nServer: Apache/2.2.15 (Red Hat)\nStrict-Transport-Security: max-age=63072000; includeSubDomains\nContent-Length: 5693545\nConnection: close\nContent-Type: text/xml\n\u003c?xml version='1.0'?\u003e\n\u003cmethodResponse\u003e\n\u003cparams\u003e\n\u003cparam\u003e\n\u003cvalue\u003e\u003carray\u003e\u003cdata\u003e\n\u003cvalue\u003e\u003cstruct\u003e\n\u003cmember\u003e\n\u003cname\u003emaven_support\u003c/name\u003e\n\u003cvalue\u003e\u003cboolean\u003e0\u003c/boolean\u003e\u003c/value\u003e\n\u003c/member\u003e\n\u003cmember\u003e\n\u003cname\u003elocked\u003c/name\u003e\n\u003cvalue\u003e\u003cboolean\u003e0\u003c/boolean\u003e\u003c/value\u003e\n\u003c/member\u003e\n\u003cmember\u003e\n\u003cname\u003ename\u003c/name\u003e\n\u003cvalue\u003e\u003cstring\u003emy-tag\u003c/string\u003e\u003c/value\u003e\n\u003c/member\u003e\n\u003cmember\u003e\n\u003cname\u003eperm\u003c/name\u003e\n\u003cvalue\u003e\u003cnil/\u003e\u003c/value\u003e\u003c/member\u003e\n\u003cmember\u003e\n\u003cname\u003eid\u003c/name\u003e\n\u003cvalue\u003e\u003cint\u003e1\u003c/int\u003e\u003c/value\u003e\n\u003c/member\u003e\n\u003cmember\u003e\n\u003cname\u003earches\u003c/name\u003e\n\u003cvalue\u003e\u003cstring\u003ei386\u003c/string\u003e\u003c/value\u003e\n\u003c/member\u003e\n\u003cmember\u003e\n\u003cname\u003emaven_include_all\u003c/name\u003e\n\u003cvalue\u003e\u003cboolean\u003e0\u003c/boolean\u003e\u003c/value\u003e\n\u003c/member\u003e\n[...]\n```\n\nFor this example, the corresponding object-model classes are [com.redhat.red.build.koji.model.xmlrpc.messages.ListTagsRequest](https://github.com/release-engineering/kojiji/blob/master/src/main/java/com/redhat/red/build/koji/model/xmlrpc/messages/ListTagsRequest.java) and [com.redhat.red.build.koji.model.xmlrpc.messages.ListTagsResponse](https://github.com/release-engineering/kojiji/blob/master/src/main/java/com/redhat/red/build/koji/model/xmlrpc/messages/ListTagsResponse.java).\n\n### 5. Factor Out Common Payload Sections\n\nMany requests / responses will contain the same types of information. These should be factored out into common object-model classes that can be reused between message class types. These live in the `com.redhat.red.build.koji.model.xmlrpc` package. For instance, multiple Koji calls may return build information as part of the response. This information is captured by the class [com.redhat.red.build.koji.model.xmlrpc.KojiBuildInfo](https://github.com/release-engineering/kojiji/blob/master/src/main/java/com/redhat/red/build/koji/model/xmlrpc/KojiBuildInfo.java).\n\n### 6. Write Unit Tests\n\nYou already have sample XML for the request and response messages that Koji expects. From here, you can turn them into unit tests that verify round-trip serialization / deserialization to XML for your new model classes. By chopping up each message exchange into its constituent XML documents and saving them in `src/test/resources`, you can implement something like the following minimal set of unit tests:\n\n* [com.redhat.red.build.koji.model.xmlrpc.messages.ListTagsRequestTest](https://github.com/release-engineering/kojiji/blob/master/src/test/java/com/redhat/red/build/koji/model/xmlrpc/messages/ListTagsRequestTest.java)\n* [com.redhat.red.build.koji.model.xmlrpc.messages.ListTagsResponseTest](https://github.com/release-engineering/kojiji/blob/master/src/test/java/com/redhat/red/build/koji/model/xmlrpc/messages/ListTagsResponseTest.java)\n\n### 7. TO BE DOCUMENTED: Integration Testing\n\nUnit tests are fine for verifying compatibility with a message protocol from a given point in time, but what happens if that message protocol changes? The only way to be really certain of compatibility with a particular version of Koji is to run tests that talk to a live instance. We have some of these tests already, which use a suite of Docker containers at build time to provision a Koji environment for testing purposes. After the build completes, these instances are torn down and discarded (after logs and other files pertinent to the test results have been retrieved, of course). To support this, we're using a project called [koji-dojo](https://github.com/release-engineering/koji-dojo).\n\nWhile this is a great way to be absolutely certain of compatibility, it is definitely labor intensive. It takes quite a bit of work to define the initial state of the system and then load it just in time for a test to use it. And beyond test data management, it becomes important to be able to simulate certain actions within the Koji environment (like builds taking place) in order to ensure the database is in a valid state. This is where we need to go next, and some of Kojiji's commands don't have integration tests now because we have yet to mock the logic that Koji's builder daemon uses to register a completed build.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frelease-engineering%2Fkojiji","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frelease-engineering%2Fkojiji","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frelease-engineering%2Fkojiji/lists"}