387 Commits

Author SHA256 Message Date
9b3d6e9a66 pr: Always allow maintainer edits in new packages 2026-01-31 10:38:03 +01:00
f47da62481 common: replace legacy logger with standard impl 2026-01-31 10:18:14 +01:00
79e5345ac6 test: refactor loggin in unit tests
Use test logger when running under a test.
2026-01-31 10:04:08 +01:00
4790ee3096 pr: small refactor 2026-01-30 16:44:11 +01:00
7d85c014d6 pr: test coverage 2026-01-30 16:44:11 +01:00
05aaf56cb7 pr: test coverage 2026-01-30 16:44:11 +01:00
74491cb9cf pr: small refactor 2026-01-30 16:44:11 +01:00
9775320411 pr: close associated PR if issue closed. 2026-01-30 16:44:11 +01:00
790540d6c5 common: test fixes after rebase 2026-01-30 16:44:11 +01:00
990f71677b pr: no need to create PR if already exists. 2026-01-30 16:44:11 +01:00
514725fb0b pr: Only update issues if they are actually open 2026-01-30 16:44:11 +01:00
ea69dcd19f pr: fix tests 2026-01-30 16:44:11 +01:00
055de8c9eb pr: use top 20 commits as base, if available 2026-01-30 16:44:11 +01:00
a13f57e464 common: add test for cloning hashes 2026-01-30 16:44:11 +01:00
b147fc7622 common: add test for directory listing 2026-01-30 16:44:11 +01:00
fc7fb4d49f pr: test updated issue ref
If issue is a SHA ref, and then it's updated, we need to make
sure that the branch is also updated.
2026-01-30 16:44:11 +01:00
40eeb25336 pr: move functions around 2026-01-30 16:44:11 +01:00
68a142046c pr: fix tests 2026-01-30 16:44:11 +01:00
240d79a4d6 pr: new package handling 2026-01-30 16:44:11 +01:00
21a8670674 pr: make sure new repos have fork/parent relationship
If new target repo is "reparented", it will have correct relationship
here. Otherwise PR creation will fail
2026-01-30 16:44:11 +01:00
d2e9abde6e common: more unit tests fixes
TZ needs to be defined, otherwise it was assumed to be local which
then resulted in unpredictable commit hashes. We define it to UTC
for unit tests

PR have state "open" not "opened"
2026-01-30 16:44:11 +01:00
a4f677690a pr: fix more unit tests 2026-01-30 16:44:10 +01:00
70460813f5 pr: merge new package 2026-01-30 16:44:10 +01:00
0651fe01d4 pr: implement first part of issue processing 2026-01-30 16:44:10 +01:00
e03fd0bdcf wip: process issues 2026-01-30 16:44:10 +01:00
c6ee055cb4 pr: add unit test for PrjGit PR to make sure we clone it
This is unit test for previous commit
2026-01-30 16:23:25 +01:00
58e5547a91 pr: fix case where PrjGit not cloned
When the PRSet is of size 1, so only PrjGit, the project git
may not be cloned. This breaks build preperations, etc.
2026-01-30 16:02:13 +01:00
c2709e1894 fix unit tests and mocks 2026-01-28 10:50:36 +01:00
7790e5f301 Merge branch 'main' into always-review-nt 2026-01-27 15:45:12 +01:00
2620aa3ddd Merge branch 'always-review' 2026-01-27 15:44:30 +01:00
59a47cd542 Merge branch 'pr-tests' 2026-01-27 13:41:34 +01:00
a0c51657d4 pr: reset timeline cache when fetching PRSet 2026-01-26 15:34:46 +01:00
edd8c67fc9 obs-staging-bot: allow build-disabling repositories in the QA projects
Using the BuildDisableRepos configuration, it is now possible to
define which repositories to build-disable in the QA project meta.

This is for example useful for the SLES development workflow, where
the product repository should only be enabled after the packagelist
definitions have been built - so it is not desirable to have them
built as soon as the QA project is created.

Example:

    {
      "ObsProject": "SUSE:SLFO:Main",
      "StagingProject": "SUSE:SLFO:Main:PullRequest",
      "QA": [
        {
          "Name": "SLES",
          "Origin": "SUSE:SLFO:Products:SLES:16.1",
          "BuildDisableRepos": ["product"]
        }
      ]
    }

Signed-off-by: Eugenio Paolantonio <eugenio.paolantonio@suse.com>
2026-01-21 19:05:48 +01:00
877e93c9bf pr: always require review, if configured
Implement ReviewRequired option to workflow.config. This will
always require a review by maintainer, unless no other maintainers
are available.

By default, ReviewRequired is false
2026-01-20 19:18:56 +01:00
51403713be pr: always require review, if configured
Implement ReviewRequired option to workflow.config. This will
always require a review by maintainer, unless no other maintainers
are available.

By default, AlwaysRequireReview is false
2026-01-20 19:17:10 +01:00
cc69a9348c Merge commit 'refs/pull/109/head' of src.opensuse.org:git-workflow/autogits 2026-01-20 18:39:23 +01:00
5b5bb9a5bc group-review: fix test name 2026-01-19 13:41:05 +01:00
Antonello Tartamo
2f39fc9836 initial documentation review 2026-01-14 15:43:27 +01:00
f959684540 pr: interfaces moved to main package 2026-01-10 00:57:22 +01:00
18f7ed658a pr: move interfaces and mocks to parent package 2026-01-10 00:40:45 +01:00
c05fa236d1 pr: Add additional unit tests
- Add a test case specifically verifying that `Gitea.SetLabels`
  is called with `staging/Auto` when a *new* project PR is created
  for submodules.
- Verify `PrjGitDescription` and `SetSubmodulesToMatchPRSet` behave
  correctly when a single `PRSet` contains 5+ different package
  repositories.
2026-01-09 18:56:33 +01:00
c866303696 pr: fix PR lists to check packages not just project PRs
Also,
- Add simple unit tests to verify mapping of `models.StateType`
  to internal event strings.
- Verify it correctly wraps `ProcesPullRequest` and handles panics
  via the deferred recovery block.
- Add tests for scenarios where `GetRecentPullRequests` fails.
- Verify the random sleep interval logic (can be tested by mocking
  `time.Sleep` if refactored, or verifying behavior with interval=0).
2026-01-09 17:48:01 +01:00
e806d6ad0d pr: revive PRProcessor sync tests
- Uncomment and fix the existing tests for `synchronized` actions.
- Ensure it uses the new `PullRequestProcessor` interface and mocked dependencies.
2026-01-09 17:12:14 +01:00
abf8aa58fc pr: test PRProcessor that is triggered by webhook
- PullRequestWebhookEvent: Verified that PR events correctly
  trigger processing with all necessary Gitea and Git mocks.
- IssueCommentWebhookEvent: Verified that issue comment events
  (which Gitea often uses for PR comments) are handled correctly.
- Recursion Limit: Verified that the recursion protection logic
  correctly terminates and cleans up when the limit is reached.
- Invalid Data Format: Verified that non-event data types return
  appropriate errors.
2026-01-09 16:59:29 +01:00
4f132ec154 pr: test verifyRepositoryConfiguration 2026-01-09 16:41:25 +01:00
86a7fd072e pr: add test cases for PRProcessor corner cases
- Add scenarios for closed/merged project PRs that trigger
   submodule checks and downstream PR updates (manual merge vs close).
- Test the "Consistency check" logic where submodules are reset
  if they don't match the PR set.
- Test the "superfluous PR" check (no-op PRs that should be closed).
2026-01-09 16:34:07 +01:00
5f5e7d98b5 pr: add some tests for UpdatePrjGitPR 2026-01-09 13:59:02 +01:00
e8738c9585 pr: add tests for RebaseAndSkipSubmoduleCommits 2026-01-09 13:44:53 +01:00
2f18adaa67 pr: move common test helpers to dedicated area 2026-01-09 12:57:42 +01:00
b7f5c97de1 pr: add error handling unit tests 2026-01-08 22:21:33 +01:00
09001ce01b pr: repo_check unit tests 2026-01-08 21:02:18 +01:00
37c9cc7a57 add PRProcessor tests 2026-01-08 20:57:18 +01:00
362e481a09 pr: fix unit tests 2026-01-08 17:54:00 +01:00
38f4c44fd0 group-review: add more unit tests 2026-01-07 11:56:04 +01:00
605d3dee06 group-review: add notification unit tests 2026-01-07 11:32:04 +01:00
6f26bcdccc group-review: add mocked unit test 2026-01-07 10:42:39 +01:00
fffdf4fad3 group-review: add additional unit tests 2026-01-07 10:29:54 +01:00
f6d2239f4d group-review: move globals to struct
This enables easier testing
2026-01-07 10:27:12 +01:00
913fb7c046 group-review: add systemd file 2026-01-05 17:07:27 +01:00
79318dc169 group-review: add env variables
instead of using command-line parameters, we can use env variables
Very helpful for services.
2026-01-05 16:53:30 +01:00
377ed1c37f group-review: set correct comment text on negative review 2026-01-05 14:13:53 +01:00
51b0487b29 pr: parse ADD issue body
Validation of repository and org and other names is for the
consumer of this call. Maybe this can change later.
2025-12-16 18:33:22 +01:00
49e32c0ab1 PR: actually subscribe to PRComments
In previous fix attempt, there were changes to process IssueComments
but PRComments are their instance of IssueComments distinct from
IssueComments webhook events

Fixes: a418b48809
2025-12-12 16:41:25 +01:00
01e4f5f59e pr: fix error reporting for timeline PrjGit parse 2025-12-11 18:45:56 +01:00
19d9fc5f1e pr: request staging only when staging.config is there
If the project git does not have a staging.config, then there is
no reason to request reviews by the staging bot.
2025-12-11 17:01:15 +01:00
c4e184140a pr: handle case when reviews is nil 2025-12-09 17:19:38 +01:00
56c492ccdf PR: do not remove maintainer if also a reviewer
Maintainer review is only required if the PR is created by non-maintainer
or ProjetGit PR is created by non-bot. If maintainer review is not required,
but the maintainer is also listed as a Reviewer, then we cannot remove
this review request from the PR.
2025-12-08 18:03:00 +01:00
3a6009a5a3 pr: review requests cannot be stale
Yes, gitea marks these as stale too, but we should just ignore this
flag in case of requests. Stale requests are still pending.
2025-12-05 10:15:02 +01:00
2c4d25a5eb pr: remove maintainers if submitter is maintainer
If we have case where reviews are already there, for whatever reason
(eg. upgrade from older bot), remove the pending reviews if they
are not needed
2025-12-05 09:36:38 +01:00
052ab37412 common: Loading pending reviews when loading reviews 2025-12-04 19:02:21 +01:00
925f546272 pr: check all reviews, not just ones tagged reviewers 2025-12-04 18:21:32 +01:00
71fd32a707 pr: fix debug statements 2025-12-04 18:04:51 +01:00
581131bdc8 pr: request and unrequest reviewers
Move the function to request and unrequest reviewers to a different
function. This will allow later simplification of the function
that determines if all reviews are complete.

Unrequesting of reviews is only possible in case of bot issued
review requests. The rest are left as-is.
2025-12-03 18:55:10 +01:00
495ed349ea common: refactor: FetchPRSet also fetches Reviews 2025-12-03 18:55:10 +01:00
350a255d6e pr: allow to fetch reviews in PRSet loader 2025-12-03 18:55:10 +01:00
e3087e46c2 PR: skip maintainer review if not needed
If project or package maintainer already reviewed the PR, as
appropriate, they are no longer re-added to the PR. We also need
to remove reviewers, but only if they were previously requested
by the bot and not something else.
2025-12-03 18:55:10 +01:00
ae6b638df6 pr: handle case of … and ... elided title
Also do not change title of PR if not created by bot
2025-12-03 12:41:50 +01:00
2c73cc683a status: placeholder for factory sample data tests 2025-11-28 18:45:24 +01:00
32adfb1111 doc: fix table 2025-11-28 17:46:49 +01:00
fe8fcbae96 status: add test data 2025-11-28 17:22:12 +01:00
5756f7ceea pr: only update PR if elided title not changed
Gitea trims long titles so we need to compare if the trimmed length
is same, not entire string that will always differ.
2025-11-28 12:25:58 +01:00
2be0f808d2 pr: make sure issue list is consistent 2025-11-28 12:08:54 +01:00
7a0f651eaf direct: Gitea can send messages with no default branch
When a repository is created, there appears to be a race condition
where the default branch is not yet set in the message webhook
event.

We should additionally take care if the submodule is "registered"
but it wasn't correctly added, mostly due to earlier error. So,
always deinit submodules
2025-11-25 10:32:59 +01:00
2e47104b17 direct: improve commit messages in auto-updates 2025-11-24 12:58:46 +01:00
76bfa612c5 direct: use local branch name, instead of remote
If we fetch only one commit and force fetch the branch to local,
it seems that the remote head ref is not actually set. So, we should
just use the local version anyway, as it's updated.
2025-11-24 11:38:54 +01:00
71aa0813ad devel: sync migrated project list 2025-11-20 20:30:38 +01:00
cc675c1b24 devel: ignore dot files
magic hash is when no files exist and echo "" is passed to md5sum
2025-11-20 19:57:35 +01:00
44e4941120 devel: handle build.specials.obscpio 2025-11-20 19:40:49 +01:00
86acfa6871 pr: set staging auto label according to config
falls back to staging/Auto if nothing is set
2025-11-20 16:25:06 +01:00
7f09b2d2d3 common: match project config before packages
We need to cycle through all project configs before we try to
match non-project config branches/packages. If we have multiple
project gits in one org, this coudl match wrong config
2025-11-20 13:22:40 +01:00
f3a37f1158 pr: case fold 2025-11-19 19:32:55 +01:00
9d6db86318 pr: log case of no config in verification check 2025-11-19 17:10:08 +01:00
e11993c81f pr: do not stop processing if failed on some pacakge during check 2025-11-19 16:36:48 +01:00
4bd259a2a0 pr: ignore pkg PR if not open and no PrjGit PR 2025-11-19 16:35:17 +01:00
162ae11cdd common: init the cache so not null 2025-11-19 15:29:52 +01:00
8431b47322 group-review: allow dots in org and package names 2025-11-19 10:00:39 +01:00
3ed5ecc3f0 pr: add staging/Auto on new PRs
also, cache timeline fetches
2025-11-17 11:01:45 +01:00
d08ab3efd6 direct: support reverts 2025-11-13 23:52:05 +01:00
a4f6628e52 direct: always deinit, even if dirty 2025-11-13 23:51:18 +01:00
25073dd619 direct: use correct remote name for submodules
should be "origin"
2025-11-13 22:15:00 +01:00
4293181b4e pr: improve logging of review errors
when user is missing, log only the missing user
2025-11-12 21:39:26 +01:00
551a4ef577 direct: use origin for submodule checkout 2025-11-10 11:03:54 +01:00
6afb18fc58 direct: use correct repo for default branch 2025-11-10 10:24:33 +01:00
f310220261 direct: log default branch 2025-11-10 10:11:11 +01:00
ef7c0c1cea direct: fix debug logging 2025-11-10 09:42:43 +01:00
27230fa03b direct: fix debug logging 2025-11-10 09:34:10 +01:00
c52d40b760 direct: explicit path for config bind 2025-11-09 23:26:04 +01:00
d3ba579a8b common: fix systemd execution
In case when we are running under older systemd that does not set
transient home, we need to improvise when connecting via SSH
and passing the identity file explicitly
2025-11-09 23:10:08 +01:00
9ef8209622 direct: bind config to working directory
Use temp /run instance directory for the config
Use ./config.json as default from within the process
2025-11-07 17:06:27 +01:00
ba66dd868e direct: fix running bot without any config params
Only use env variables.
2025-11-07 16:19:13 +01:00
17755fa2b5 status: fix repo links for monitor page 2025-11-07 13:59:52 +01:00
f94d3a8942 status: update README 2025-11-05 16:56:30 +01:00
20e1109602 spec: packaging fixes
* Update Version to 1, since we now have devel project and updates
should have version bump instead of downgrade
* other fixes
2025-11-05 16:38:15 +01:00
c25d3be44e direct: add systemd unit file 2025-11-05 13:24:54 +01:00
8db558891a direct: remove config.Branch clobbering
use our own copy of branch instead of writing it in the config.
This should fix handling of default branches where the default
branch differs between repositories.
2025-11-04 18:00:21 +01:00
0e06ba5993 common: classifying rm branches on name
Branches with suffixes

  -rm
  -removed
  -deleted

are now classified as removed. This is important in case project
config refers to default branch names which must exist so we need
to be able to classify such branches to either use them or ignore
them
2025-11-04 18:00:21 +01:00
736769d630 direct: add a repo with branch but no submodule 2025-11-04 18:00:21 +01:00
93c970d0dd direct: move logging to common.Log* function 2025-11-04 18:00:21 +01:00
5544a65947 obs-staging-bot: Expand possible branch of QA repos
That way a source merge of any product is not triggering rebuilds in
pull request QA sub projects. We may need a config option here to
enable/disable this.
2025-11-03 17:54:57 +01:00
918723d57b Merge commit '55846562c1d9dcb395e545f7c8e0bcb74c47b85693f4e955ef488530781b9bf2'
PR!88
2025-11-03 17:49:45 +01:00
a418b48809 pr: process PR on comments, not issue changes 2025-10-31 13:07:18 +01:00
55846562c1 Add simple readme for gitea_status_proxy 2025-10-31 10:33:58 +01:00
95c7770cad Change log level for auth errors 2025-10-31 10:33:58 +01:00
1b900e3202 Properly proxy json input directly to gitea 2025-10-31 10:33:51 +01:00
d083acfd1c Be more verbose about authentication errors 2025-10-30 13:09:17 +01:00
244160e20e Update authorization headers
For gitea API AuthorizationHeaderToken tokens must be prepended with "token" followed by a space, also fix content type
2025-10-30 13:09:17 +01:00
ed2847a2c6 README: devel-project follows main
And use home:adamm:autogits/autogits for building staging branch, if any
2025-10-28 12:54:22 +01:00
1457caa64b Merge branch 'main' of src.opensuse.org:git-workflow/autogits 2025-10-28 12:51:12 +01:00
b9a38c1724 Update README.md 2025-10-28 12:09:10 +01:00
74edad5d3e devel: fix pool setting script 2025-10-28 11:32:51 +01:00
Jan Zerebecki
e5cad365ee Run go tests from rpm check
Skip some failing tests to be able to run the rest.
Add missing config to make git commit succeed inside rpmbuild.
2025-10-27 14:42:21 +01:00
Jan Zerebecki
53851ba10f Add ci jobs for go vendor 2025-10-24 11:45:41 +02:00
Jan Zerebecki
056e5208c8 Add ci jobs for go generate
either to check it produces no diff, or to manually trigger pushing any
diff as a commmit to the current branch.
2025-10-24 11:45:38 +02:00
Jan Zerebecki
af142fdb15 Prefix packages and build rest
Add some dependencies from Containerfiles, so containers can be built
from the rpm and implicitly pull those in.
Build some binaries that where added since and add sub-package for them.
2025-10-24 11:22:52 +02:00
Jan Zerebecki
5ce92beb52 Add go generate result 2025-10-24 10:39:34 +02:00
Gitea Actions
ae379ec408 CI run result of: go mod vendor 2025-10-24 10:39:31 +02:00
458837b007 status: complete the fix for insufficient Clone()
Ammends: 58d1f2de91
2025-10-15 18:46:46 +02:00
a3feab6f7e status: use obs+xml mime header instead of xml
browsers request application/xml on their Accept: headers by default,
which causes status to return XML to them instead of falling back
to SVG
2025-10-15 18:42:52 +02:00
fa647ab2d8 status: do not marshall empty XMLName in json 2025-10-15 18:24:52 +02:00
19902813b5 status: fix xml output 2025-10-15 18:09:21 +02:00
23a7f310c5 status: Add application/xml support in output 2025-10-15 16:59:52 +02:00
58d1f2de91 status: make a copy before overwriting 2025-10-14 19:37:36 +02:00
d623844411 pr: do not fail checkout 2025-10-13 18:37:42 +02:00
04825b552e pr: use force-merge instead of force-push
The permission is to accept a change without required reviews, not
to actually force-push

Fixes 7bad8eb5a9
2025-10-12 10:22:49 +02:00
ca7966f3e0 pr: sanity check
make sure that the checked out PR matches what Gitea is sending
us, otherwise pause for a few seconds and retry.
2025-10-11 18:10:15 +02:00
0c47ca4d32 pr: updating PR needs to update the SHA
If we are updating a Project Git PR, we need to save the updated
hash or we may be lookign at pre-update PR for various operations,
including merging.

This mostly only affects project gits in devel projects where
the project git could be updated by direct workflow bot, but then
the project is incorrectly resulting in no package update.
2025-10-11 17:25:48 +02:00
7bad8eb5a9 pr: Add config definitions for permission set 2025-10-09 18:43:56 +02:00
c2c60b77e5 use autogits package prefix 2025-10-08 13:03:06 +02:00
76b5a5dc0d import: factory hash setting utility 2025-10-07 22:55:58 +02:00
58da491049 common: handle translation to SSH if already SSH 2025-10-07 17:26:27 +02:00
626bead304 status: improve request logging 2025-10-06 14:07:35 +02:00
30bac996f4 status: redundant entry in service file 2025-10-06 14:03:38 +02:00
9adc718b6f spec: hujson moved to utils subpackage 2025-10-06 13:52:39 +02:00
070f45bc25 status: add no lock function
Locking is not re-entrant, so these are useful if we need
to find things while we already lock the strctures
2025-10-06 13:49:19 +02:00
d061f29699 status: use env as parameters to service
Instead of having to rewrite the service file with parameters,
leverage Env file to pass default parameters values.
2025-10-06 13:49:12 +02:00
f6fd96881d staging: improve docs 2025-10-02 17:40:00 +02:00
2be785676a reparent: add readme 2025-10-02 17:05:34 +02:00
1b9ee2d46a PR: ref requries PR fetch, and not in timeline 2025-10-02 15:13:43 +02:00
b7bbafacf8 PR: limit search to bot account for ProjectGit PRs 2025-10-02 13:45:31 +02:00
240896f101 status: fix delete function logic 2025-10-01 19:35:43 +02:00
a7b326fceb status: limit results to specific packages 2025-10-01 19:28:47 +02:00
76ed03f86f status: add json output support
if Accept: application/json is present, return JSON output
of build results instead of SVG
2025-10-01 18:58:08 +02:00
1af2f53755 PR: Fix case where PR repo != target repo
Was using a check that the label has the repo name in it, but
this is not always reliable. So, check repo.ID if it's the same.
2025-10-01 15:33:39 +02:00
0de9071f92 group-review: we need to clone before modifying a slice 2025-09-30 17:27:36 +02:00
855faea659 imported devel:openSUSE:Factory 2025-09-29 15:10:25 +02:00
dbd581ffef import: packages are not just in factory
Some packages share names of openSUSE:Factory packages but actually
have nothing in common with them. So before importing the Factory
package, check if the package is actually a devel project for Factory
and only proceed if it is. Otherwise, assume that the devel
project package is independent.
2025-09-29 15:08:30 +02:00
1390225614 PR: list missing PRs in the logs 2025-09-29 14:58:43 +02:00
a03491f75c Keep maintainers from staging template project
They need to keep access as they might need to be able to modify the
stage project. They could grant access anyway, by adding themselfs
as they own the upper project. No reason to force them the
extra trip or to hide build results first to them
2025-09-24 10:39:07 +02:00
2092fc4f42 Fix handling of all project flags
We skipped access and sourceaccess flags before
2025-09-24 09:33:29 +02:00
d2973f4792 PR: only consider open PR when creating new PRs 2025-09-21 23:21:40 +02:00
58022c6edc update transition project list 2025-09-21 20:21:15 +02:00
994e6b3ca2 status: fix typo regression 2025-09-18 19:18:03 +02:00
6414336ee6 status: add basic project level build results 2025-09-18 19:05:35 +02:00
1104581eb6 status: superflous Sprintf 2025-09-18 16:50:59 +02:00
6ad110e5d3 status: escape strings 2025-09-18 16:30:34 +02:00
e39ce302b8 status: fix README 2025-09-18 13:07:08 +02:00
3f216dc275 docs: improve README 2025-09-16 22:30:18 +02:00
8af7e58534 common: handle group data in PR reviews 2025-09-16 18:13:35 +02:00
043673d9ac common: handle ReviewGroup in maintainership data
ReviewGroups can be added as maintainers and can be optionally
expanded. This is handy when a ReviewGroup is a project maintainer
2025-09-16 17:40:18 +02:00
73737be16a rabbitmq: add support for forwarding status events to Rabbit 2025-09-16 13:23:43 +02:00
1d3ed81ac5 staging: use https cloning always
We can just pass the token, so SSH option for cloning is obsolete
2025-09-16 10:11:28 +02:00
49c4784e70 staging: handle case of no staging config 2025-09-15 17:58:21 +02:00
be15c86973 staging: use correct gitea token 2025-09-15 17:44:52 +02:00
72857db561 staging: add gitea token as user for cloning
For private repos, we need to identify ourselves to Gitea
2025-09-15 17:28:38 +02:00
faf53aaae2 move staging-bot env file to /etc/default 2025-09-15 14:00:56 +02:00
9e058101f0 Merge commit '4ae45d9913dcd473fc931c27dcc5dee93c70723121bf6f77c256c7dd196ea768' of src.opensuse.org:adamm/autogits 2025-09-15 13:54:46 +02:00
Elisei Roca
4ae45d9913 Look for configuration file in /etc/default
Files in /etc/sysconfig/ should have all the sysconfig headers an so on.
2025-09-15 13:24:18 +02:00
56cf8293ed staging: clone via target repo only 2025-09-15 12:30:08 +02:00
fd5b3598bf Don't crash when new packages got added
The build result request of the base project is failing in this
situation, since the requested package does not exist.

Therefore we need to have seperate lists for proper handling.
2025-09-13 15:47:50 +02:00
9dd5a57b81 staging: fix no config case 2025-09-11 17:22:02 +02:00
1cd385e227 common: handle case of non-existing config file 2025-09-11 16:56:03 +02:00
3c20eb567b staging: allow wider character set in pr regex 2025-09-11 16:09:42 +02:00
ff7df44d37 staging: assume changed directories are packages
Ignore any non-top level direcotries here. This should be fixed
to handle _manifest files
2025-09-11 14:56:27 +02:00
1a19873f77 Merge remote-tracking branch 'gitea/main' 2025-09-11 09:35:05 +02:00
6a09bf021e Revert "common: use X-Total-Count in multi-page results"
This reverts commit 5addde0a71.
2025-09-11 09:34:13 +02:00
f2089f99fc staging: use helper function to SetCommitStatus 2025-09-09 12:55:14 +02:00
10ea3a8f8f obs-staging-bot: Fix setting of commit status 2025-09-09 12:46:43 +02:00
9faa6ead49 Log errors on SetCommitStatus 2025-09-09 12:46:21 +02:00
29cce5741a staging: typo fix 2025-09-09 12:46:11 +02:00
804e542c3f Decline too large staging projects
In most cases anyway an error in pull request.
2025-09-09 12:41:07 +02:00
72899162b0 status: need to fetch repositories during sync
We need to fetch repositories so that we can have package
data. We only need to fetch one set of results per project,
not all repos.
2025-09-03 16:42:01 +02:00
168a419bbe status: allow for package search endpoint
OBS has issues searching for packages in scmsynced projects.
Since we have a list of all the repositories, we can allow
for a search endpoint here.

/search?q=term1&q=term2...

results is JSON

[
   project1/pkgA,
   project2/pkgB
]
2025-09-03 14:35:15 +02:00
6a71641295 common: take care of empty result sets
In case of empty result pages, we should ignore the X-Total-Count
header.

Fixes: 5addde0a71
2025-09-03 12:21:07 +02:00
5addde0a71 common: use X-Total-Count in multi-page results 2025-09-03 01:00:33 +02:00
90ea1c9463 common: remove duplicate 2025-09-02 20:50:23 +02:00
a4fb3e6151 PR: Don't clobber other's PrjGit description
If we did not create the PRjGit PR, don't touch the title
and description

Closes: #68
2025-09-02 19:47:47 +02:00
e2abbfcc63 staging: improve cleanup logging 2025-09-01 12:49:55 +02:00
f6cb35acca spec: add obs-staging-bot.service 2025-09-01 12:29:29 +02:00
f4386c3d12 Try to use Staging Master Project as default build target if available
This allows us to set custom build configuration or repository sets for
pull request projects.
2025-09-01 11:52:30 +02:00
f8594af8c6 obs-status: report error on monitor page if error
If we have error with REDIS connection, report it as error 500
on the / default page. Otherwise, report the 404 there instead
as before.
2025-09-01 11:20:54 +02:00
b8ef69a5a7 group-review: react on comment events
Instead of just polling for events, we can use issue_comment events
to process PRs more quickly.

At same time increased default polling interval to 10 minutes if
we use events

Closes #67
2025-08-30 10:41:29 +02:00
c980b9f84d group-review: improve comment made by the bot
Bot name should be expanded for easy copy-pasta
2025-08-29 18:19:03 +02:00
4651440457 Revert "Fixing creation or PR even when we don't want it"
This reverts commit e90ba95869.

We need to assign reviews anyway...
2025-08-29 17:09:08 +02:00
7d58882ed8 Accept review (instead of removal) on no submodule change
Because we require approval by staging bot in the workflow bot.
2025-08-29 15:08:05 +02:00
e90ba95869 Fixing creation or PR even when we don't want it 2025-08-29 15:08:05 +02:00
1015e79026 PR: don't try to update PR if PrjGit only being updated 2025-08-29 14:36:20 +02:00
833cb8b430 PR: marshall config before logging it 2025-08-28 18:13:11 +02:00
a882ae283f PR: workaround lfs errors
in case where files are not in lfs but should be, the checkout
causes files to be modified. Then the checkout of the PR.Head fails.
There should be better way of dealing with this
2025-08-28 16:30:04 +02:00
305e90b254 common: fix logging format string 2025-08-28 13:09:32 +02:00
c80683182d group-review: handle case when not yet reviewed 2025-08-28 10:16:49 +02:00
51cd4da97b group-review: use suggested wording
Closes: #50
2025-08-27 19:27:59 +02:00
cf71fe49d6 group-review: don't spam reviews if already there
Check if review is already in the timeline and don't spam it again

Closes: #51
2025-08-27 19:16:51 +02:00
85a9a81804 Add HuJSON helper 2025-08-27 17:04:48 +02:00
72b979b587 PR: remove closed package PRs from a PRset
This used to happen as a side-effect of a different code path
that was removed in b96b784b38
2025-08-27 14:57:43 +02:00
bb4350519b common: fix invalid log message
Log message complained about request processing even when
it finished request processing.
2025-08-27 14:54:32 +02:00
62658e23a7 PR: quiet submodule deinit output 2025-08-27 14:49:16 +02:00
6a1f92af12 tests: comment out tests that crash 2025-08-27 11:49:26 +02:00
24ed21ce7d tests: fix panics 2025-08-26 23:51:14 +02:00
46a187a60e pr: error format fix 2025-08-26 23:50:48 +02:00
e0c7ea44ea tests: make sure to vendor all the modules 2025-08-26 22:54:54 +02:00
f013180c4b PR: assign reviewers only when not merging 2025-08-26 22:41:37 +02:00
b96b784b38 PR: remove broken code 2025-08-26 19:57:48 +02:00
6864e95404 PR: merge correct branches
Add sanity check that we merge correct branches too
2025-08-26 19:43:51 +02:00
0ba4652595 common: use older git --heads instead of --branches 2025-08-26 19:17:32 +02:00
8d0047649a PR: if we have unpushed commits, update PRset
PRset is used elsewhere and if the pending, unpushed commits
are not part of it, we have an old state
2025-08-26 18:59:38 +02:00
2f180c264e PR: check pending changes, pushed changes 2025-08-26 18:16:42 +02:00
7b87c4fd73 PR: fix parsing of project prs in timeline
Fixes: 933ca9a3db
2025-08-26 17:56:38 +02:00
7d2233dd4a PR: add NoProjectGitPR option 2025-08-26 16:19:56 +02:00
c30ae5750b PR: clone fixes 2025-08-26 15:47:58 +02:00
ea2134c6e9 PR: checkout a commit, for safety - we can't push to non-branch 2025-08-26 13:51:09 +02:00
b22f418595 PR: process with ProjectGit originating from non-local 2025-08-26 13:37:11 +02:00
c4c9a16e7f PR: fix PR parsing with ! 2025-08-26 12:50:21 +02:00
5b1e6941c2 PR: typo in command line 2025-08-26 11:39:52 +02:00
923bcd89db common: timeline items can be null? 2025-08-26 11:36:51 +02:00
e96f4d343b PR: catch panic in PR processing 2025-08-26 11:36:28 +02:00
bcb63fe1e9 Add build status to README 2025-08-25 19:58:37 +02:00
f4e78e53d3 spec: install workflow bots and remove importer
importer is one-off kidn of a program and can't really be run
by itself. It requires git-importer + database + ability to register
to git-obs-bridge which is internal only
2025-08-25 19:54:03 +02:00
082db173f3 vendor: move vendored sources in-tree
This should make it easier to see changes instead of just a blob
2025-08-25 19:48:19 +02:00
7e055c3169 Merge branch 'jzerebecki-fix-pr-link' 2025-08-25 19:12:59 +02:00
7e59e527d8 PR: fix type errors 2025-08-25 18:18:00 +02:00
518845b3d8 importer: dedup maintainer and expand groups 2025-08-25 17:40:38 +02:00
b091e0e98d common: panic if the config is unresoveable
either branch for project config must be defined in the config, OR
it can be fetched as default branch from Gitea. If neither happens,
it's best not to do any guessing here
2025-08-25 17:04:43 +02:00
cedb7c0e76 Add Container files 2025-08-25 13:53:09 +02:00
7209f9f519 update READMEs for workflow bots 2025-08-25 11:32:51 +02:00
bd5482d54e status: use toplevel window for opening links 2025-08-24 19:36:40 +02:00
bc95d50378 [group-review]: Add config options 2025-08-23 13:04:58 +02:00
fff996b497 [group-review]: submitter member of group
submitter cannot be reviewer. Added to the help message

Closes: #59
2025-08-22 17:50:30 +02:00
2b67e6d80e group-review: Add Silent option
Closes: #60
2025-08-22 17:39:29 +02:00
5a875c19a0 PR: handle issues webhooks
These issues have to be associated with a PR. Otherwise processing
is ignored. We need these to handle comments to bot
2025-08-22 16:28:43 +02:00
538698373a common: API can fail... 2025-08-22 15:30:09 +02:00
84b8ca65ce staging: adapt to updated result types 2025-08-22 15:03:02 +02:00
a02358e641 PR: proces PRs on comments too, like "merge ok" 2025-08-22 14:59:24 +02:00
33c9bffc2e Merge messages and handle gitea manual merge race 2025-08-22 13:55:04 +02:00
4894c0d90a mark manual merge instead of relying on Gitea -- delays? 2025-08-22 09:07:34 +02:00
090c291f8a prjgit manual merge check 2025-08-21 17:39:52 +02:00
42cedb6267 Verify that pool is sha256 2025-08-21 17:38:51 +02:00
f7229dfaf9 Merge branch 'main' of src.opensuse.org:adamm/autogits 2025-08-19 17:30:16 +02:00
Jan Zerebecki
933ca9a3db Fix PR link
to use ! instead of # . The later is for issues and only works due to
a redirect, which currently fails in gitea if a repo has its issue
tracker disabled.
2025-08-19 16:27:39 +02:00
390cb89702 import: import SHA1 -> SHA256 repos
Also, always import all files to LFS when exported from scmsync
archives, as more often than not they are forgotten
2025-08-17 19:51:01 +02:00
6cbeaef6f2 import: import SHA1 -> SHA256 repos
Also, always import all files to LFS when exported from scmsync
archives, as more often than not they are forgotten
2025-08-17 19:43:45 +02:00
d146fb8c4e common: add last-updated obs status field 2025-08-13 17:05:47 +02:00
7e78ee83c1 common: fix detection of branches 2025-08-13 17:04:48 +02:00
17e925bfd7 importer: follow scmsync'ed repos HEAD 2025-08-13 16:45:47 +02:00
878df15e58 Merge branch 'main' of src.opensuse.org:adamm/autogits 2025-08-13 12:48:35 +02:00
c84af6286d Fix crash on connection
Setting channel object in Rabbit listener object.
2025-08-12 11:29:25 +02:00
d2cbb8fd34 importer: rework according to updated git-importer 2025-08-12 10:38:50 +02:00
8436a49c5d br: build results as svg for packages 2025-08-05 16:08:52 +02:00
106e36d6bf importer: use -packages instead of -package
Improve docs to allow multiple packages specified and how
2025-07-29 13:19:39 +02:00
0ec4986163 importer: continue processing repos ...
continue vs. break issue
2025-07-29 13:16:43 +02:00
fb7f6adc98 importer: allow multiple packages in the -package param 2025-07-28 20:07:07 +02:00
231f29b065 Merge remote-tracking branch 'gitea/main' 2025-07-28 14:04:31 +02:00
3f3645a453 importer: remove branches when exist
Don't generate errors on imports that we ignore. Problem is this
slows donw the import
2025-07-28 14:03:20 +02:00
42e2713cd8 Merge remote-tracking branch 'gitea/main' 2025-07-26 13:56:16 +02:00
3d24dce5c0 common: rabbit refactor
Generalize interface to allow processing of any events, not just
Gitea events.
2025-07-26 13:54:51 +02:00
0cefb45d8a allow imports of + in reponames 2025-07-25 14:57:13 +02:00
ddbb824006 group-review: fix group review approval and disapproval
and add unit tests for this
2025-07-25 13:54:30 +02:00
69dac4ec31 common: fix manifest path when pkg is path 2025-07-18 23:02:03 +02:00
b7e03ab465 common: use standard function for Basenamej 2025-07-18 20:41:57 +02:00
76aec3aabb PR: PrjGit description generation in one place
This allows for easier editing and for guidance of what will
happen next
2025-07-18 16:26:35 +02:00
19fb7e277b importer: case when OBS package name != repo name
also handle just one package import, for testing
2025-07-18 16:21:52 +02:00
51261f1bc1 PR: Add manifest to subdir mapping functions 2025-07-18 15:54:53 +02:00
949810709d import: handle previusly clones scmsync repos 2025-07-17 16:43:53 +02:00
c012570e89 importer: map packages to Gitea names 2025-07-16 21:28:26 +02:00
44a3b15a7d Merge pull request 'gitea_status_proxy' (#56) from ldragon/autogits:proxy into main
Reviewed-on: adamm/autogits#56
Reviewed-by: Adam Majer <adamm@noreply.src.opensuse.org>
2025-07-16 12:44:48 +02:00
c5db1c83a7 PR: detect and rebase project git commits
When project is advanced, and we have other package changes
to same project, the project git changes need to be rebased. The
simplest way of doing this is to skip all the submodule conflicts
and re-create them. This allows the submodules changes to be
mergeable again.
2025-07-15 19:08:05 +02:00
9f0909621b PR: fix timeline fetches
only fetch latest reviews from a user, not all
2025-07-15 11:06:17 +02:00
b3914b04bd Fix logic in crash protection
We must not access review.User object if it is nil
2025-07-11 12:02:37 +02:00
b43a19189e Enable code stream publishing 2025-07-11 12:02:08 +02:00
01b665230e message typo 2025-07-11 12:01:58 +02:00
1a07d4c541 Create Pull Requests to specified branches
instead of always using DefaultBranch. This means that target needs
always gets specified now.
2025-07-11 12:01:43 +02:00
22e44dff47 Don't fail on project git pull request creation. 2025-07-11 12:01:24 +02:00
f9021d08b9 PR: fix case where submodule cannot be initialized
Sometimes the commit is already cleaned up and Project Git cannot
be initialized. This should not be an error. Only fatal error
is if we can't update the PR to current state.
2025-07-10 18:28:09 +02:00
7a0394e51b PR: use "open" not "opened" as state 2025-07-10 16:54:28 +02:00
518bc15696 PR: close empty prjgit PRs 2025-07-09 20:39:38 +02:00
51873eb048 PR: log prjgit PrjGit creator 2025-07-09 20:06:13 +02:00
4f33ce979c PR: use MergeBase as ref. branch for prjgit
The target branch can be moving target, so not appropriate
2025-07-09 19:42:26 +02:00
7cc4db2283 common: prune removed remote branches
During a repository update, we need to remove branches that
no longer exist on remote from local cache.
2025-07-09 18:28:37 +02:00
4d9e2f8cab PR: update PrjGit PR when package PRs are removed or added 2025-07-09 18:05:05 +02:00
ed4f27a19e PR: refactor 2025-07-09 17:33:44 +02:00
e438b5b064 common: fix parsing of submodule commit id from tree object 2025-06-26 14:25:20 +02:00
885bb7e537 forward: fix logic
* fix approval/request changes string
* use common.DevelProject fetcher code
* fix parsing of Requests meta
2025-06-26 14:24:21 +02:00
977d75f6e9 reviews: only react to comment
also, reviews are reverse sorted.
fixed some bugs
2025-06-25 16:13:08 +02:00
42a9ee48e0 import: update config files 2025-06-24 16:03:33 +02:00
9333e5c3da PR: fix README quoting 2025-06-24 14:33:06 +02:00
5e29c88dc8 PR: fix README quoting 2025-06-24 14:32:23 +02:00
4f0f101620 importer: handle case of devel project in git 2025-06-23 18:48:09 +02:00
253f009da3 common: Add devel project query 2025-06-23 18:47:12 +02:00
5e66a14fa9 forward-bot: finish initial braindump 2025-06-17 23:39:47 +02:00
e79122e494 forward-bot: additional first code 2025-06-17 19:27:00 +02:00
0b4b1a4e21 common: Add basic OBS request APIs 2025-06-17 19:24:13 +02:00
0019546e30 forward-bot: initial skeleton 2025-06-17 00:46:26 +02:00
6438a8625a Replace PrjGit creation logic 2025-06-16 14:22:21 +02:00
3928fa6429 PR: use config project git branch, not default 2025-06-13 00:06:02 +02:00
e92ac4a592 PR: refactor 2025-06-12 23:51:04 +02:00
a1520ebfb0 PR: PRSet consistency check 2025-06-12 18:44:16 +02:00
c8d65a3ae5 PR: refactor
Move AssociatedPR fetching
2025-06-11 16:28:02 +02:00
b849a72f31 PR: request optional reviews
Ignore these reviews in approval, for otherwise they can be used
to fetch optional review information
2025-06-10 18:48:42 +02:00
568a2f3df8 PR: Add ability to parse optional reviewers
Document reviewer syntax in the Readme.md
2025-06-10 17:20:33 +02:00
30c8b2fe57 PR: require PRs to be in opened state
PR's that are not opened (eg. closed, or merged) cannot be part of
a consistent PRset. Either everything is merged, or everything should
be opened.
2025-06-10 16:31:44 +02:00
69b0f9a5ed PR: fix error logging 2025-06-10 15:59:07 +02:00
a283d4f26f PR: no submitter reviews needed 2025-06-07 21:52:47 +02:00
af898a6b8d pr: manual project only merge ok is manual merge ok 2025-06-07 21:42:11 +02:00
b89cdb7664 PR: fix parsing comments from timeline 2025-06-05 19:15:53 +02:00
d37bfaa9d3 common: workaround case when user do not have gitea accounts and cannot get reviews assigned 2025-06-04 14:59:46 +02:00
90cca05b31 common: fix maintainership parsing when no maintienrs explicitly set 2025-06-04 13:56:04 +02:00
7c229500c1 common: debug logging 2025-06-03 23:46:53 +02:00
290424c4a7 common: sort timeline in desc order 2025-06-03 23:42:02 +02:00
703fa101a4 group-review: fix crash in notification handling when no config 2025-06-03 17:48:09 +02:00
66e4982e2d group-review: fix build 2025-06-03 16:59:46 +02:00
09b1c415dd PR: fix deadlock in verification routines via git/org locking 2025-06-03 16:18:00 +02:00
629b941558 PR: use correct path for local repo cache 2025-06-03 14:13:58 +02:00
aa50481c00 PR: add test for unauthorized merge reviews 2025-06-03 10:48:17 +02:00
bc714ee22d PR: fix build 2025-06-03 10:40:49 +02:00
b8cc0357a7 PR: limit manual merge to Projects
Add "ManualMergeProject" to require "merge ok" sign-offs on
project level only
2025-06-03 00:07:34 +02:00
aed0ac3ee9 PR: allow maintainers to approve merges by default 2025-06-02 23:54:05 +02:00
cca3575596 PR: add "merge ok" manual merge option 2025-06-02 16:22:50 +02:00
69dcebcf74 common: use Timeline for reviews
Gitea doesn't keep track of Stale reviews well. We should parse
Timeline of a PR *always* and apply our own logic to this instead
2025-05-30 16:51:30 +02:00
e5d07f0ce6 refactor to use net/http 2025-05-30 14:43:47 +05:30
df9478a920 gitea status proxy 2025-05-28 11:20:09 +05:30
7da9daddd5 direct: fix error formatting element 2025-05-27 12:33:51 +02:00
cd0c3bc759 common: fix tests 2025-05-27 12:11:21 +02:00
af096af507 pr: require manual merge options for repositories 2025-05-26 18:10:25 +02:00
d150c66427 common: update gitea APIs 2025-05-26 16:55:15 +02:00
3bef967023 wip 2025-05-16 17:57:02 +02:00
9c3658b33e pr: remove pending requests
Remove all pending review requests when we merge
2025-05-13 18:34:56 +02:00
6968cbc942 group-review: use URL and not hardcode amqps for rabbit 2025-05-13 16:43:16 +02:00
2cb7a065a9 common: extract timeline fetcher to common code 2025-05-13 15:32:38 +02:00
35058623a7 group-review: logic fixes
* Only look at reviews after last update or review request
* Re-request reviews if they are needed
* Use timeline to filter reviews
* Ignore reviews not associated with the group name

Issue: adamm/autogits#28
2025-05-13 14:53:10 +02:00
24fe165c46 reviews: use timeline and ignore reviews prior to last push 2025-05-12 19:44:10 +02:00
1498438fee pr: fix fetching for merging 2025-05-10 16:48:06 +02:00
4653904ded pr: merge - preliminary fixes 2025-05-09 17:28:35 +02:00
bd87bf8ce3 staging: reviewer can be nil
If a user is requested reviewer, but is then deleted in Gitea,
it is still there but as "nil" user that doesn't resolve.
2025-05-09 16:55:16 +02:00
364c3f4ab7 staging: fix logging and cache stale, cleaned up repos 2025-05-08 15:55:27 +02:00
fd8b7f1bee staging: add cleaned up notification cache 2025-05-08 14:49:46 +02:00
da32adb16b staging: cleanup logic
Add cleanup logic for finished requests

Merged PRs are immediatelly removed along with any QA subprojects
Unmerged closed PRs are removed after a day, default 48 hours
since closing.
2025-05-08 13:56:31 +02:00
1b5a0ad0c8 common: default cleanup delay is 48 for unmerged PRs 2025-05-08 13:56:13 +02:00
e78fdf4a09 common: set cookies when availalbe, not just 200 res code 2025-05-08 13:55:31 +02:00
0564a50fb5 remove debug code in OBS client 2025-05-08 13:24:20 +02:00
4f7db36123 handle build results different when request with lastbuild=1
In that case we need to

 * ignore repo state as it is the current one. There is no last state
 * handle "unkown" state as finished as the package was never attempted,
   but we don't know the reason (eg. broken source or unresolvable)
2025-05-08 10:49:09 +02:00
41d536ea1b common: fix parsing commit messages 2025-05-08 10:42:33 +02:00
91d915cc28 Drop release targets in pull request projects 2025-05-08 10:42:03 +02:00
c7a300119e Fix QA project setup handling 2025-05-08 10:41:30 +02:00
c5c3e1c115 Implement detection for local repositories
Repositories which build against another repo in the same project need
to do so also in the forked project. This is eg for consuming rpms
from one repo in an image build from same project.
2025-05-08 10:28:38 +02:00
c93788d0ee pr: fixes 2025-05-07 16:10:16 +02:00
1e46f8d0ab common: fix tests 2025-05-07 13:41:59 +02:00
9963ae90ef common: fix tests 2025-05-07 12:45:26 +02:00
a9225bbd76 Merge branch 'refactor' into wip 2025-05-07 12:38:19 +02:00
801fff6e22 common: fix parsing commit messages 2025-05-07 12:31:11 +02:00
b4b0d075be staging: only mark as read when processing is done 2025-05-07 01:08:32 +02:00
16c2eb7090 staging fixes 2025-05-07 00:25:44 +02:00
3264ad1589 staging: status line requires write repo access 2025-05-07 00:05:57 +02:00
cb64635aea pr: use correct prjgit repo name 2025-05-06 23:59:51 +02:00
aeb4c20744 pr: reset submodules if they not agreed 2025-05-06 23:15:27 +02:00
da1df24666 wip 2025-05-06 18:06:04 +02:00
6b3c613f14 wip 2025-05-05 18:57:05 +02:00
eb997e1ae9 common: fix dynamic listening for events 2025-05-05 15:33:20 +02:00
f52d72e04a staging: use status line in PRs 2025-05-05 13:52:46 +02:00
832 changed files with 177517 additions and 3364 deletions

View File

@@ -0,0 +1,33 @@
name: go-generate-check
on:
push:
branches: ['main']
paths:
- '**.go'
- '**.mod'
- '**.sum'
pull_request:
paths:
- '**.go'
- '**.mod'
- '**.sum'
workflow_dispatch:
jobs:
go-generate-check:
name: go-generate-check
container:
image: registry.opensuse.org/devel/factory/git-workflow/containers/opensuse/bci/golang-extended:latest
steps:
- run: git clone --no-checkout --depth 1 ${{ gitea.server_url }}/${{ gitea.repository }} .
- run: git fetch origin ${{ gitea.ref }}
- run: git checkout FETCH_HEAD
- run: go generate -C common
- run: go generate -C workflow-pr
- run: git add -N .; git diff
- run: |
status=$(git status --short)
if [[ -n "$status" ]]; then
echo -e "$status"
echo "Please commit the differences from running: go generate"
false
fi

View File

@@ -0,0 +1,24 @@
name: go-generate-push
on:
workflow_dispatch:
jobs:
go-generate-push:
name: go-generate-push
container:
image: registry.opensuse.org/devel/factory/git-workflow/containers/opensuse/bci/golang-extended:latest
steps:
- run: git clone --no-checkout --depth 1 ${{ gitea.server_url }}/${{ gitea.repository }} .
- run: git fetch origin ${{ gitea.ref }}
- run: git checkout FETCH_HEAD
- run: go generate -C common
- run: go generate -C workflow-pr
- run: |
host=${{ gitea.server_url }}
host=${host#https://}
echo $host
git remote set-url origin "https://x-access-token:${{ secrets.GITEA_TOKEN }}@$host/${{ gitea.repository }}"
git config user.name "Gitea Actions"
git config user.email "gitea_noreply@opensuse.org"
- run: 'git status --short; git status --porcelain=2|grep --quiet -v . || ( git add .;git commit -m "CI run result of: go generate"; git push origin HEAD:${{ gitea.ref }} )'
- run: git log -p FETCH_HEAD...HEAD
- run: git log --numstat FETCH_HEAD...HEAD

View File

@@ -0,0 +1,33 @@
name: go-vendor-check
on:
push:
branches: ['main']
paths:
- '**.mod'
- '**.sum'
pull_request:
paths:
- '**.mod'
- '**.sum'
workflow_dispatch:
jobs:
go-generate-check:
name: go-vendor-check
container:
image: registry.opensuse.org/devel/factory/git-workflow/containers/opensuse/bci/golang-extended:latest
steps:
- run: git clone --no-checkout --depth 1 ${{ gitea.server_url }}/${{ gitea.repository }} .
- run: git fetch origin ${{ gitea.ref }}
- run: git checkout FETCH_HEAD
- run: go mod download
- run: go mod vendor
- run: go mod verify
- run: git add -N .; git diff
- run: go mod tidy -diff || true
- run: |
status=$(git status --short)
if [[ -n "$status" ]]; then
echo -e "$status"
echo "Please commit the differences from running: go generate"
false
fi

View File

@@ -0,0 +1,26 @@
name: go-generate-push
on:
workflow_dispatch:
jobs:
go-generate-push:
name: go-generate-push
container:
image: registry.opensuse.org/devel/factory/git-workflow/containers/opensuse/bci/golang-extended:latest
steps:
- run: git clone --no-checkout --depth 1 ${{ gitea.server_url }}/${{ gitea.repository }} .
- run: git fetch origin ${{ gitea.ref }}
- run: git checkout FETCH_HEAD
- run: go mod download
- run: go mod vendor
- run: go mod verify
- run: |
host=${{ gitea.server_url }}
host=${host#https://}
echo $host
git remote set-url origin "https://x-access-token:${{ secrets.GITEA_TOKEN }}@$host/${{ gitea.repository }}"
git config user.name "Gitea Actions"
git config user.email "gitea_noreply@opensuse.org"
- run: 'git status --short; git status --porcelain=2|grep --quiet -v . || ( git add .;git commit -m "CI run result of: go mod vendor"; git push origin HEAD:${{ gitea.ref }} )'
- run: go mod tidy -diff || true
- run: git log -p FETCH_HEAD...HEAD
- run: git log --numstat FETCH_HEAD...HEAD

5
.gitignore vendored
View File

@@ -1,5 +1,2 @@
mock
node_modules
*.obscpio
autogits-tmp.tar.zst
*.osc
*.conf

View File

@@ -5,11 +5,15 @@ The bots that drive Git Workflow for package management
* devel-importer -- helper to import an OBS devel project into a Gitea organization
* gitea-events-rabbitmq-publisher -- takes all events from a Gitea organization (webhook) and publishes it on a RabbitMQ instance
* gitea-status-proxy -- allows bots without code owner permission to set Gitea's commit status
* group-review -- group review proxy
* hujson -- translates JWCC (json with commas and comments) to Standard JSON
* obs-forward-bot -- forwards PR as OBS sr (TODO)
* obs-staging-bot -- build bot for a PR
* obs-status-service -- report build status of an OBS project as an SVG
* workflow-pr -- keeps PR to _ObsPrj consistent with a PR to a package update
* workflow-direct -- update _ObsPrj based on direct pushes and repo creations/removals from organization
* staging-utils -- review tooling for PR
* staging-utils -- review tooling for PR (TODO)
- list PR
- merge PR
- split PR
@@ -19,7 +23,18 @@ The bots that drive Git Workflow for package management
Bugs
----
Report bugs to issue tracker at https://src.opensuse.org/adamm/autogits
Report bugs to issue tracker at https://src.opensuse.org/git-workflow/autogits
Build Status
------------
Devel project build status (`main` branch):
![devel:Factory:git-workflow](https://br.opensuse.org/status/devel:Factory:git-workflow/autogits)
`staging` branch build status:
![Staging Build Status](https://br.opensuse.org/status/home:adamm:autogits/autogits)

View File

@@ -1,15 +0,0 @@
<services>
<!-- workaround, go_modules needs a tar and obs_scm doesn't take file://. -->
<service name="roast" mode="manual">
<param name="target">.</param>
<param name="reproducible">true</param>
<param name="outfile">autogits-tmp.tar.zst</param>
<param name="exclude">autogits-tmp.tar.zst</param>
</service>
<service name="go_modules" mode="manual">
<param name="basename">./</param>
<param name="compression">zst</param>
<param name="vendorname">vendor</param>
</service>
</services>

View File

@@ -17,15 +17,14 @@
Name: autogits
Version: 0
Version: 1
Release: 0
Summary: GitWorkflow utilities
License: GPL-2.0-or-later
URL: https://src.opensuse.org/adamm/autogits
Source1: vendor.tar.zst
BuildRequires: golang-packaging
BuildRequires: git
BuildRequires: systemd-rpm-macros
BuildRequires: zstd
BuildRequires: go
%{?systemd_ordering}
%description
@@ -33,160 +32,268 @@ Git Workflow tooling and utilities enabling automated handing of OBS projects
as git repositories
%package -n gitea-events-rabbitmq-publisher
%package devel-importer
Summary: Imports devel projects from obs to git
%description -n autogits-devel-importer
Command-line tool to import devel projects from obs to git
%package doc
Summary: Common documentation files
BuildArch: noarch
%description -n autogits-doc
Common documentation files
%package gitea-events-rabbitmq-publisher
Summary: Publishes Gitea webhook data via RabbitMQ
%description -n gitea-events-rabbitmq-publisher
%description gitea-events-rabbitmq-publisher
Listens on an HTTP socket and publishes Gitea events on a RabbitMQ instance
with a topic
<scope>.src.$organization.$webhook_type.[$webhook_action_type]
%package -n doc
Summary: Common documentation files
%package gitea-status-proxy
Summary: Proxy for setting commit status in Gitea
%description -n doc
Common documentation files
%description gitea-status-proxy
Setting commit status requires code write access token. This proxy
is middleware that delegates status setting without access to other APIs
%package -n devel-importer
Summary: Imports devel projects from obs to git
%description -n devel-importer
Command-line tool to import devel projects from obs to git
%package -n group-review
%package group-review
Summary: Reviews of groups defined in ProjectGit
%description -n group-review
%description group-review
Is used to handle reviews associated with groups defined in the
ProjectGit.
%package -n obs-staging-bot
%package obs-forward-bot
Summary: obs-forward-bot
%description obs-forward-bot
%package obs-staging-bot
Summary: Build a PR against a ProjectGit, if review is requested
%description -n obs-staging-bot
%description obs-staging-bot
Build a PR against a ProjectGit, if review is requested.
%package -n obs-status-service
%package obs-status-service
Summary: Reports build status of OBS service as an easily to produce SVG
%description -n obs-status-service
%description obs-status-service
Reports build status of OBS service as an easily to produce SVG
%package -n workflow-direct
Summary: Keep ProjectGit in sync for a devel project
%package utils
Summary: HuJSON to JSON parser
Provides: hujson
Provides: /usr/bin/hujson
%description -n workflow-direct
%description utils
HuJSON to JSON parser, using stdin -> stdout pipe
%package workflow-direct
Summary: Keep ProjectGit in sync for a devel project
Requires: openssh-clients
Requires: git-core
%description workflow-direct
Keep ProjectGit in sync with packages in the organization of a devel project
%package -n workflow-pr
%package workflow-pr
Summary: Keeps ProjectGit PR in-sync with a PackageGit PR
Requires: openssh-clients
Requires: git-core
%description -n workflow-pr
%description workflow-pr
Keeps ProjectGit PR in-sync with a PackageGit PR
%prep
cp -r /home/abuild/rpmbuild/SOURCES/* ./
tar x --zstd -f %{SOURCE1}
%build
go build \
-C gitea-events-rabbitmq-publisher \
-mod=vendor \
-C devel-importer \
-buildmode=pie
go build \
-C devel-importer \
-mod=vendor \
-C utils/hujson \
-buildmode=pie
go build \
-C gitea-events-rabbitmq-publisher \
-buildmode=pie
go build \
-C gitea_status_proxy \
-buildmode=pie
go build \
-C group-review \
-mod=vendor \
-buildmode=pie
go build \
-C obs-forward-bot \
-buildmode=pie
go build \
-C obs-staging-bot \
-mod=vendor \
-buildmode=pie
go build \
-C obs-status-service \
-mod=vendor \
-buildmode=pie
#go build \
# -C workflow-direct \
# -mod=vendor \
# -buildmode=pie
#go build \
# -C workflow-pr \
# -mod=vendor \
# -buildmode=pie
go build \
-C workflow-direct \
-buildmode=pie
go build \
-C workflow-pr \
-buildmode=pie
%check
go test -C common -v
go test -C group-review -v
go test -C obs-staging-bot -v
go test -C obs-status-service -v
go test -C workflow-direct -v
# TODO build fails
#go test -C workflow-pr -v
%install
install -D -m0755 devel-importer/devel-importer %{buildroot}%{_bindir}/devel-importer
install -D -m0755 gitea-events-rabbitmq-publisher/gitea-events-rabbitmq-publisher %{buildroot}%{_bindir}/gitea-events-rabbitmq-publisher
install -D -m0644 systemd/gitea-events-rabbitmq-publisher.service %{buildroot}%{_unitdir}/gitea-events-rabbitmq-publisher.service
install -D -m0755 devel-importer/devel-importer %{buildroot}%{_bindir}/devel-importer
install -D -m0755 gitea_status_proxy/gitea_status_proxy %{buildroot}%{_bindir}/gitea_status_proxy
install -D -m0755 group-review/group-review %{buildroot}%{_bindir}/group-review
install -D -m0644 systemd/group-review@.service %{buildroot}%{_unitdir}/group-review@.service
install -D -m0755 obs-forward-bot/obs-forward-bot %{buildroot}%{_bindir}/obs-forward-bot
install -D -m0755 obs-staging-bot/obs-staging-bot %{buildroot}%{_bindir}/obs-staging-bot
install -D -m0644 systemd/obs-staging-bot.service %{buildroot}%{_unitdir}/obs-staging-bot.service
install -D -m0755 obs-status-service/obs-status-service %{buildroot}%{_bindir}/obs-status-service
#install -D -m0755 workflow-direct/workflow-direct %{buildroot}%{_bindir}/workflow-direct
#install -D -m0755 workflow-pr/workflow-pr %{buildroot}%{_bindir}/workflow-pr
install -D -m0644 systemd/obs-status-service.service %{buildroot}%{_unitdir}/obs-status-service.service
install -D -m0755 workflow-direct/workflow-direct %{buildroot}%{_bindir}/workflow-direct
install -D -m0644 systemd/workflow-direct@.service %{buildroot}%{_unitdir}/workflow-direct@.service
install -D -m0755 workflow-pr/workflow-pr %{buildroot}%{_bindir}/workflow-pr
install -D -m0755 utils/hujson/hujson %{buildroot}%{_bindir}/hujson
%pre -n gitea-events-rabbitmq-publisher
%pre gitea-events-rabbitmq-publisher
%service_add_pre gitea-events-rabbitmq-publisher.service
%post -n gitea-events-rabbitmq-publisher
%post gitea-events-rabbitmq-publisher
%service_add_post gitea-events-rabbitmq-publisher.service
%preun -n gitea-events-rabbitmq-publisher
%preun gitea-events-rabbitmq-publisher
%service_del_preun gitea-events-rabbitmq-publisher.service
%postun -n gitea-events-rabbitmq-publisher
%postun gitea-events-rabbitmq-publisher
%service_del_postun gitea-events-rabbitmq-publisher.service
%files -n gitea-events-rabbitmq-publisher
%pre group-review
%service_add_pre group-review@.service
%post group-review
%service_add_post group-review@.service
%preun group-review
%service_del_preun group-review@.service
%postun group-review
%service_del_postun group-review@.service
%pre obs-staging-bot
%service_add_pre obs-staging-bot.service
%post obs-staging-bot
%service_add_post obs-staging-bot.service
%preun obs-staging-bot
%service_del_preun obs-staging-bot.service
%postun obs-staging-bot
%service_del_postun obs-staging-bot.service
%pre obs-status-service
%service_add_pre obs-status-service.service
%post obs-status-service
%service_add_post obs-status-service.service
%preun obs-status-service
%service_del_preun obs-status-service.service
%postun obs-status-service
%service_del_postun obs-status-service.service
%pre workflow-pr
%service_add_pre workflow-direct@.service
%post workflow-pr
%service_add_post workflow-direct@.service
%preun workflow-pr
%service_del_preun workflow-direct@.service
%postun workflow-pr
%service_del_postun workflow-direct@.service
%files devel-importer
%license COPYING
%doc devel-importer/README.md
%{_bindir}/devel-importer
%files doc
%license COPYING
%doc doc/README.md
%doc doc/workflows.md
%files gitea-events-rabbitmq-publisher
%license COPYING
%doc gitea-events-rabbitmq-publisher/README.md
%{_bindir}/gitea-events-rabbitmq-publisher
%{_unitdir}/gitea-events-rabbitmq-publisher.service
%files -n doc
%files gitea-status-proxy
%license COPYING
%doc doc/README.md
%doc doc/workflows.md
%{_bindir}/gitea_status_proxy
%files -n devel-importer
%license COPYING
%doc devel-importer/README.md
%{_bindir}/devel-importer
%files -n group-review
%files group-review
%license COPYING
%doc group-review/README.md
%{_bindir}/group-review
%{_unitdir}/group-review@.service
%files -n obs-staging-bot
%files obs-forward-bot
%license COPYING
%{_bindir}/obs-forward-bot
%files obs-staging-bot
%license COPYING
%doc obs-staging-bot/README.md
%{_bindir}/obs-staging-bot
%{_unitdir}/obs-staging-bot.service
%files -n obs-status-service
%files obs-status-service
%license COPYING
%doc obs-status-service/README.md
%{_bindir}/obs-status-service
%{_unitdir}/obs-status-service.service
%files -n workflow-direct
%files utils
%license COPYING
%{_bindir}/hujson
%files workflow-direct
%license COPYING
%doc workflow-direct/README.md
#%{_bindir}/workflow-direct
%{_bindir}/workflow-direct
%{_unitdir}/workflow-direct@.service
%files -n workflow-pr
%files workflow-pr
%license COPYING
%doc workflow-pr/README.md
#%{_bindir}/workflow-pr
%{_bindir}/workflow-pr

View File

@@ -1,13 +1,15 @@
all: build
api.json:
api.json::
curl -o api.json https://src.opensuse.org/swagger.v1.json
gitea-generated/client/gitea_api_client.go:: api.json
gitea-generated/client/gitea_api_client.go: api.json
[ -d gitea-generated ] || mkdir gitea-generated
podman run --rm -v $$(pwd):/api ghcr.io/go-swagger/go-swagger generate client -f /api/api.json -t /api/gitea-generated
podman run --rm -v $$(pwd)/..:/api ghcr.io/go-swagger/go-swagger generate client -f /api/common/api.json -t /api/common/gitea-generated
api: gitea-generated/client/gitea_api_client.go mock_gitea_utils.go
swagger: gitea-generated/client/gitea_api_client.go
api:
go generate
build: api

File diff suppressed because it is too large Load Diff

View File

@@ -11,14 +11,14 @@ import (
"strings"
)
const PrPattern = "PR: %s/%s#%d"
const PrPattern = "PR: %s/%s!%d"
type BasicPR struct {
Org, Repo string
Num int64
}
var validOrgAndRepoRx *regexp.Regexp = regexp.MustCompile("^[A-Za-z0-9_-]+$")
var validOrgAndRepoRx *regexp.Regexp = regexp.MustCompile("^[A-Za-z0-9_\\.-]+$")
func parsePrLine(line string) (BasicPR, error) {
var ret BasicPR
@@ -36,10 +36,14 @@ func parsePrLine(line string) (BasicPR, error) {
return ret, errors.New("missing / separator")
}
repo := strings.SplitN(org[1], "#", 2)
repo := strings.SplitN(org[1], "!", 2)
ret.Repo = repo[0]
if len(repo) != 2 {
return ret, errors.New("Missing # separator")
repo = strings.SplitN(org[1], "#", 2)
ret.Repo = repo[0]
}
if len(repo) != 2 {
return ret, errors.New("Missing ! or # separator")
}
// Gitea requires that each org and repo be [A-Za-z0-9_-]+

View File

@@ -14,6 +14,7 @@ func newStringScanner(s string) *bufio.Scanner {
}
func TestAssociatedPRScanner(t *testing.T) {
common.SetTestLogger(t)
testTable := []struct {
name string
input string
@@ -34,7 +35,7 @@ func TestAssociatedPRScanner(t *testing.T) {
},
{
"Multiple PRs",
"Some header of the issue\n\nFollowed by some description\nPR: test/foo#4\n\nPR: test/goo#5\n",
"Some header of the issue\n\nFollowed by some description\nPR: test/foo#4\n\nPR: test/goo!5\n",
[]common.BasicPR{
{Org: "test", Repo: "foo", Num: 4},
{Org: "test", Repo: "goo", Num: 5},
@@ -95,6 +96,7 @@ func TestAssociatedPRScanner(t *testing.T) {
}
func TestAppendingPRsToDescription(t *testing.T) {
common.SetTestLogger(t)
testTable := []struct {
name string
desc string
@@ -107,7 +109,7 @@ func TestAppendingPRsToDescription(t *testing.T) {
[]common.BasicPR{
{Org: "a", Repo: "b", Num: 100},
},
"something\n\nPR: a/b#100",
"something\n\nPR: a/b!100",
},
{
"Append multiple PR to end of description",
@@ -119,7 +121,7 @@ func TestAppendingPRsToDescription(t *testing.T) {
{Org: "b", Repo: "b", Num: 100},
{Org: "c", Repo: "b", Num: 100},
},
"something\n\nPR: a1/b#100\nPR: a1/c#100\nPR: a1/c#101\nPR: b/b#100\nPR: c/b#100",
"something\n\nPR: a1/b!100\nPR: a1/c!100\nPR: a1/c!101\nPR: b/b!100\nPR: c/b!100",
},
{
"Append multiple sorted PR to end of description and remove dups",
@@ -133,7 +135,7 @@ func TestAppendingPRsToDescription(t *testing.T) {
{Org: "a1", Repo: "c", Num: 101},
{Org: "a1", Repo: "b", Num: 100},
},
"something\n\nPR: a1/b#100\nPR: a1/c#100\nPR: a1/c#101\nPR: b/b#100\nPR: c/b#100",
"something\n\nPR: a1/b!100\nPR: a1/c!100\nPR: a1/c!101\nPR: b/b!100\nPR: c/b!100",
},
}

View File

@@ -25,6 +25,7 @@ import (
"io"
"log"
"os"
"slices"
"strings"
"github.com/tailscale/hujson"
@@ -35,6 +36,9 @@ import (
const (
ProjectConfigFile = "workflow.config"
StagingConfigFile = "staging.config"
Permission_ForceMerge = "force-merge"
Permission_Group = "release-engineering"
)
type ConfigFile struct {
@@ -43,21 +47,53 @@ type ConfigFile struct {
type ReviewGroup struct {
Name string
Silent bool // will not request reviews from group members
Reviewers []string
}
type QAConfig struct {
Name string
Origin string
BuildDisableRepos []string // which repos to build disable in the new project
}
type Permissions struct {
Permission string
Members []string
}
const (
Label_StagingAuto = "staging/Auto"
Label_ReviewPending = "review/Pending"
Label_ReviewDone = "review/Done"
Label_NewRepository = "new/New Repository"
)
func LabelKey(tag_value string) string {
// capitalize first letter and remove /
if len(tag_value) == 0 {
return ""
}
return strings.ToUpper(tag_value[0:1]) + strings.ReplaceAll(tag_value[1:], "/", "")
}
type AutogitConfig struct {
Workflows []string // [pr, direct, test]
Organization string
GitProjectName string // Organization/GitProjectName.git is PrjGit
Branch string // branch name of PkgGit that aligns with PrjGit submodules
Reviewers []string // only used by `pr` workflow
ReviewGroups []ReviewGroup
GitProjectName string // Organization/GitProjectName.git is PrjGit
Branch string // branch name of PkgGit that aligns with PrjGit submodules
Reviewers []string // only used by `pr` workflow
Permissions []*Permissions // only used by `pr` workflow
ReviewGroups []*ReviewGroup
Committers []string // group in addition to Reviewers and Maintainers that can order the bot around, mostly as helper for factory-maintainers
Subdirs []string // list of directories to sort submodules into. Needed b/c _manifest cannot list non-existent directories
Labels map[string]string // list of tags, if not default, to apply
NoProjectGitPR bool // do not automatically create project git PRs, just assign reviewers and assume somethign else creates the ProjectGit PR
ManualMergeOnly bool // only merge with "Merge OK" comment by Project Maintainers and/or Package Maintainers and/or reviewers
ManualMergeProject bool // require merge of ProjectGit PRs with "Merge OK" by ProjectMaintainers and/or reviewers
ReviewRequired bool // always require a maintainer review, even if maintainer submits it. Only ignored if no other package or project reviewers
}
type AutogitConfigs []*AutogitConfig
@@ -95,7 +131,7 @@ type GiteaFileContentAndRepoFetcher interface {
GiteaRepoFetcher
}
func PartiallyParseWorkflowConfig(data []byte) (*AutogitConfig, error) {
func UnmarshalWorkflowConfig(data []byte) (*AutogitConfig, error) {
var config AutogitConfig
data, err := hujson.Standardize(data)
if err != nil {
@@ -130,7 +166,7 @@ func ReadWorkflowConfig(gitea GiteaFileContentAndRepoFetcher, git_project string
return nil, fmt.Errorf("Error fetching 'workflow.config' for %s/%s#%s: %w", a[0], prjGitRepo, branch, err)
}
config, err := PartiallyParseWorkflowConfig(data)
config, err := UnmarshalWorkflowConfig(data)
if err != nil {
return nil, err
}
@@ -171,6 +207,8 @@ func (configs AutogitConfigs) GetPrjGitConfig(org, repo, branch string) *Autogit
if c.GitProjectName == prjgit {
return c
}
}
for _, c := range configs {
if c.Organization == org && c.Branch == branch {
return c
}
@@ -179,6 +217,27 @@ func (configs AutogitConfigs) GetPrjGitConfig(org, repo, branch string) *Autogit
return nil
}
func (config *AutogitConfig) HasPermission(user, permission string) bool {
if config == nil {
return false
}
for _, p := range config.Permissions {
if p.Permission == permission {
if slices.Contains(p.Members, user) {
return true
}
for _, m := range p.Members {
if members, err := config.GetReviewGroupMembers(m); err == nil && slices.Contains(members, user) {
return true
}
}
}
}
return false
}
func (config *AutogitConfig) GetReviewGroupMembers(reviewer string) ([]string, error) {
for _, g := range config.ReviewGroups {
if g.Name == reviewer {
@@ -189,10 +248,19 @@ func (config *AutogitConfig) GetReviewGroupMembers(reviewer string) ([]string, e
return nil, errors.New("User " + reviewer + " not found as group reviewer for " + config.GitProjectName)
}
func (config *AutogitConfig) GetReviewGroup(reviewer string) (*ReviewGroup, error) {
for _, g := range config.ReviewGroups {
if g.Name == reviewer {
return g, nil
}
}
return nil, errors.New("User " + reviewer + " not found as group reviewer for " + config.GitProjectName)
}
func (config *AutogitConfig) GetPrjGit() (string, string, string) {
org := config.Organization
repo := DefaultGitPrj
branch := "master"
branch := ""
a := strings.Split(config.GitProjectName, "/")
if len(a[0]) > 0 {
@@ -216,6 +284,9 @@ func (config *AutogitConfig) GetPrjGit() (string, string, string) {
}
}
if len(branch) == 0 {
panic("branch for project is undefined. Should not happend." + org + "/" + repo)
}
return org, repo, branch
}
@@ -223,9 +294,18 @@ func (config *AutogitConfig) GetRemoteBranch() string {
return "origin_" + config.Branch
}
func (config *AutogitConfig) Label(label string) string {
if t, found := config.Labels[LabelKey(label)]; found {
return t
}
return label
}
type StagingConfig struct {
ObsProject string
RebuildAll bool
ObsProject string
RebuildAll bool
CleanupDelay int // cleanup delay, in hours, for unmerged closed PRs (def: 48)
// if set, then only use pull request numbers as unique identifiers
StagingProject string
@@ -234,10 +314,14 @@ type StagingConfig struct {
func ParseStagingConfig(data []byte) (*StagingConfig, error) {
var staging StagingConfig
if len(data) == 0 {
return nil, errors.New("non-existent config file.")
}
data, err := hujson.Standardize(data)
if err != nil {
return nil, err
}
staging.CleanupDelay = 48
if err := json.Unmarshal(data, &staging); err != nil {
return nil, err
}

View File

@@ -4,12 +4,151 @@ import (
"slices"
"testing"
"go.uber.org/mock/gomock"
"src.opensuse.org/autogits/common"
"src.opensuse.org/autogits/common/gitea-generated/models"
mock_common "src.opensuse.org/autogits/common/mock"
)
func TestLabelKey(t *testing.T) {
tests := map[string]string{
"": "",
"foo": "Foo",
"foo/bar": "Foobar",
"foo/Bar": "FooBar",
}
for k, v := range tests {
if c := common.LabelKey(k); c != v {
t.Error("expected", v, "got", c, "input", k)
}
}
}
func TestConfigLabelParser(t *testing.T) {
tests := []struct {
name string
json string
label_value string
}{
{
name: "empty",
json: "{}",
label_value: "path/String",
},
{
name: "defined",
json: `{"Labels": {"foo": "bar", "PathString": "moo/Label"}}`,
label_value: "moo/Label",
},
{
name: "undefined",
json: `{"Labels": {"foo": "bar", "NotPathString": "moo/Label"}}`,
label_value: "path/String",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
repo := models.Repository{
DefaultBranch: "master",
}
ctl := NewController(t)
gitea := mock_common.NewMockGiteaFileContentAndRepoFetcher(ctl)
gitea.EXPECT().GetRepositoryFileContent("foo", "bar", "", "workflow.config").Return([]byte(test.json), "abc", nil)
gitea.EXPECT().GetRepository("foo", "bar").Return(&repo, nil)
config, err := common.ReadWorkflowConfig(gitea, "foo/bar")
if err != nil || config == nil {
t.Fatal(err)
}
if l := config.Label("path/String"); l != test.label_value {
t.Error("Expecting", test.label_value, "got", l)
}
})
}
}
func TestProjectConfigMatcher(t *testing.T) {
configs := common.AutogitConfigs{
{
Organization: "test",
GitProjectName: "test/prjgit#main",
},
{
Organization: "test",
Branch: "main",
GitProjectName: "test/prjgit#main",
},
{
Organization: "test",
Branch: "main",
GitProjectName: "test/bar#never_match",
},
{
Organization: "test",
GitProjectName: "test/bar#main",
},
}
tests := []struct {
name string
org string
repo string
branch string
config int
}{
{
name: "invalid match",
org: "foo",
repo: "bar",
config: -1,
},
{
name: "default branch",
org: "test",
repo: "foo",
branch: "",
config: 0,
},
{
name: "main branch",
org: "test",
repo: "foo",
branch: "main",
config: 1,
},
{
name: "prjgit only match",
org: "test",
repo: "bar",
branch: "main",
config: 3,
},
{
name: "non-default branch match",
org: "test",
repo: "bar",
branch: "something_main",
config: -1,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
c := configs.GetPrjGitConfig(test.org, test.repo, test.branch)
if test.config < 0 {
if c != nil {
t.Fatal("Expected nil. Got:", *c)
}
} else if config := configs[test.config]; c != config {
t.Fatal("Expected", *config, "got", *c)
}
})
}
}
func TestConfigWorkflowParser(t *testing.T) {
tests := []struct {
name string
@@ -36,19 +175,28 @@ func TestConfigWorkflowParser(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ctl := gomock.NewController(t)
ctl := NewController(t)
gitea := mock_common.NewMockGiteaFileContentAndRepoFetcher(ctl)
gitea.EXPECT().GetRepositoryFileContent("foo", "bar", "", "workflow.config").Return([]byte(test.config_json), "abc", nil)
gitea.EXPECT().GetRepository("foo", "bar").Return(&test.repo, nil)
_, err := common.ReadWorkflowConfig(gitea, "foo/bar")
config, err := common.ReadWorkflowConfig(gitea, "foo/bar")
if err != nil {
t.Fatal(err)
}
if config.ManualMergeOnly != false {
t.Fatal("This should be false")
}
if config.Label("foobar") != "foobar" {
t.Fatal("undefined label should return default value")
}
})
}
}
// FIXME: should test ReadWorkflowConfig as it will always set prjgit completely
func TestProjectGitParser(t *testing.T) {
tests := []struct {
name string
@@ -59,20 +207,21 @@ func TestProjectGitParser(t *testing.T) {
}{
{
name: "repo only",
prjgit: "repo.git",
prjgit: "repo.git#master",
org: "org",
branch: "br",
res: [3]string{"org", "repo.git", "master"},
},
{
name: "default",
org: "org",
res: [3]string{"org", common.DefaultGitPrj, "master"},
name: "default",
org: "org",
prjgit: "org/_ObsPrj#master",
res: [3]string{"org", common.DefaultGitPrj, "master"},
},
{
name: "repo with branch",
org: "org2",
prjgit: "repo.git#somebranch",
prjgit: "org2/repo.git#somebranch",
res: [3]string{"org2", "repo.git", "somebranch"},
},
{
@@ -82,32 +231,32 @@ func TestProjectGitParser(t *testing.T) {
res: [3]string{"oorg", "foo.bar", "point"},
},
{
name: "whitespace shouldn't matter",
name: "whitespace shouldn't matter",
prjgit: " oorg / \nfoo.bar\t # point ",
res: [3]string{"oorg", "foo.bar", "point"},
},
{
name: "repo org and empty branch",
org: "org3",
prjgit: "oorg/foo.bar#",
prjgit: "oorg/foo.bar#master",
res: [3]string{"oorg", "foo.bar", "master"},
},
{
name: "only branch defined",
org: "org3",
prjgit: "#mybranch",
prjgit: "org3/_ObsPrj#mybranch",
res: [3]string{"org3", "_ObsPrj", "mybranch"},
},
{
name: "only org and branch defined",
org: "org3",
prjgit: "org1/#mybranch",
prjgit: "org1/_ObsPrj#mybranch",
res: [3]string{"org1", "_ObsPrj", "mybranch"},
},
{
name: "empty org and repo",
org: "org3",
prjgit: "/repo#",
prjgit: "org3/repo#master",
res: [3]string{"org3", "repo", "master"},
},
}
@@ -128,3 +277,67 @@ func TestProjectGitParser(t *testing.T) {
})
}
}
func TestConfigPermissions(t *testing.T) {
tests := []struct {
name string
permission string
user string
config *common.AutogitConfig
result bool
}{
{
name: "NoPermissions",
permission: common.Permission_ForceMerge,
},
{
name: "NoPermissions",
permission: common.Permission_Group,
},
{
name: "Regular permission ForcePush",
permission: common.Permission_ForceMerge,
result: true,
user: "user",
config: &common.AutogitConfig{
Permissions: []*common.Permissions{
&common.Permissions{
Permission: common.Permission_ForceMerge,
Members: []string{"user"},
},
},
},
},
{
name: "User is part of a group",
permission: common.Permission_ForceMerge,
result: true,
user: "user",
config: &common.AutogitConfig{
Permissions: []*common.Permissions{
&common.Permissions{
Permission: common.Permission_ForceMerge,
Members: []string{"group"},
},
},
ReviewGroups: []*common.ReviewGroup{
&common.ReviewGroup{
Name: "group",
Reviewers: []string{"some", "members", "including", "user"},
},
},
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if r := test.config.HasPermission(test.user, test.permission); r != test.result {
t.Error("Expecting", test.result, "but got opposite")
}
if r := test.config.HasPermission(test.user+test.user, test.permission); r {
t.Error("Expecting false for fake user, but got opposite")
}
})
}
}

View File

@@ -33,3 +33,6 @@ const (
TopicApp = "src"
)
// when set, pushing to remote does not happen, and other remote side-effects should also not happen
var IsDryRun bool

View File

@@ -1731,3 +1731,246 @@ const requestedReviewJSON = `{
"commit_id": "",
"review": null
}`
const requestStatusJSON=`{
"commit": {
"id": "e637d86cbbdd438edbf60148e28f9d75a74d51b27b01f75610f247cd18394c8e",
"message": "Update nodejs-common.changes\n",
"url": "https://src.opensuse.org/autogits/nodejs-common/commit/e637d86cbbdd438edbf60148e28f9d75a74d51b27b01f75610f247cd18394c8e",
"author": {
"name": "Adam Majer",
"email": "adamm@noreply.src.opensuse.org",
"username": "adamm"
},
"committer": {
"name": "Adam Majer",
"email": "adamm@noreply.src.opensuse.org",
"username": "adamm"
},
"verification": null,
"timestamp": "2025-09-16T12:41:02+02:00",
"added": [],
"removed": [],
"modified": [
"nodejs-common.changes"
]
},
"context": "test",
"created_at": "2025-09-16T10:50:32Z",
"description": "",
"id": 21663,
"repository": {
"id": 90520,
"owner": {
"id": 983,
"login": "autogits",
"login_name": "",
"source_id": 0,
"full_name": "",
"email": "",
"avatar_url": "https://src.opensuse.org/avatars/80a61ef3a14c3c22f0b8b1885d1a75d4",
"html_url": "https://src.opensuse.org/autogits",
"language": "",
"is_admin": false,
"last_login": "0001-01-01T00:00:00Z",
"created": "2024-06-20T09:46:37+02:00",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "",
"website": "",
"description": "",
"visibility": "public",
"followers_count": 0,
"following_count": 0,
"starred_repos_count": 0,
"username": "autogits"
},
"name": "nodejs-common",
"full_name": "autogits/nodejs-common",
"description": "",
"empty": false,
"private": false,
"fork": true,
"template": false,
"parent": {
"id": 62649,
"owner": {
"id": 64,
"login": "pool",
"login_name": "",
"source_id": 0,
"full_name": "",
"email": "",
"avatar_url": "https://src.opensuse.org/avatars/b10a8c0bede9eb4ea771b04db3149f28",
"html_url": "https://src.opensuse.org/pool",
"language": "",
"is_admin": false,
"last_login": "0001-01-01T00:00:00Z",
"created": "2023-03-01T14:41:17+01:00",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "",
"website": "",
"description": "",
"visibility": "public",
"followers_count": 2,
"following_count": 0,
"starred_repos_count": 0,
"username": "pool"
},
"name": "nodejs-common",
"full_name": "pool/nodejs-common",
"description": "",
"empty": false,
"private": false,
"fork": false,
"template": false,
"mirror": false,
"size": 134,
"language": "",
"languages_url": "https://src.opensuse.org/api/v1/repos/pool/nodejs-common/languages",
"html_url": "https://src.opensuse.org/pool/nodejs-common",
"url": "https://src.opensuse.org/api/v1/repos/pool/nodejs-common",
"link": "",
"ssh_url": "gitea@src.opensuse.org:pool/nodejs-common.git",
"clone_url": "https://src.opensuse.org/pool/nodejs-common.git",
"original_url": "",
"website": "",
"stars_count": 0,
"forks_count": 3,
"watchers_count": 12,
"open_issues_count": 0,
"open_pr_counter": 0,
"release_counter": 0,
"default_branch": "factory",
"archived": false,
"created_at": "2024-06-17T17:08:45+02:00",
"updated_at": "2025-08-21T21:58:31+02:00",
"archived_at": "1970-01-01T01:00:00+01:00",
"permissions": {
"admin": true,
"push": true,
"pull": true
},
"has_issues": true,
"internal_tracker": {
"enable_time_tracker": false,
"allow_only_contributors_to_track_time": true,
"enable_issue_dependencies": true
},
"has_wiki": false,
"has_pull_requests": true,
"has_projects": false,
"projects_mode": "all",
"has_releases": false,
"has_packages": false,
"has_actions": false,
"ignore_whitespace_conflicts": false,
"allow_merge_commits": true,
"allow_rebase": true,
"allow_rebase_explicit": true,
"allow_squash_merge": true,
"allow_fast_forward_only_merge": true,
"allow_rebase_update": true,
"allow_manual_merge": true,
"autodetect_manual_merge": true,
"default_delete_branch_after_merge": false,
"default_merge_style": "merge",
"default_allow_maintainer_edit": false,
"avatar_url": "",
"internal": false,
"mirror_interval": "",
"object_format_name": "sha256",
"mirror_updated": "0001-01-01T00:00:00Z",
"topics": [],
"licenses": []
},
"mirror": false,
"size": 143,
"language": "",
"languages_url": "https://src.opensuse.org/api/v1/repos/autogits/nodejs-common/languages",
"html_url": "https://src.opensuse.org/autogits/nodejs-common",
"url": "https://src.opensuse.org/api/v1/repos/autogits/nodejs-common",
"link": "",
"ssh_url": "gitea@src.opensuse.org:autogits/nodejs-common.git",
"clone_url": "https://src.opensuse.org/autogits/nodejs-common.git",
"original_url": "",
"website": "",
"stars_count": 0,
"forks_count": 1,
"watchers_count": 4,
"open_issues_count": 0,
"open_pr_counter": 1,
"release_counter": 0,
"default_branch": "factory",
"archived": false,
"created_at": "2024-07-01T13:29:03+02:00",
"updated_at": "2025-09-16T12:41:03+02:00",
"archived_at": "1970-01-01T01:00:00+01:00",
"permissions": {
"admin": true,
"push": true,
"pull": true
},
"has_issues": false,
"has_wiki": false,
"has_pull_requests": true,
"has_projects": false,
"projects_mode": "all",
"has_releases": false,
"has_packages": false,
"has_actions": false,
"ignore_whitespace_conflicts": false,
"allow_merge_commits": true,
"allow_rebase": true,
"allow_rebase_explicit": true,
"allow_squash_merge": true,
"allow_fast_forward_only_merge": true,
"allow_rebase_update": true,
"allow_manual_merge": true,
"autodetect_manual_merge": true,
"default_delete_branch_after_merge": false,
"default_merge_style": "merge",
"default_allow_maintainer_edit": false,
"avatar_url": "",
"internal": false,
"mirror_interval": "",
"object_format_name": "sha256",
"mirror_updated": "0001-01-01T00:00:00Z",
"topics": [],
"licenses": [
"MIT"
]
},
"sender": {
"id": 129,
"login": "adamm",
"login_name": "",
"source_id": 0,
"full_name": "Adam Majer",
"email": "adamm@noreply.src.opensuse.org",
"avatar_url": "https://src.opensuse.org/avatars/3e8917bfbf04293f7c20c28cacd83dae2ba9b78a6c6a9a1bedf14c683d8a3763",
"html_url": "https://src.opensuse.org/adamm",
"language": "",
"is_admin": false,
"last_login": "0001-01-01T00:00:00Z",
"created": "2023-07-21T16:43:48+02:00",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "",
"website": "",
"description": "",
"visibility": "public",
"followers_count": 1,
"following_count": 0,
"starred_repos_count": 0,
"username": "adamm"
},
"sha": "e637d86cbbdd438edbf60148e28f9d75a74d51b27b01f75610f247cd18394c8e",
"state": "pending",
"target_url": "https://src.opensuse.org/",
"updated_at": "2025-09-16T10:50:32Z"
}`

View File

@@ -28,6 +28,7 @@ import (
"os/exec"
"path"
"path/filepath"
"slices"
"strings"
"sync"
)
@@ -39,10 +40,19 @@ type GitSubmoduleLister interface {
GitSubmoduleCommitId(cwd, packageName, commitId string) (subCommitId string, valid bool)
}
type GitDirectoryLister interface {
GitDirectoryList(gitPath, commitId string) (dirlist map[string]string, err error)
GitDirectoryContentList(gitPath, commitId string) (dirlist map[string]string, err error)
}
type GitStatusLister interface {
GitStatus(cwd string) ([]GitStatusData, error)
}
type GitDiffLister interface {
GitDiff(cwd, base, head string) (string, error)
}
type Git interface {
// error if git, but wrong remote
GitClone(repo, branch, remoteUrl string) (string, error) // clone, or check if path is already checked out remote and force pulls, error otherwise. Return remotename, errror
@@ -56,12 +66,16 @@ type Git interface {
io.Closer
GitSubmoduleLister
GitDirectoryLister
GitStatusLister
GitExecWithOutputOrPanic(cwd string, params ...string) string
GitExecOrPanic(cwd string, params ...string)
GitExec(cwd string, params ...string) error
GitExecWithOutput(cwd string, params ...string) (string, error)
GitExecQuietOrPanic(cwd string, params ...string)
GitDiffLister
}
type GitHandlerImpl struct {
@@ -69,7 +83,8 @@ type GitHandlerImpl struct {
GitCommiter string
GitEmail string
lock *sync.Mutex
lock *sync.Mutex
quiet bool
}
func (s *GitHandlerImpl) GetPath() string {
@@ -132,6 +147,7 @@ func (s *gitHandlerGeneratorImpl) CreateGitHandler(org string) (Git, error) {
}
func (s *gitHandlerGeneratorImpl) ReadExistingPath(org string) (Git, error) {
LogDebug("Locking git org:", org)
s.lock_lock.Lock()
defer s.lock_lock.Unlock()
@@ -153,6 +169,7 @@ func (s *gitHandlerGeneratorImpl) ReadExistingPath(org string) (Git, error) {
func (s *gitHandlerGeneratorImpl) ReleaseLock(org string) {
m, ok := s.lock[org]
if ok {
LogDebug("Unlocking git org:", org)
m.Unlock()
}
}
@@ -196,19 +213,26 @@ func (refs *GitReferences) addReference(id, branch string) {
}
func (e *GitHandlerImpl) GitClone(repo, branch, remoteUrl string) (string, error) {
LogDebug("Cloning", remoteUrl, " repo:", repo, " branch:", branch)
remoteUrlComp, err := ParseGitRemoteUrl(remoteUrl)
if err != nil {
return "", fmt.Errorf("Cannot parse remote URL: %w", err)
}
if len(branch) == 0 {
remoteBranch := "HEAD"
if len(branch) == 0 && remoteUrlComp != nil && remoteUrlComp.Commit != "HEAD" {
branch = remoteUrlComp.Commit
}
if len(branch) == 0 {
branch = "HEAD"
remoteBranch = branch
} else if len(branch) > 0 {
remoteBranch = branch
}
remoteName := remoteUrlComp.RemoteName()
LogDebug("Clone", *remoteUrlComp, " -> ", remoteName)
if remoteUrlComp != nil {
LogDebug("Clone", *remoteUrlComp, " -> ", remoteName)
} else {
LogDebug("Clone", "[default] -> ", remoteName)
}
remoteRef := remoteName + "/" + remoteBranch
if fi, err := os.Stat(path.Join(e.GitPath, repo)); os.IsNotExist(err) {
if err = e.GitExec("", "clone", "--origin", remoteName, remoteUrl, repo); err != nil {
return remoteName, err
@@ -222,18 +246,57 @@ func (e *GitHandlerImpl) GitClone(repo, branch, remoteUrl string) (string, error
e.GitExecOrPanic(repo, "remote", "set-url", remoteName, remoteUrl)
}
e.GitExecOrPanic(repo, "fetch", remoteName, branch)
// check if we have submodule to deinit
if list, _ := e.GitSubmoduleList(repo, "HEAD"); len(list) > 0 {
e.GitExecQuietOrPanic(repo, "submodule", "deinit", "--all", "--force")
}
e.GitExecOrPanic(repo, "fetch", "--prune", remoteName, remoteBranch)
}
return remoteName, e.GitExec(repo, "checkout", "-B", branch, "refs/remotes/"+remoteName+"/"+branch)
/*
refsBytes, err := os.ReadFile(path.Join(e.GitPath, repo, ".git/refs/remotes", remoteName, "HEAD"))
if err != nil {
LogError("Cannot read HEAD of remote", remoteName)
return remoteName, fmt.Errorf("Cannot read HEAD of remote %s", remoteName)
}
refs := string(refsBytes)
if refs[0:5] != "ref: " {
LogError("Unexpected format of remote HEAD ref:", refs)
return remoteName, fmt.Errorf("Unexpected format of remote HEAD ref: %s", refs)
}
if len(branch) == 0 || branch == "HEAD" {
remoteRef = strings.TrimSpace(refs[5:])
branch = remoteRef[strings.LastIndex(remoteRef, "/")+1:]
LogDebug("remoteRef", remoteRef)
LogDebug("branch", branch)
}
*/
args := []string{"fetch", "--prune", remoteName}
if len(branch) > 0 {
args = append(args, branch)
}
if strings.TrimSpace(e.GitExecWithOutputOrPanic(repo, "rev-parse", "--is-shallow-repository")) == "true" {
args = slices.Insert(args, 1, "--unshallow")
}
e.GitExecOrPanic(repo, args...)
return remoteName, e.GitExec(repo, "checkout", "-f", "--track", "-B", branch, remoteRef)
}
func (e *GitHandlerImpl) GitBranchHead(gitDir, branchName string) (string, error) {
id, err := e.GitExecWithOutput(gitDir, "show-ref", "--hash", "--verify", "refs/heads/"+branchName)
id, err := e.GitExecWithOutput(gitDir, "show-ref", "--heads", "--hash", branchName)
if err != nil {
return "", fmt.Errorf("Can't find default branch: %s", branchName)
}
return strings.TrimSpace(id), nil
id = strings.TrimSpace(SplitLines(id)[0])
if len(id) < 10 {
return "", fmt.Errorf("Can't find branch: %s", branchName)
}
return id, nil
}
func (e *GitHandlerImpl) GitRemoteHead(gitDir, remote, branchName string) (string, error) {
@@ -246,6 +309,7 @@ func (e *GitHandlerImpl) GitRemoteHead(gitDir, remote, branchName string) (strin
}
func (e *GitHandlerImpl) Close() error {
LogDebug("Unlocking git lock")
e.lock.Unlock()
return nil
}
@@ -291,6 +355,10 @@ var ExtraGitParams []string
func (e *GitHandlerImpl) GitExecWithOutput(cwd string, params ...string) (string, error) {
cmd := exec.Command("/usr/bin/git", params...)
var identityFile string
if i := os.Getenv("AUTOGITS_IDENTITY_FILE"); len(i) > 0 {
identityFile = " -i " + i
}
cmd.Env = []string{
"GIT_CEILING_DIRECTORIES=" + e.GitPath,
"GIT_CONFIG_GLOBAL=/dev/null",
@@ -298,7 +366,8 @@ func (e *GitHandlerImpl) GitExecWithOutput(cwd string, params ...string) (string
"GIT_COMMITTER_NAME=" + e.GitCommiter,
"EMAIL=not@exist@src.opensuse.org",
"GIT_LFS_SKIP_SMUDGE=1",
"GIT_SSH_COMMAND=/usr/bin/ssh -o StrictHostKeyChecking=yes",
"GIT_LFS_SKIP_PUSH=1",
"GIT_SSH_COMMAND=/usr/bin/ssh -o StrictHostKeyChecking=yes" + identityFile,
}
if len(ExtraGitParams) > 0 {
cmd.Env = append(cmd.Env, ExtraGitParams...)
@@ -306,9 +375,11 @@ func (e *GitHandlerImpl) GitExecWithOutput(cwd string, params ...string) (string
cmd.Dir = filepath.Join(e.GitPath, cwd)
cmd.Stdin = nil
LogDebug("git execute:", cmd.Args)
LogDebug("git execute @", cwd, ":", cmd.Args)
out, err := cmd.CombinedOutput()
LogDebug(string(out))
if !e.quiet {
LogDebug(string(out))
}
if err != nil {
LogError("git", cmd.Args, " error:", err)
return "", fmt.Errorf("error executing: git %#v \n%s\n err: %w", cmd.Args, out, err)
@@ -317,6 +388,13 @@ func (e *GitHandlerImpl) GitExecWithOutput(cwd string, params ...string) (string
return string(out), nil
}
func (e *GitHandlerImpl) GitExecQuietOrPanic(cwd string, params ...string) {
e.quiet = true
e.GitExecOrPanic(cwd, params...)
e.quiet = false
return
}
type ChanIO struct {
ch chan byte
}
@@ -446,21 +524,29 @@ func parseGitMsg(data <-chan byte) (GitMsg, error) {
}, nil
}
func parseGitCommitHdr(data <-chan byte) ([2]string, error) {
func parseGitCommitHdr(oldHdr [2]string, data <-chan byte) ([2]string, int, error) {
hdr := make([]byte, 0, 60)
val := make([]byte, 0, 1000)
c := <-data
size := 1
if c != '\n' { // end of header marker
for ; c != ' '; c = <-data {
hdr = append(hdr, c)
size++
}
if size == 1 { // continuation header here
hdr = []byte(oldHdr[0])
val = append([]byte(oldHdr[1]), '\n')
}
for c := <-data; c != '\n'; c = <-data {
val = append(val, c)
size++
}
size++
}
return [2]string{string(hdr), string(val)}, nil
return [2]string{string(hdr), string(val)}, size, nil
}
func parseGitCommitMsg(data <-chan byte, l int) (string, error) {
@@ -470,7 +556,6 @@ func parseGitCommitMsg(data <-chan byte, l int) (string, error) {
msg = append(msg, c)
l--
}
// l--
if l != 0 {
return "", fmt.Errorf("Unexpected data in the git commit msg: l=%d", l)
@@ -490,12 +575,14 @@ func parseGitCommit(data <-chan byte) (GitCommit, error) {
var c GitCommit
l := hdr.size
for {
hdr, err := parseGitCommitHdr(data)
var hdr [2]string
hdr, size, err := parseGitCommitHdr(hdr, data)
if err != nil {
return GitCommit{}, nil
}
l -= size
if len(hdr[0])+len(hdr[1]) == 0 { // hdr end marker
if size == 1 {
break
}
@@ -503,10 +590,7 @@ func parseGitCommit(data <-chan byte) (GitCommit, error) {
case "tree":
c.Tree = hdr[1]
}
l -= len(hdr[0]) + len(hdr[1]) + 2
}
l--
c.Msg, err = parseGitCommitMsg(data, l)
return c, err
@@ -595,7 +679,7 @@ func (e *GitHandlerImpl) GitParseCommits(cwd string, commitIDs []string) (parsed
var done sync.Mutex
done.Lock()
data_in, data_out := ChanIO{make(chan byte, 256)}, ChanIO{make(chan byte, 70)}
data_in, data_out := ChanIO{make(chan byte)}, ChanIO{make(chan byte)}
parsedCommits = make([]GitCommit, 0, len(commitIDs))
go func() {
@@ -629,7 +713,12 @@ func (e *GitHandlerImpl) GitParseCommits(cwd string, commitIDs []string) (parsed
return len(data), nil
})
LogDebug("command run:", cmd.Args)
err = cmd.Run()
if e := cmd.Run(); e != nil {
LogError(e)
close(data_in.ch)
close(data_out.ch)
return nil, e
}
done.Lock()
return
@@ -640,7 +729,7 @@ func (e *GitHandlerImpl) GitCatFile(cwd, commitId, filename string) (data []byte
var done sync.Mutex
done.Lock()
data_in, data_out := ChanIO{make(chan byte, 256)}, ChanIO{make(chan byte, 70)}
data_in, data_out := ChanIO{make(chan byte)}, ChanIO{make(chan byte)}
go func() {
defer done.Unlock()
@@ -694,6 +783,7 @@ func (e *GitHandlerImpl) GitCatFile(cwd, commitId, filename string) (data []byte
})
LogDebug("command run:", cmd.Args)
if e := cmd.Run(); e != nil {
LogError(e)
close(data_in.ch)
close(data_out.ch)
return nil, e
@@ -702,13 +792,165 @@ func (e *GitHandlerImpl) GitCatFile(cwd, commitId, filename string) (data []byte
return
}
// return (directory) -> (hash) map for all submodules
func (e *GitHandlerImpl) GitDirectoryList(gitPath, commitId string) (directoryList map[string]string, err error) {
var done sync.Mutex
directoryList = make(map[string]string)
done.Lock()
data_in, data_out := ChanIO{make(chan byte)}, ChanIO{make(chan byte)}
LogDebug("Getting directory for:", commitId)
go func() {
defer done.Unlock()
defer close(data_out.ch)
data_out.Write([]byte(commitId))
data_out.ch <- '\x00'
var c GitCommit
c, err = parseGitCommit(data_in.ch)
if err != nil {
err = fmt.Errorf("Error parsing git commit. Err: %w", err)
return
}
trees := make(map[string]string)
trees[""] = c.Tree
for len(trees) > 0 {
for p, tree := range trees {
delete(trees, p)
data_out.Write([]byte(tree))
data_out.ch <- '\x00'
var tree GitTree
tree, err = parseGitTree(data_in.ch)
if err != nil {
err = fmt.Errorf("Error parsing git tree: %w", err)
return
}
for _, te := range tree.items {
if te.isTree() {
directoryList[p+te.name] = te.hash
}
}
}
}
}()
cmd := exec.Command("/usr/bin/git", "cat-file", "--batch", "-Z")
cmd.Env = []string{
"GIT_CEILING_DIRECTORIES=" + e.GitPath,
"GIT_LFS_SKIP_SMUDGE=1",
"GIT_CONFIG_GLOBAL=/dev/null",
}
cmd.Dir = filepath.Join(e.GitPath, gitPath)
cmd.Stdout = &data_in
cmd.Stdin = &data_out
cmd.Stderr = writeFunc(func(data []byte) (int, error) {
LogError(string(data))
return len(data), nil
})
LogDebug("command run:", cmd.Args)
if e := cmd.Run(); e != nil {
LogError(e)
close(data_in.ch)
close(data_out.ch)
return directoryList, e
}
done.Lock()
return directoryList, err
}
// return (directory) -> (hash) map for all submodules
func (e *GitHandlerImpl) GitDirectoryContentList(gitPath, commitId string) (directoryList map[string]string, err error) {
var done sync.Mutex
directoryList = make(map[string]string)
done.Lock()
data_in, data_out := ChanIO{make(chan byte)}, ChanIO{make(chan byte)}
LogDebug("Getting directory content for:", commitId)
go func() {
defer done.Unlock()
defer close(data_out.ch)
data_out.Write([]byte(commitId))
data_out.ch <- '\x00'
var c GitCommit
c, err = parseGitCommit(data_in.ch)
if err != nil {
err = fmt.Errorf("Error parsing git commit. Err: %w", err)
return
}
trees := make(map[string]string)
trees[""] = c.Tree
for len(trees) > 0 {
for p, tree := range trees {
delete(trees, p)
data_out.Write([]byte(tree))
data_out.ch <- '\x00'
var tree GitTree
tree, err = parseGitTree(data_in.ch)
if err != nil {
err = fmt.Errorf("Error parsing git tree: %w", err)
return
}
for _, te := range tree.items {
if te.isBlob() || te.isSubmodule() {
directoryList[p+te.name] = te.hash
} else if te.isTree() {
trees[p+te.name] = te.hash
}
}
}
}
}()
cmd := exec.Command("/usr/bin/git", "cat-file", "--batch", "-Z")
cmd.Env = []string{
"GIT_CEILING_DIRECTORIES=" + e.GitPath,
"GIT_LFS_SKIP_SMUDGE=1",
"GIT_CONFIG_GLOBAL=/dev/null",
}
cmd.Dir = filepath.Join(e.GitPath, gitPath)
cmd.Stdout = &data_in
cmd.Stdin = &data_out
cmd.Stderr = writeFunc(func(data []byte) (int, error) {
LogError(string(data))
return len(data), nil
})
LogDebug("command run:", cmd.Args)
if e := cmd.Run(); e != nil {
LogError(e)
close(data_in.ch)
close(data_out.ch)
return directoryList, e
}
done.Lock()
return directoryList, err
}
// return (filename) -> (hash) map for all submodules
func (e *GitHandlerImpl) GitSubmoduleList(gitPath, commitId string) (submoduleList map[string]string, err error) {
var done sync.Mutex
submoduleList = make(map[string]string)
done.Lock()
data_in, data_out := ChanIO{make(chan byte, 256)}, ChanIO{make(chan byte, 70)}
data_in, data_out := ChanIO{make(chan byte)}, ChanIO{make(chan byte)}
LogDebug("Getting submodules for:", commitId)
go func() {
defer done.Unlock()
@@ -766,14 +1008,19 @@ func (e *GitHandlerImpl) GitSubmoduleList(gitPath, commitId string) (submoduleLi
return len(data), nil
})
LogDebug("command run:", cmd.Args)
err = cmd.Run()
if e := cmd.Run(); e != nil {
LogError(e)
close(data_in.ch)
close(data_out.ch)
return submoduleList, e
}
done.Lock()
return submoduleList, err
}
func (e *GitHandlerImpl) GitSubmoduleCommitId(cwd, packageName, commitId string) (subCommitId string, valid bool) {
data_in, data_out := ChanIO{make(chan byte, 256)}, ChanIO{make(chan byte, 70)}
data_in, data_out := ChanIO{make(chan byte)}, ChanIO{make(chan byte)}
var wg sync.WaitGroup
wg.Add(1)
@@ -782,7 +1029,7 @@ func (e *GitHandlerImpl) GitSubmoduleCommitId(cwd, packageName, commitId string)
go func() {
defer func() {
if recover() != nil {
subCommitId = "wrong"
subCommitId = ""
commitId = "ok"
valid = false
}
@@ -829,12 +1076,15 @@ func (e *GitHandlerImpl) GitSubmoduleCommitId(cwd, packageName, commitId string)
return len(data), nil
})
LogDebug("command run:", cmd.Args)
if err := cmd.Run(); err != nil {
LogError("Error running command:", cmd.Args, err)
if e := cmd.Run(); e != nil {
LogError(e)
close(data_in.ch)
close(data_out.ch)
return subCommitId, false
}
wg.Wait()
return subCommitId, len(subCommitId) == len(commitId)
return subCommitId, len(subCommitId) > 0
}
const (
@@ -849,6 +1099,16 @@ type GitStatusData struct {
Path string
Status int
States [3]string
/*
<sub> A 4 character field describing the submodule state.
"N..." when the entry is not a submodule.
"S<c><m><u>" when the entry is a submodule.
<c> is "C" if the commit changed; otherwise ".".
<m> is "M" if it has tracked changes; otherwise ".".
<u> is "U" if there are untracked changes; otherwise ".".
*/
SubmoduleChanges string
}
func parseGitStatusHexString(data io.ByteReader) (string, error) {
@@ -871,6 +1131,20 @@ func parseGitStatusHexString(data io.ByteReader) (string, error) {
}
}
func parseGitStatusString(data io.ByteReader) (string, error) {
str := make([]byte, 0, 100)
for {
c, err := data.ReadByte()
if err != nil {
return "", errors.New("Unexpected EOF. Expected NUL string term")
}
if c == 0 || c == ' ' {
return string(str), nil
}
str = append(str, c)
}
}
func parseGitStatusStringWithSpace(data io.ByteReader) (string, error) {
str := make([]byte, 0, 100)
for {
c, err := data.ReadByte()
@@ -911,7 +1185,7 @@ func parseSingleStatusEntry(data io.ByteReader) (*GitStatusData, error) {
return nil, err
}
ret.Status = GitStatus_Modified
ret.Path, err = parseGitStatusString(data)
ret.Path, err = parseGitStatusStringWithSpace(data)
if err != nil {
return nil, err
}
@@ -921,11 +1195,11 @@ func parseSingleStatusEntry(data io.ByteReader) (*GitStatusData, error) {
return nil, err
}
ret.Status = GitStatus_Renamed
ret.Path, err = parseGitStatusString(data)
ret.Path, err = parseGitStatusStringWithSpace(data)
if err != nil {
return nil, err
}
ret.States[0], err = parseGitStatusString(data)
ret.States[0], err = parseGitStatusStringWithSpace(data)
if err != nil {
return nil, err
}
@@ -935,7 +1209,7 @@ func parseSingleStatusEntry(data io.ByteReader) (*GitStatusData, error) {
return nil, err
}
ret.Status = GitStatus_Untracked
ret.Path, err = parseGitStatusString(data)
ret.Path, err = parseGitStatusStringWithSpace(data)
if err != nil {
return nil, err
}
@@ -945,15 +1219,22 @@ func parseSingleStatusEntry(data io.ByteReader) (*GitStatusData, error) {
return nil, err
}
ret.Status = GitStatus_Ignored
ret.Path, err = parseGitStatusString(data)
ret.Path, err = parseGitStatusStringWithSpace(data)
if err != nil {
return nil, err
}
case 'u':
var err error
if err = skipGitStatusEntry(data, 7); err != nil {
if err = skipGitStatusEntry(data, 2); err != nil {
return nil, err
}
if ret.SubmoduleChanges, err = parseGitStatusString(data); err != nil {
return nil, err
}
if err = skipGitStatusEntry(data, 4); err != nil {
return nil, err
}
if ret.States[0], err = parseGitStatusHexString(data); err != nil {
return nil, err
}
@@ -964,7 +1245,7 @@ func parseSingleStatusEntry(data io.ByteReader) (*GitStatusData, error) {
return nil, err
}
ret.Status = GitStatus_Unmerged
ret.Path, err = parseGitStatusString(data)
ret.Path, err = parseGitStatusStringWithSpace(data)
if err != nil {
return nil, err
}
@@ -1011,3 +1292,26 @@ func (e *GitHandlerImpl) GitStatus(cwd string) (ret []GitStatusData, err error)
return parseGitStatusData(bufio.NewReader(bytes.NewReader(out)))
}
func (e *GitHandlerImpl) GitDiff(cwd, base, head string) (string, error) {
LogDebug("getting diff from", base, "..", head)
cmd := exec.Command("/usr/bin/git", "diff", base+".."+head)
cmd.Env = []string{
"GIT_CEILING_DIRECTORIES=" + e.GitPath,
"GIT_LFS_SKIP_SMUDGE=1",
"GIT_CONFIG_GLOBAL=/dev/null",
}
cmd.Dir = filepath.Join(e.GitPath, cwd)
cmd.Stderr = writeFunc(func(data []byte) (int, error) {
LogError(string(data))
return len(data), nil
})
LogDebug("command run:", cmd.Args)
out, err := cmd.Output()
if err != nil {
LogError("Error running command", cmd.Args, err)
}
return string(out), nil
}

View File

@@ -24,12 +24,14 @@ import (
"os"
"os/exec"
"path"
"path/filepath"
"slices"
"strings"
"testing"
)
func TestGitClone(t *testing.T) {
SetTestLogger(t)
tests := []struct {
name string
@@ -54,6 +56,8 @@ func TestGitClone(t *testing.T) {
},
}
return
execPath, err := os.Getwd()
if err != nil {
t.Fatal(err)
@@ -91,7 +95,59 @@ func TestGitClone(t *testing.T) {
}
}
func TestGitCloneCommitID(t *testing.T) {
SetTestLogger(t)
execPath, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
d := t.TempDir()
if err := os.Chdir(d); err != nil {
t.Fatal(err)
}
defer os.Chdir(execPath)
cmd := exec.Command(path.Join(execPath, "test_repo_setup.sh"))
if out, err := cmd.CombinedOutput(); err != nil {
t.Log(string(out))
t.Fatal(err)
}
gh, err := AllocateGitWorkTree(d, "Test", "test@example.com")
if err != nil {
t.Fatal(err)
}
g, err := gh.CreateGitHandler("org")
if err != nil {
t.Fatal(err)
}
// Get a commit ID from pkgA
remoteUrl := "file://" + d + "/pkgA"
out, err := exec.Command("git", "-C", path.Join(d, "pkgA"), "rev-parse", "main").Output()
if err != nil {
t.Fatal(err)
}
commitID := strings.TrimSpace(string(out))
repo := "pkgAcloneCommitID"
if _, err := g.GitClone(repo, commitID, remoteUrl); err != nil {
t.Skip("TODO: Add GitClone CommitID support")
t.Fatalf("GitClone failed with commit ID: %v", err)
}
// Verify we are at the right commit
head, err := g.GitBranchHead(repo, commitID)
if err != nil {
t.Fatalf("GitBranchHead failed: %v", err)
}
if head != commitID {
t.Errorf("Expected head %s, got %s", commitID, head)
}
}
func TestGitMsgParsing(t *testing.T) {
SetTestLogger(t)
t.Run("tree message with size 56", func(t *testing.T) {
const hdr = "f40888ea4515fe2e8eea617a16f5f50a45f652d894de3ad181d58de3aafb8f98 tree 56\x00"
@@ -170,6 +226,7 @@ func TestGitMsgParsing(t *testing.T) {
}
func TestGitCommitParsing(t *testing.T) {
SetTestLogger(t)
t.Run("parse valid commit message", func(t *testing.T) {
const commitData = "f40888ea4515fe2e8eea617a16f5f50a45f652d894de3ad181d58de3aafb8f99 commit 253\000" +
`tree e20033df9f18780756ba4a96dbc7eb1a626253961039cb674156f266ba7a4e53
@@ -198,7 +255,7 @@ committer Adam Majer <amajer@suse.com> 1720709149 +0200
})
t.Run("parse multiline headers", func(t *testing.T) {
const commitData = "cae5831ab48470ff060a5aaa12eb6e5a7acaf91e commit 1491\x00" +
const commitData = "cae5831ab48470ff060a5aaa12eb6e5a7acaf91e commit 1492\000" +
`tree 1f9c8fe8099615d6d3921528402ac53f09213b02
parent e08a654fae0ecc91678819e0b62a2e014bad3339
author Yagiz Nizipli <yagiz@nizipli.com> 1720967314 -0400
@@ -230,7 +287,7 @@ Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Reviewed-By: Richard Lau <rlau@redhat.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>` + "\x00"
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>` + "\000"
ch := make(chan byte, 5000)
for _, b := range []byte(commitData) {
@@ -251,6 +308,51 @@ Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>` + "\x00"
}
})
t.Run("parse multiline headers", func(t *testing.T) {
const commitData = "c07c52c57a10fb355956df3caad2986613838f149274fbe312ad76560764829d commit 1150\000" + `tree 3e06b280ea056141ed5e8af9794a41ae5281930c45321803eab53a240cb60044
parent 19362a2cecb1fd25a89e03611d08ac68dcb1732f9dc0a68a40926356787fa4ca
author Adrian Schröter <adrian@suse.de> 1746600403 +0200
committer Adrian Schröter <adrian@suse.de> 1746600403 +0200
gpgsig-sha256 -----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEE1QF1zm/pNbvyhgLFkY2MlUwI22cFAmgbAd0ACgkQkY2MlUwI
22dxtA//eUCzIqxVdaEnOrFeTyxKig/mCOjaAyctmwr0vXUyElRtjXe4TzVG3QtR
uDfhIrKYLZ2tU/0TewTW/4XopWxLuqEzVQLrjuYl7K5P3GoYk52W1yGT0szzm7/i
87j4UdRL9YGU/gYO7nSzstcfTP6AcmYzVUoOnwYR0K2vyOVjO4niL3mFXxLkIgIt
jd82xcE4JpQz9Yjyq2nDdz4A55kLAwsqY+dOct4oC6bZmj1/JeoGQfPvUsvsQgcI
syCHVh0GBxjvSv50V/VPzxQTFMal/TdtvAD4kmP/9RDi/5THzus8Peam8pV0gEIC
Q15ZcuLwIsC9i7ifUDYgzLgBBRdpSI0qji4Y6clWULPVjsyghgyfQw1trBSySpC8
O1XfajUM+rXyrBLP6kzY+zl/zyzRdJ8JhljmC+SmNuyyEB77Hkn83k0f+aBhhqC2
4b3fIsKtwJZ1w6gr6SSz1BottiT9ShQzRaL8iRoF/2l5MkHPR+QFg2J7EIBqCbCQ
hFUjdvWAXQBWkkTQlJmLmJBXDOLQg3o6xCbnZM0gPFjZWE7e3Mpky7H0+xPnoeg9
ukuvkexXQ6yrdiekA7HRLc76Te/I0m7KDOOWZ3rbJV6uH/3ps4FbLQTZO12AtZ6J
n8hYdYfw9yjCxiKUjnEtXtDRe8DJpqv+hO0Wj4MI5gIA2JE2lzY=
=Keg5
-----END PGP SIGNATURE-----
dummy change, don't merge
` + "\000"
ch := make(chan byte)
go func() {
for _, b := range []byte(commitData) {
ch <- b
}
}()
commit, err := parseGitCommit(ch)
if err != nil {
t.Error(err)
}
if commit.Tree != "3e06b280ea056141ed5e8af9794a41ae5281930c45321803eab53a240cb60044" {
t.Errorf("Invalid commit object: %#v", commit)
}
if commit.Msg != "dummy change, don't merge\n" {
t.Errorf("Invalid commit msg: '%s'", commit.Msg)
}
})
t.Run("parse tree object", func(t *testing.T) {
const treeData = "\x31\x61\x30\x35\x64\x62\x37\x33\x36\x39\x33\x37\x34\x33\x30\x65\x31\x38\x64\x66\x34\x33\x61\x32\x37\x61\x39\x38\x30\x30\x31\x30\x31\x32\x65\x31\x65\x64\x32\x30\x34\x38\x32\x39\x38\x36\x37\x31\x32\x38\x66\x32\x63\x65\x38\x34\x30\x36\x62\x35\x63\x66\x63\x39\x20\x74\x72\x65\x65\x20\x32\x30\x35\x00\x34\x30\x30\x30\x30\x20\x62\x6f\x74\x73\x2d\x63\x6f\x6d\x6d\x6f\x6e\x00\x93\x17\xaa\x47\xf6\xea\x37\xe8\xbc\xe2\x80\x77\x57\x90\xf4\xa8\x01\xd7\xe3\x70\x2f\x84\xfb\xe1\xb0\x0e\x4a\x2c\x1c\x75\x2c\x2b\x34\x30\x30\x30\x30\x20\x6f\x62\x73\x2d\x73\x74\x61\x67\x69\x6e\x67\x2d\x62\x6f\x74\x00\x79\x77\x8b\x28\x7d\x37\x10\x59\xb9\x71\x28\x36\xed\x20\x31\x5f\xfb\xe1\xed\xb5\xba\x4f\x5e\xbb\x65\x65\x68\x23\x77\x32\x58\xfe\x34\x30\x30\x30\x30\x20\x70\x72\x2d\x72\x65\x76\x69\x65\x77\x00\x36\x0d\x45\xcb\x76\xb8\x93\xb3\x21\xba\xfa\xd5\x00\x9d\xfc\x59\xab\x88\xc1\x3c\x81\xcb\x48\x5a\xe0\x29\x29\x0f\xe3\x6b\x3c\x5e\x34\x30\x30\x30\x30\x20\x70\x72\x6a\x67\x69\x74\x2d\x75\x70\x64\x61\x74\x65\x72\x00\xb4\x0b\x1c\xf5\xfb\xec\x9a\xb2\x9f\x48\x3e\x21\x18\x0d\x51\xb7\x98\x6e\x21\x99\x74\x84\x67\x71\x41\x24\x42\xfc\xc9\x04\x12\x99\x00"
@@ -335,6 +437,7 @@ Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>` + "\x00"
}
func TestCommitTreeParsing(t *testing.T) {
SetTestLogger(t)
gitDir := t.TempDir()
testDir, _ := os.Getwd()
var commitId string
@@ -345,6 +448,7 @@ func TestCommitTreeParsing(t *testing.T) {
commitId = commitId + strings.TrimSpace(string(data))
return len(data), nil
})
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
t.Fatal(err.Error())
}
@@ -442,6 +546,7 @@ func TestCommitTreeParsing(t *testing.T) {
}
func TestGitStatusParse(t *testing.T) {
SetTestLogger(t)
testData := []struct {
name string
data []byte
@@ -508,6 +613,8 @@ func TestGitStatusParse(t *testing.T) {
Path: ".gitmodules",
Status: GitStatus_Unmerged,
States: [3]string{"587ec403f01113f2629da538f6e14b84781f70ac59c41aeedd978ea8b1253a76", "d23eb05d9ca92883ab9f4d28f3ec90c05f667f3a5c8c8e291bd65e03bac9ae3c", "087b1d5f22dbf0aa4a879fff27fff03568b334c90daa5f2653f4a7961e24ea33"},
SubmoduleChanges: "N...",
},
},
},
@@ -546,3 +653,67 @@ func TestGitStatusParse(t *testing.T) {
})
}
}
func TestGitDirectoryListRepro(t *testing.T) {
SetTestLogger(t)
d := t.TempDir()
// Setup a mock environment for GitHandlerImpl
gh, err := AllocateGitWorkTree(d, "Test", "test@example.com")
if err != nil {
t.Fatal(err)
}
org := "repo-org"
repoName := "test-repo"
repoPath := filepath.Join(d, org, repoName)
err = os.MkdirAll(repoPath, 0755)
if err != nil {
t.Fatal(err)
}
runGit := func(args ...string) {
cmd := exec.Command("git", args...)
cmd.Dir = repoPath
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("git %v failed: %v\n%s", args, err, out)
}
}
runGit("init", "-b", "main", "--object-format=sha256")
runGit("config", "user.email", "test@example.com")
runGit("config", "user.name", "test")
// Create a directory and a file
err = os.Mkdir(filepath.Join(repoPath, "subdir"), 0755)
if err != nil {
t.Fatal(err)
}
err = os.WriteFile(filepath.Join(repoPath, "subdir", "file.txt"), []byte("hello"), 0644)
if err != nil {
t.Fatal(err)
}
runGit("add", "subdir/file.txt")
runGit("commit", "-m", "add subdir")
// Now create the handler
g, err := gh.CreateGitHandler(org)
if err != nil {
t.Fatal(err)
}
// Call GitDirectoryList
dirs, err := g.GitDirectoryList(repoName, "HEAD")
if err != nil {
t.Fatal(err)
}
t.Logf("Directories found: %v", dirs)
if len(dirs) == 0 {
t.Error("No directories found, but 'subdir' should be there")
}
if _, ok := dirs["subdir"]; !ok {
t.Errorf("Expected 'subdir' in directory list, got %v", dirs)
}
}

View File

@@ -36,6 +36,12 @@ func (o *IssueEditIssueAttachmentReader) ReadResponse(response runtime.ClientRes
return nil, err
}
return nil, result
case 422:
result := NewIssueEditIssueAttachmentUnprocessableEntity()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 423:
result := NewIssueEditIssueAttachmentLocked()
if err := result.readResponse(response, consumer, o.formats); err != nil {
@@ -189,6 +195,78 @@ func (o *IssueEditIssueAttachmentNotFound) readResponse(response runtime.ClientR
return nil
}
// NewIssueEditIssueAttachmentUnprocessableEntity creates a IssueEditIssueAttachmentUnprocessableEntity with default headers values
func NewIssueEditIssueAttachmentUnprocessableEntity() *IssueEditIssueAttachmentUnprocessableEntity {
return &IssueEditIssueAttachmentUnprocessableEntity{}
}
/*
IssueEditIssueAttachmentUnprocessableEntity describes a response with status code 422, with default header values.
APIValidationError is error format response related to input validation
*/
type IssueEditIssueAttachmentUnprocessableEntity struct {
Message string
URL string
}
// IsSuccess returns true when this issue edit issue attachment unprocessable entity response has a 2xx status code
func (o *IssueEditIssueAttachmentUnprocessableEntity) IsSuccess() bool {
return false
}
// IsRedirect returns true when this issue edit issue attachment unprocessable entity response has a 3xx status code
func (o *IssueEditIssueAttachmentUnprocessableEntity) IsRedirect() bool {
return false
}
// IsClientError returns true when this issue edit issue attachment unprocessable entity response has a 4xx status code
func (o *IssueEditIssueAttachmentUnprocessableEntity) IsClientError() bool {
return true
}
// IsServerError returns true when this issue edit issue attachment unprocessable entity response has a 5xx status code
func (o *IssueEditIssueAttachmentUnprocessableEntity) IsServerError() bool {
return false
}
// IsCode returns true when this issue edit issue attachment unprocessable entity response a status code equal to that given
func (o *IssueEditIssueAttachmentUnprocessableEntity) IsCode(code int) bool {
return code == 422
}
// Code gets the status code for the issue edit issue attachment unprocessable entity response
func (o *IssueEditIssueAttachmentUnprocessableEntity) Code() int {
return 422
}
func (o *IssueEditIssueAttachmentUnprocessableEntity) Error() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/issues/{index}/assets/{attachment_id}][%d] issueEditIssueAttachmentUnprocessableEntity", 422)
}
func (o *IssueEditIssueAttachmentUnprocessableEntity) String() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/issues/{index}/assets/{attachment_id}][%d] issueEditIssueAttachmentUnprocessableEntity", 422)
}
func (o *IssueEditIssueAttachmentUnprocessableEntity) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}
// NewIssueEditIssueAttachmentLocked creates a IssueEditIssueAttachmentLocked with default headers values
func NewIssueEditIssueAttachmentLocked() *IssueEditIssueAttachmentLocked {
return &IssueEditIssueAttachmentLocked{}

View File

@@ -36,6 +36,12 @@ func (o *IssueEditIssueCommentAttachmentReader) ReadResponse(response runtime.Cl
return nil, err
}
return nil, result
case 422:
result := NewIssueEditIssueCommentAttachmentUnprocessableEntity()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 423:
result := NewIssueEditIssueCommentAttachmentLocked()
if err := result.readResponse(response, consumer, o.formats); err != nil {
@@ -189,6 +195,78 @@ func (o *IssueEditIssueCommentAttachmentNotFound) readResponse(response runtime.
return nil
}
// NewIssueEditIssueCommentAttachmentUnprocessableEntity creates a IssueEditIssueCommentAttachmentUnprocessableEntity with default headers values
func NewIssueEditIssueCommentAttachmentUnprocessableEntity() *IssueEditIssueCommentAttachmentUnprocessableEntity {
return &IssueEditIssueCommentAttachmentUnprocessableEntity{}
}
/*
IssueEditIssueCommentAttachmentUnprocessableEntity describes a response with status code 422, with default header values.
APIValidationError is error format response related to input validation
*/
type IssueEditIssueCommentAttachmentUnprocessableEntity struct {
Message string
URL string
}
// IsSuccess returns true when this issue edit issue comment attachment unprocessable entity response has a 2xx status code
func (o *IssueEditIssueCommentAttachmentUnprocessableEntity) IsSuccess() bool {
return false
}
// IsRedirect returns true when this issue edit issue comment attachment unprocessable entity response has a 3xx status code
func (o *IssueEditIssueCommentAttachmentUnprocessableEntity) IsRedirect() bool {
return false
}
// IsClientError returns true when this issue edit issue comment attachment unprocessable entity response has a 4xx status code
func (o *IssueEditIssueCommentAttachmentUnprocessableEntity) IsClientError() bool {
return true
}
// IsServerError returns true when this issue edit issue comment attachment unprocessable entity response has a 5xx status code
func (o *IssueEditIssueCommentAttachmentUnprocessableEntity) IsServerError() bool {
return false
}
// IsCode returns true when this issue edit issue comment attachment unprocessable entity response a status code equal to that given
func (o *IssueEditIssueCommentAttachmentUnprocessableEntity) IsCode(code int) bool {
return code == 422
}
// Code gets the status code for the issue edit issue comment attachment unprocessable entity response
func (o *IssueEditIssueCommentAttachmentUnprocessableEntity) Code() int {
return 422
}
func (o *IssueEditIssueCommentAttachmentUnprocessableEntity) Error() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/issues/comments/{id}/assets/{attachment_id}][%d] issueEditIssueCommentAttachmentUnprocessableEntity", 422)
}
func (o *IssueEditIssueCommentAttachmentUnprocessableEntity) String() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/issues/comments/{id}/assets/{attachment_id}][%d] issueEditIssueCommentAttachmentUnprocessableEntity", 422)
}
func (o *IssueEditIssueCommentAttachmentUnprocessableEntity) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}
// NewIssueEditIssueCommentAttachmentLocked creates a IssueEditIssueCommentAttachmentLocked with default headers values
func NewIssueEditIssueCommentAttachmentLocked() *IssueEditIssueCommentAttachmentLocked {
return &IssueEditIssueCommentAttachmentLocked{}

View File

@@ -64,13 +64,13 @@ type IssueSearchIssuesParams struct {
/* Assigned.
filter (issues / pulls) assigned to you, default is false
Filter issues or pulls assigned to the authenticated user
*/
Assigned *bool
/* Before.
Only show notifications updated before the given time. This is a timestamp in RFC 3339 format
Only show issues updated before the given time (RFC 3339 format)
Format: date-time
*/
@@ -78,49 +78,51 @@ type IssueSearchIssuesParams struct {
/* Created.
filter (issues / pulls) created by you, default is false
Filter issues or pulls created by the authenticated user
*/
Created *bool
/* Labels.
comma separated list of labels. Fetch only issues that have any of this labels. Non existent labels are discarded
Comma-separated list of label names. Fetch only issues that have any of these labels. Non existent labels are discarded.
*/
Labels *string
/* Limit.
page size of results
Number of items per page
*/
Limit *int64
/* Mentioned.
filter (issues / pulls) mentioning you, default is false
Filter issues or pulls mentioning the authenticated user
*/
Mentioned *bool
/* Milestones.
comma separated list of milestone names. Fetch only issues that have any of this milestones. Non existent are discarded
Comma-separated list of milestone names. Fetch only issues that have any of these milestones. Non existent milestones are discarded.
*/
Milestones *string
/* Owner.
filter by owner
Filter by repository owner
*/
Owner *string
/* Page.
page number of results to return (1-based)
Page number of results to return (1-based)
Default: 1
*/
Page *int64
/* PriorityRepoID.
repository to prioritize in the results
Repository ID to prioritize in the results
Format: int64
*/
@@ -128,25 +130,25 @@ type IssueSearchIssuesParams struct {
/* Q.
search string
Search string
*/
Q *string
/* ReviewRequested.
filter pulls requesting your review, default is false
Filter pull requests where the authenticated user's review was requested
*/
ReviewRequested *bool
/* Reviewed.
filter pulls reviewed by you, default is false
Filter pull requests reviewed by the authenticated user
*/
Reviewed *bool
/* Since.
Only show notifications updated after the given time. This is a timestamp in RFC 3339 format
Only show issues updated after the given time (RFC 3339 format)
Format: date-time
*/
@@ -154,19 +156,21 @@ type IssueSearchIssuesParams struct {
/* State.
whether issue is open or closed
State of the issue
Default: "open"
*/
State *string
/* Team.
filter by team (requires organization owner parameter to be provided)
Filter by team (requires organization owner parameter)
*/
Team *string
/* Type.
filter by type (issues / pulls) if set
Filter by issue type
*/
Type *string
@@ -187,7 +191,36 @@ func (o *IssueSearchIssuesParams) WithDefaults() *IssueSearchIssuesParams {
//
// All values with no default are reset to their zero value.
func (o *IssueSearchIssuesParams) SetDefaults() {
// no default values defined for this parameter
var (
assignedDefault = bool(false)
createdDefault = bool(false)
mentionedDefault = bool(false)
pageDefault = int64(1)
reviewRequestedDefault = bool(false)
reviewedDefault = bool(false)
stateDefault = string("open")
)
val := IssueSearchIssuesParams{
Assigned: &assignedDefault,
Created: &createdDefault,
Mentioned: &mentionedDefault,
Page: &pageDefault,
ReviewRequested: &reviewRequestedDefault,
Reviewed: &reviewedDefault,
State: &stateDefault,
}
val.timeout = o.timeout
val.Context = o.Context
val.HTTPClient = o.HTTPClient
*o = val
}
// WithTimeout adds the timeout to the issue search issues params

View File

@@ -30,6 +30,18 @@ func (o *IssueSearchIssuesReader) ReadResponse(response runtime.ClientResponse,
return nil, err
}
return result, nil
case 400:
result := NewIssueSearchIssuesBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 422:
result := NewIssueSearchIssuesUnprocessableEntity()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("[GET /repos/issues/search] issueSearchIssues", response, response.Code())
}
@@ -102,3 +114,147 @@ func (o *IssueSearchIssuesOK) readResponse(response runtime.ClientResponse, cons
return nil
}
// NewIssueSearchIssuesBadRequest creates a IssueSearchIssuesBadRequest with default headers values
func NewIssueSearchIssuesBadRequest() *IssueSearchIssuesBadRequest {
return &IssueSearchIssuesBadRequest{}
}
/*
IssueSearchIssuesBadRequest describes a response with status code 400, with default header values.
APIError is error format response
*/
type IssueSearchIssuesBadRequest struct {
Message string
URL string
}
// IsSuccess returns true when this issue search issues bad request response has a 2xx status code
func (o *IssueSearchIssuesBadRequest) IsSuccess() bool {
return false
}
// IsRedirect returns true when this issue search issues bad request response has a 3xx status code
func (o *IssueSearchIssuesBadRequest) IsRedirect() bool {
return false
}
// IsClientError returns true when this issue search issues bad request response has a 4xx status code
func (o *IssueSearchIssuesBadRequest) IsClientError() bool {
return true
}
// IsServerError returns true when this issue search issues bad request response has a 5xx status code
func (o *IssueSearchIssuesBadRequest) IsServerError() bool {
return false
}
// IsCode returns true when this issue search issues bad request response a status code equal to that given
func (o *IssueSearchIssuesBadRequest) IsCode(code int) bool {
return code == 400
}
// Code gets the status code for the issue search issues bad request response
func (o *IssueSearchIssuesBadRequest) Code() int {
return 400
}
func (o *IssueSearchIssuesBadRequest) Error() string {
return fmt.Sprintf("[GET /repos/issues/search][%d] issueSearchIssuesBadRequest", 400)
}
func (o *IssueSearchIssuesBadRequest) String() string {
return fmt.Sprintf("[GET /repos/issues/search][%d] issueSearchIssuesBadRequest", 400)
}
func (o *IssueSearchIssuesBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}
// NewIssueSearchIssuesUnprocessableEntity creates a IssueSearchIssuesUnprocessableEntity with default headers values
func NewIssueSearchIssuesUnprocessableEntity() *IssueSearchIssuesUnprocessableEntity {
return &IssueSearchIssuesUnprocessableEntity{}
}
/*
IssueSearchIssuesUnprocessableEntity describes a response with status code 422, with default header values.
APIValidationError is error format response related to input validation
*/
type IssueSearchIssuesUnprocessableEntity struct {
Message string
URL string
}
// IsSuccess returns true when this issue search issues unprocessable entity response has a 2xx status code
func (o *IssueSearchIssuesUnprocessableEntity) IsSuccess() bool {
return false
}
// IsRedirect returns true when this issue search issues unprocessable entity response has a 3xx status code
func (o *IssueSearchIssuesUnprocessableEntity) IsRedirect() bool {
return false
}
// IsClientError returns true when this issue search issues unprocessable entity response has a 4xx status code
func (o *IssueSearchIssuesUnprocessableEntity) IsClientError() bool {
return true
}
// IsServerError returns true when this issue search issues unprocessable entity response has a 5xx status code
func (o *IssueSearchIssuesUnprocessableEntity) IsServerError() bool {
return false
}
// IsCode returns true when this issue search issues unprocessable entity response a status code equal to that given
func (o *IssueSearchIssuesUnprocessableEntity) IsCode(code int) bool {
return code == 422
}
// Code gets the status code for the issue search issues unprocessable entity response
func (o *IssueSearchIssuesUnprocessableEntity) Code() int {
return 422
}
func (o *IssueSearchIssuesUnprocessableEntity) Error() string {
return fmt.Sprintf("[GET /repos/issues/search][%d] issueSearchIssuesUnprocessableEntity", 422)
}
func (o *IssueSearchIssuesUnprocessableEntity) String() string {
return fmt.Sprintf("[GET /repos/issues/search][%d] issueSearchIssuesUnprocessableEntity", 422)
}
func (o *IssueSearchIssuesUnprocessableEntity) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}

View File

@@ -0,0 +1,242 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// NewListActionTasksParams creates a new ListActionTasksParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewListActionTasksParams() *ListActionTasksParams {
return &ListActionTasksParams{
timeout: cr.DefaultTimeout,
}
}
// NewListActionTasksParamsWithTimeout creates a new ListActionTasksParams object
// with the ability to set a timeout on a request.
func NewListActionTasksParamsWithTimeout(timeout time.Duration) *ListActionTasksParams {
return &ListActionTasksParams{
timeout: timeout,
}
}
// NewListActionTasksParamsWithContext creates a new ListActionTasksParams object
// with the ability to set a context for a request.
func NewListActionTasksParamsWithContext(ctx context.Context) *ListActionTasksParams {
return &ListActionTasksParams{
Context: ctx,
}
}
// NewListActionTasksParamsWithHTTPClient creates a new ListActionTasksParams object
// with the ability to set a custom HTTPClient for a request.
func NewListActionTasksParamsWithHTTPClient(client *http.Client) *ListActionTasksParams {
return &ListActionTasksParams{
HTTPClient: client,
}
}
/*
ListActionTasksParams contains all the parameters to send to the API endpoint
for the list action tasks operation.
Typically these are written to a http.Request.
*/
type ListActionTasksParams struct {
/* Limit.
page size of results, default maximum page size is 50
*/
Limit *int64
/* Owner.
owner of the repo
*/
Owner string
/* Page.
page number of results to return (1-based)
*/
Page *int64
/* Repo.
name of the repo
*/
Repo string
timeout time.Duration
Context context.Context
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the list action tasks params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *ListActionTasksParams) WithDefaults() *ListActionTasksParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the list action tasks params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *ListActionTasksParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the list action tasks params
func (o *ListActionTasksParams) WithTimeout(timeout time.Duration) *ListActionTasksParams {
o.SetTimeout(timeout)
return o
}
// SetTimeout adds the timeout to the list action tasks params
func (o *ListActionTasksParams) SetTimeout(timeout time.Duration) {
o.timeout = timeout
}
// WithContext adds the context to the list action tasks params
func (o *ListActionTasksParams) WithContext(ctx context.Context) *ListActionTasksParams {
o.SetContext(ctx)
return o
}
// SetContext adds the context to the list action tasks params
func (o *ListActionTasksParams) SetContext(ctx context.Context) {
o.Context = ctx
}
// WithHTTPClient adds the HTTPClient to the list action tasks params
func (o *ListActionTasksParams) WithHTTPClient(client *http.Client) *ListActionTasksParams {
o.SetHTTPClient(client)
return o
}
// SetHTTPClient adds the HTTPClient to the list action tasks params
func (o *ListActionTasksParams) SetHTTPClient(client *http.Client) {
o.HTTPClient = client
}
// WithLimit adds the limit to the list action tasks params
func (o *ListActionTasksParams) WithLimit(limit *int64) *ListActionTasksParams {
o.SetLimit(limit)
return o
}
// SetLimit adds the limit to the list action tasks params
func (o *ListActionTasksParams) SetLimit(limit *int64) {
o.Limit = limit
}
// WithOwner adds the owner to the list action tasks params
func (o *ListActionTasksParams) WithOwner(owner string) *ListActionTasksParams {
o.SetOwner(owner)
return o
}
// SetOwner adds the owner to the list action tasks params
func (o *ListActionTasksParams) SetOwner(owner string) {
o.Owner = owner
}
// WithPage adds the page to the list action tasks params
func (o *ListActionTasksParams) WithPage(page *int64) *ListActionTasksParams {
o.SetPage(page)
return o
}
// SetPage adds the page to the list action tasks params
func (o *ListActionTasksParams) SetPage(page *int64) {
o.Page = page
}
// WithRepo adds the repo to the list action tasks params
func (o *ListActionTasksParams) WithRepo(repo string) *ListActionTasksParams {
o.SetRepo(repo)
return o
}
// SetRepo adds the repo to the list action tasks params
func (o *ListActionTasksParams) SetRepo(repo string) {
o.Repo = repo
}
// WriteToRequest writes these params to a swagger request
func (o *ListActionTasksParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
if err := r.SetTimeout(o.timeout); err != nil {
return err
}
var res []error
if o.Limit != nil {
// query param limit
var qrLimit int64
if o.Limit != nil {
qrLimit = *o.Limit
}
qLimit := swag.FormatInt64(qrLimit)
if qLimit != "" {
if err := r.SetQueryParam("limit", qLimit); err != nil {
return err
}
}
}
// path param owner
if err := r.SetPathParam("owner", o.Owner); err != nil {
return err
}
if o.Page != nil {
// query param page
var qrPage int64
if o.Page != nil {
qrPage = *o.Page
}
qPage := swag.FormatInt64(qrPage)
if qPage != "" {
if err := r.SetQueryParam("page", qPage); err != nil {
return err
}
}
}
// path param repo
if err := r.SetPathParam("repo", o.Repo); err != nil {
return err
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,464 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"encoding/json"
"fmt"
"io"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
// ListActionTasksReader is a Reader for the ListActionTasks structure.
type ListActionTasksReader struct {
formats strfmt.Registry
}
// ReadResponse reads a server response into the received o.
func (o *ListActionTasksReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 200:
result := NewListActionTasksOK()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
case 400:
result := NewListActionTasksBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 403:
result := NewListActionTasksForbidden()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 404:
result := NewListActionTasksNotFound()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 409:
result := NewListActionTasksConflict()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 422:
result := NewListActionTasksUnprocessableEntity()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("[GET /repos/{owner}/{repo}/actions/tasks] ListActionTasks", response, response.Code())
}
}
// NewListActionTasksOK creates a ListActionTasksOK with default headers values
func NewListActionTasksOK() *ListActionTasksOK {
return &ListActionTasksOK{}
}
/*
ListActionTasksOK describes a response with status code 200, with default header values.
TasksList
*/
type ListActionTasksOK struct {
Payload *models.ActionTaskResponse
}
// IsSuccess returns true when this list action tasks o k response has a 2xx status code
func (o *ListActionTasksOK) IsSuccess() bool {
return true
}
// IsRedirect returns true when this list action tasks o k response has a 3xx status code
func (o *ListActionTasksOK) IsRedirect() bool {
return false
}
// IsClientError returns true when this list action tasks o k response has a 4xx status code
func (o *ListActionTasksOK) IsClientError() bool {
return false
}
// IsServerError returns true when this list action tasks o k response has a 5xx status code
func (o *ListActionTasksOK) IsServerError() bool {
return false
}
// IsCode returns true when this list action tasks o k response a status code equal to that given
func (o *ListActionTasksOK) IsCode(code int) bool {
return code == 200
}
// Code gets the status code for the list action tasks o k response
func (o *ListActionTasksOK) Code() int {
return 200
}
func (o *ListActionTasksOK) Error() string {
payload, _ := json.Marshal(o.Payload)
return fmt.Sprintf("[GET /repos/{owner}/{repo}/actions/tasks][%d] listActionTasksOK %s", 200, payload)
}
func (o *ListActionTasksOK) String() string {
payload, _ := json.Marshal(o.Payload)
return fmt.Sprintf("[GET /repos/{owner}/{repo}/actions/tasks][%d] listActionTasksOK %s", 200, payload)
}
func (o *ListActionTasksOK) GetPayload() *models.ActionTaskResponse {
return o.Payload
}
func (o *ListActionTasksOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.ActionTaskResponse)
// response payload
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
return err
}
return nil
}
// NewListActionTasksBadRequest creates a ListActionTasksBadRequest with default headers values
func NewListActionTasksBadRequest() *ListActionTasksBadRequest {
return &ListActionTasksBadRequest{}
}
/*
ListActionTasksBadRequest describes a response with status code 400, with default header values.
APIError is error format response
*/
type ListActionTasksBadRequest struct {
Message string
URL string
}
// IsSuccess returns true when this list action tasks bad request response has a 2xx status code
func (o *ListActionTasksBadRequest) IsSuccess() bool {
return false
}
// IsRedirect returns true when this list action tasks bad request response has a 3xx status code
func (o *ListActionTasksBadRequest) IsRedirect() bool {
return false
}
// IsClientError returns true when this list action tasks bad request response has a 4xx status code
func (o *ListActionTasksBadRequest) IsClientError() bool {
return true
}
// IsServerError returns true when this list action tasks bad request response has a 5xx status code
func (o *ListActionTasksBadRequest) IsServerError() bool {
return false
}
// IsCode returns true when this list action tasks bad request response a status code equal to that given
func (o *ListActionTasksBadRequest) IsCode(code int) bool {
return code == 400
}
// Code gets the status code for the list action tasks bad request response
func (o *ListActionTasksBadRequest) Code() int {
return 400
}
func (o *ListActionTasksBadRequest) Error() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/actions/tasks][%d] listActionTasksBadRequest", 400)
}
func (o *ListActionTasksBadRequest) String() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/actions/tasks][%d] listActionTasksBadRequest", 400)
}
func (o *ListActionTasksBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}
// NewListActionTasksForbidden creates a ListActionTasksForbidden with default headers values
func NewListActionTasksForbidden() *ListActionTasksForbidden {
return &ListActionTasksForbidden{}
}
/*
ListActionTasksForbidden describes a response with status code 403, with default header values.
APIForbiddenError is a forbidden error response
*/
type ListActionTasksForbidden struct {
Message string
URL string
}
// IsSuccess returns true when this list action tasks forbidden response has a 2xx status code
func (o *ListActionTasksForbidden) IsSuccess() bool {
return false
}
// IsRedirect returns true when this list action tasks forbidden response has a 3xx status code
func (o *ListActionTasksForbidden) IsRedirect() bool {
return false
}
// IsClientError returns true when this list action tasks forbidden response has a 4xx status code
func (o *ListActionTasksForbidden) IsClientError() bool {
return true
}
// IsServerError returns true when this list action tasks forbidden response has a 5xx status code
func (o *ListActionTasksForbidden) IsServerError() bool {
return false
}
// IsCode returns true when this list action tasks forbidden response a status code equal to that given
func (o *ListActionTasksForbidden) IsCode(code int) bool {
return code == 403
}
// Code gets the status code for the list action tasks forbidden response
func (o *ListActionTasksForbidden) Code() int {
return 403
}
func (o *ListActionTasksForbidden) Error() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/actions/tasks][%d] listActionTasksForbidden", 403)
}
func (o *ListActionTasksForbidden) String() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/actions/tasks][%d] listActionTasksForbidden", 403)
}
func (o *ListActionTasksForbidden) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}
// NewListActionTasksNotFound creates a ListActionTasksNotFound with default headers values
func NewListActionTasksNotFound() *ListActionTasksNotFound {
return &ListActionTasksNotFound{}
}
/*
ListActionTasksNotFound describes a response with status code 404, with default header values.
APINotFound is a not found empty response
*/
type ListActionTasksNotFound struct {
}
// IsSuccess returns true when this list action tasks not found response has a 2xx status code
func (o *ListActionTasksNotFound) IsSuccess() bool {
return false
}
// IsRedirect returns true when this list action tasks not found response has a 3xx status code
func (o *ListActionTasksNotFound) IsRedirect() bool {
return false
}
// IsClientError returns true when this list action tasks not found response has a 4xx status code
func (o *ListActionTasksNotFound) IsClientError() bool {
return true
}
// IsServerError returns true when this list action tasks not found response has a 5xx status code
func (o *ListActionTasksNotFound) IsServerError() bool {
return false
}
// IsCode returns true when this list action tasks not found response a status code equal to that given
func (o *ListActionTasksNotFound) IsCode(code int) bool {
return code == 404
}
// Code gets the status code for the list action tasks not found response
func (o *ListActionTasksNotFound) Code() int {
return 404
}
func (o *ListActionTasksNotFound) Error() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/actions/tasks][%d] listActionTasksNotFound", 404)
}
func (o *ListActionTasksNotFound) String() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/actions/tasks][%d] listActionTasksNotFound", 404)
}
func (o *ListActionTasksNotFound) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}
// NewListActionTasksConflict creates a ListActionTasksConflict with default headers values
func NewListActionTasksConflict() *ListActionTasksConflict {
return &ListActionTasksConflict{}
}
/*
ListActionTasksConflict describes a response with status code 409, with default header values.
APIConflict is a conflict empty response
*/
type ListActionTasksConflict struct {
}
// IsSuccess returns true when this list action tasks conflict response has a 2xx status code
func (o *ListActionTasksConflict) IsSuccess() bool {
return false
}
// IsRedirect returns true when this list action tasks conflict response has a 3xx status code
func (o *ListActionTasksConflict) IsRedirect() bool {
return false
}
// IsClientError returns true when this list action tasks conflict response has a 4xx status code
func (o *ListActionTasksConflict) IsClientError() bool {
return true
}
// IsServerError returns true when this list action tasks conflict response has a 5xx status code
func (o *ListActionTasksConflict) IsServerError() bool {
return false
}
// IsCode returns true when this list action tasks conflict response a status code equal to that given
func (o *ListActionTasksConflict) IsCode(code int) bool {
return code == 409
}
// Code gets the status code for the list action tasks conflict response
func (o *ListActionTasksConflict) Code() int {
return 409
}
func (o *ListActionTasksConflict) Error() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/actions/tasks][%d] listActionTasksConflict", 409)
}
func (o *ListActionTasksConflict) String() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/actions/tasks][%d] listActionTasksConflict", 409)
}
func (o *ListActionTasksConflict) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}
// NewListActionTasksUnprocessableEntity creates a ListActionTasksUnprocessableEntity with default headers values
func NewListActionTasksUnprocessableEntity() *ListActionTasksUnprocessableEntity {
return &ListActionTasksUnprocessableEntity{}
}
/*
ListActionTasksUnprocessableEntity describes a response with status code 422, with default header values.
APIValidationError is error format response related to input validation
*/
type ListActionTasksUnprocessableEntity struct {
Message string
URL string
}
// IsSuccess returns true when this list action tasks unprocessable entity response has a 2xx status code
func (o *ListActionTasksUnprocessableEntity) IsSuccess() bool {
return false
}
// IsRedirect returns true when this list action tasks unprocessable entity response has a 3xx status code
func (o *ListActionTasksUnprocessableEntity) IsRedirect() bool {
return false
}
// IsClientError returns true when this list action tasks unprocessable entity response has a 4xx status code
func (o *ListActionTasksUnprocessableEntity) IsClientError() bool {
return true
}
// IsServerError returns true when this list action tasks unprocessable entity response has a 5xx status code
func (o *ListActionTasksUnprocessableEntity) IsServerError() bool {
return false
}
// IsCode returns true when this list action tasks unprocessable entity response a status code equal to that given
func (o *ListActionTasksUnprocessableEntity) IsCode(code int) bool {
return code == 422
}
// Code gets the status code for the list action tasks unprocessable entity response
func (o *ListActionTasksUnprocessableEntity) Code() int {
return 422
}
func (o *ListActionTasksUnprocessableEntity) Error() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/actions/tasks][%d] listActionTasksUnprocessableEntity", 422)
}
func (o *ListActionTasksUnprocessableEntity) String() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/actions/tasks][%d] listActionTasksUnprocessableEntity", 422)
}
func (o *ListActionTasksUnprocessableEntity) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}

View File

@@ -0,0 +1,194 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
// NewRepoCreateTagProtectionParams creates a new RepoCreateTagProtectionParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewRepoCreateTagProtectionParams() *RepoCreateTagProtectionParams {
return &RepoCreateTagProtectionParams{
timeout: cr.DefaultTimeout,
}
}
// NewRepoCreateTagProtectionParamsWithTimeout creates a new RepoCreateTagProtectionParams object
// with the ability to set a timeout on a request.
func NewRepoCreateTagProtectionParamsWithTimeout(timeout time.Duration) *RepoCreateTagProtectionParams {
return &RepoCreateTagProtectionParams{
timeout: timeout,
}
}
// NewRepoCreateTagProtectionParamsWithContext creates a new RepoCreateTagProtectionParams object
// with the ability to set a context for a request.
func NewRepoCreateTagProtectionParamsWithContext(ctx context.Context) *RepoCreateTagProtectionParams {
return &RepoCreateTagProtectionParams{
Context: ctx,
}
}
// NewRepoCreateTagProtectionParamsWithHTTPClient creates a new RepoCreateTagProtectionParams object
// with the ability to set a custom HTTPClient for a request.
func NewRepoCreateTagProtectionParamsWithHTTPClient(client *http.Client) *RepoCreateTagProtectionParams {
return &RepoCreateTagProtectionParams{
HTTPClient: client,
}
}
/*
RepoCreateTagProtectionParams contains all the parameters to send to the API endpoint
for the repo create tag protection operation.
Typically these are written to a http.Request.
*/
type RepoCreateTagProtectionParams struct {
// Body.
Body *models.CreateTagProtectionOption
/* Owner.
owner of the repo
*/
Owner string
/* Repo.
name of the repo
*/
Repo string
timeout time.Duration
Context context.Context
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the repo create tag protection params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoCreateTagProtectionParams) WithDefaults() *RepoCreateTagProtectionParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the repo create tag protection params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoCreateTagProtectionParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the repo create tag protection params
func (o *RepoCreateTagProtectionParams) WithTimeout(timeout time.Duration) *RepoCreateTagProtectionParams {
o.SetTimeout(timeout)
return o
}
// SetTimeout adds the timeout to the repo create tag protection params
func (o *RepoCreateTagProtectionParams) SetTimeout(timeout time.Duration) {
o.timeout = timeout
}
// WithContext adds the context to the repo create tag protection params
func (o *RepoCreateTagProtectionParams) WithContext(ctx context.Context) *RepoCreateTagProtectionParams {
o.SetContext(ctx)
return o
}
// SetContext adds the context to the repo create tag protection params
func (o *RepoCreateTagProtectionParams) SetContext(ctx context.Context) {
o.Context = ctx
}
// WithHTTPClient adds the HTTPClient to the repo create tag protection params
func (o *RepoCreateTagProtectionParams) WithHTTPClient(client *http.Client) *RepoCreateTagProtectionParams {
o.SetHTTPClient(client)
return o
}
// SetHTTPClient adds the HTTPClient to the repo create tag protection params
func (o *RepoCreateTagProtectionParams) SetHTTPClient(client *http.Client) {
o.HTTPClient = client
}
// WithBody adds the body to the repo create tag protection params
func (o *RepoCreateTagProtectionParams) WithBody(body *models.CreateTagProtectionOption) *RepoCreateTagProtectionParams {
o.SetBody(body)
return o
}
// SetBody adds the body to the repo create tag protection params
func (o *RepoCreateTagProtectionParams) SetBody(body *models.CreateTagProtectionOption) {
o.Body = body
}
// WithOwner adds the owner to the repo create tag protection params
func (o *RepoCreateTagProtectionParams) WithOwner(owner string) *RepoCreateTagProtectionParams {
o.SetOwner(owner)
return o
}
// SetOwner adds the owner to the repo create tag protection params
func (o *RepoCreateTagProtectionParams) SetOwner(owner string) {
o.Owner = owner
}
// WithRepo adds the repo to the repo create tag protection params
func (o *RepoCreateTagProtectionParams) WithRepo(repo string) *RepoCreateTagProtectionParams {
o.SetRepo(repo)
return o
}
// SetRepo adds the repo to the repo create tag protection params
func (o *RepoCreateTagProtectionParams) SetRepo(repo string) {
o.Repo = repo
}
// WriteToRequest writes these params to a swagger request
func (o *RepoCreateTagProtectionParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
if err := r.SetTimeout(o.timeout); err != nil {
return err
}
var res []error
if o.Body != nil {
if err := r.SetBodyParam(o.Body); err != nil {
return err
}
}
// path param owner
if err := r.SetPathParam("owner", o.Owner); err != nil {
return err
}
// path param repo
if err := r.SetPathParam("repo", o.Repo); err != nil {
return err
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,402 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"encoding/json"
"fmt"
"io"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
// RepoCreateTagProtectionReader is a Reader for the RepoCreateTagProtection structure.
type RepoCreateTagProtectionReader struct {
formats strfmt.Registry
}
// ReadResponse reads a server response into the received o.
func (o *RepoCreateTagProtectionReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 201:
result := NewRepoCreateTagProtectionCreated()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
case 403:
result := NewRepoCreateTagProtectionForbidden()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 404:
result := NewRepoCreateTagProtectionNotFound()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 422:
result := NewRepoCreateTagProtectionUnprocessableEntity()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 423:
result := NewRepoCreateTagProtectionLocked()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("[POST /repos/{owner}/{repo}/tag_protections] repoCreateTagProtection", response, response.Code())
}
}
// NewRepoCreateTagProtectionCreated creates a RepoCreateTagProtectionCreated with default headers values
func NewRepoCreateTagProtectionCreated() *RepoCreateTagProtectionCreated {
return &RepoCreateTagProtectionCreated{}
}
/*
RepoCreateTagProtectionCreated describes a response with status code 201, with default header values.
TagProtection
*/
type RepoCreateTagProtectionCreated struct {
Payload *models.TagProtection
}
// IsSuccess returns true when this repo create tag protection created response has a 2xx status code
func (o *RepoCreateTagProtectionCreated) IsSuccess() bool {
return true
}
// IsRedirect returns true when this repo create tag protection created response has a 3xx status code
func (o *RepoCreateTagProtectionCreated) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo create tag protection created response has a 4xx status code
func (o *RepoCreateTagProtectionCreated) IsClientError() bool {
return false
}
// IsServerError returns true when this repo create tag protection created response has a 5xx status code
func (o *RepoCreateTagProtectionCreated) IsServerError() bool {
return false
}
// IsCode returns true when this repo create tag protection created response a status code equal to that given
func (o *RepoCreateTagProtectionCreated) IsCode(code int) bool {
return code == 201
}
// Code gets the status code for the repo create tag protection created response
func (o *RepoCreateTagProtectionCreated) Code() int {
return 201
}
func (o *RepoCreateTagProtectionCreated) Error() string {
payload, _ := json.Marshal(o.Payload)
return fmt.Sprintf("[POST /repos/{owner}/{repo}/tag_protections][%d] repoCreateTagProtectionCreated %s", 201, payload)
}
func (o *RepoCreateTagProtectionCreated) String() string {
payload, _ := json.Marshal(o.Payload)
return fmt.Sprintf("[POST /repos/{owner}/{repo}/tag_protections][%d] repoCreateTagProtectionCreated %s", 201, payload)
}
func (o *RepoCreateTagProtectionCreated) GetPayload() *models.TagProtection {
return o.Payload
}
func (o *RepoCreateTagProtectionCreated) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.TagProtection)
// response payload
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
return err
}
return nil
}
// NewRepoCreateTagProtectionForbidden creates a RepoCreateTagProtectionForbidden with default headers values
func NewRepoCreateTagProtectionForbidden() *RepoCreateTagProtectionForbidden {
return &RepoCreateTagProtectionForbidden{}
}
/*
RepoCreateTagProtectionForbidden describes a response with status code 403, with default header values.
APIForbiddenError is a forbidden error response
*/
type RepoCreateTagProtectionForbidden struct {
Message string
URL string
}
// IsSuccess returns true when this repo create tag protection forbidden response has a 2xx status code
func (o *RepoCreateTagProtectionForbidden) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo create tag protection forbidden response has a 3xx status code
func (o *RepoCreateTagProtectionForbidden) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo create tag protection forbidden response has a 4xx status code
func (o *RepoCreateTagProtectionForbidden) IsClientError() bool {
return true
}
// IsServerError returns true when this repo create tag protection forbidden response has a 5xx status code
func (o *RepoCreateTagProtectionForbidden) IsServerError() bool {
return false
}
// IsCode returns true when this repo create tag protection forbidden response a status code equal to that given
func (o *RepoCreateTagProtectionForbidden) IsCode(code int) bool {
return code == 403
}
// Code gets the status code for the repo create tag protection forbidden response
func (o *RepoCreateTagProtectionForbidden) Code() int {
return 403
}
func (o *RepoCreateTagProtectionForbidden) Error() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/tag_protections][%d] repoCreateTagProtectionForbidden", 403)
}
func (o *RepoCreateTagProtectionForbidden) String() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/tag_protections][%d] repoCreateTagProtectionForbidden", 403)
}
func (o *RepoCreateTagProtectionForbidden) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}
// NewRepoCreateTagProtectionNotFound creates a RepoCreateTagProtectionNotFound with default headers values
func NewRepoCreateTagProtectionNotFound() *RepoCreateTagProtectionNotFound {
return &RepoCreateTagProtectionNotFound{}
}
/*
RepoCreateTagProtectionNotFound describes a response with status code 404, with default header values.
APINotFound is a not found empty response
*/
type RepoCreateTagProtectionNotFound struct {
}
// IsSuccess returns true when this repo create tag protection not found response has a 2xx status code
func (o *RepoCreateTagProtectionNotFound) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo create tag protection not found response has a 3xx status code
func (o *RepoCreateTagProtectionNotFound) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo create tag protection not found response has a 4xx status code
func (o *RepoCreateTagProtectionNotFound) IsClientError() bool {
return true
}
// IsServerError returns true when this repo create tag protection not found response has a 5xx status code
func (o *RepoCreateTagProtectionNotFound) IsServerError() bool {
return false
}
// IsCode returns true when this repo create tag protection not found response a status code equal to that given
func (o *RepoCreateTagProtectionNotFound) IsCode(code int) bool {
return code == 404
}
// Code gets the status code for the repo create tag protection not found response
func (o *RepoCreateTagProtectionNotFound) Code() int {
return 404
}
func (o *RepoCreateTagProtectionNotFound) Error() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/tag_protections][%d] repoCreateTagProtectionNotFound", 404)
}
func (o *RepoCreateTagProtectionNotFound) String() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/tag_protections][%d] repoCreateTagProtectionNotFound", 404)
}
func (o *RepoCreateTagProtectionNotFound) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}
// NewRepoCreateTagProtectionUnprocessableEntity creates a RepoCreateTagProtectionUnprocessableEntity with default headers values
func NewRepoCreateTagProtectionUnprocessableEntity() *RepoCreateTagProtectionUnprocessableEntity {
return &RepoCreateTagProtectionUnprocessableEntity{}
}
/*
RepoCreateTagProtectionUnprocessableEntity describes a response with status code 422, with default header values.
APIValidationError is error format response related to input validation
*/
type RepoCreateTagProtectionUnprocessableEntity struct {
Message string
URL string
}
// IsSuccess returns true when this repo create tag protection unprocessable entity response has a 2xx status code
func (o *RepoCreateTagProtectionUnprocessableEntity) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo create tag protection unprocessable entity response has a 3xx status code
func (o *RepoCreateTagProtectionUnprocessableEntity) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo create tag protection unprocessable entity response has a 4xx status code
func (o *RepoCreateTagProtectionUnprocessableEntity) IsClientError() bool {
return true
}
// IsServerError returns true when this repo create tag protection unprocessable entity response has a 5xx status code
func (o *RepoCreateTagProtectionUnprocessableEntity) IsServerError() bool {
return false
}
// IsCode returns true when this repo create tag protection unprocessable entity response a status code equal to that given
func (o *RepoCreateTagProtectionUnprocessableEntity) IsCode(code int) bool {
return code == 422
}
// Code gets the status code for the repo create tag protection unprocessable entity response
func (o *RepoCreateTagProtectionUnprocessableEntity) Code() int {
return 422
}
func (o *RepoCreateTagProtectionUnprocessableEntity) Error() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/tag_protections][%d] repoCreateTagProtectionUnprocessableEntity", 422)
}
func (o *RepoCreateTagProtectionUnprocessableEntity) String() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/tag_protections][%d] repoCreateTagProtectionUnprocessableEntity", 422)
}
func (o *RepoCreateTagProtectionUnprocessableEntity) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}
// NewRepoCreateTagProtectionLocked creates a RepoCreateTagProtectionLocked with default headers values
func NewRepoCreateTagProtectionLocked() *RepoCreateTagProtectionLocked {
return &RepoCreateTagProtectionLocked{}
}
/*
RepoCreateTagProtectionLocked describes a response with status code 423, with default header values.
APIRepoArchivedError is an error that is raised when an archived repo should be modified
*/
type RepoCreateTagProtectionLocked struct {
Message string
URL string
}
// IsSuccess returns true when this repo create tag protection locked response has a 2xx status code
func (o *RepoCreateTagProtectionLocked) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo create tag protection locked response has a 3xx status code
func (o *RepoCreateTagProtectionLocked) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo create tag protection locked response has a 4xx status code
func (o *RepoCreateTagProtectionLocked) IsClientError() bool {
return true
}
// IsServerError returns true when this repo create tag protection locked response has a 5xx status code
func (o *RepoCreateTagProtectionLocked) IsServerError() bool {
return false
}
// IsCode returns true when this repo create tag protection locked response a status code equal to that given
func (o *RepoCreateTagProtectionLocked) IsCode(code int) bool {
return code == 423
}
// Code gets the status code for the repo create tag protection locked response
func (o *RepoCreateTagProtectionLocked) Code() int {
return 423
}
func (o *RepoCreateTagProtectionLocked) Error() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/tag_protections][%d] repoCreateTagProtectionLocked", 423)
}
func (o *RepoCreateTagProtectionLocked) String() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/tag_protections][%d] repoCreateTagProtectionLocked", 423)
}
func (o *RepoCreateTagProtectionLocked) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}

View File

@@ -0,0 +1,196 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// NewRepoDeleteTagProtectionParams creates a new RepoDeleteTagProtectionParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewRepoDeleteTagProtectionParams() *RepoDeleteTagProtectionParams {
return &RepoDeleteTagProtectionParams{
timeout: cr.DefaultTimeout,
}
}
// NewRepoDeleteTagProtectionParamsWithTimeout creates a new RepoDeleteTagProtectionParams object
// with the ability to set a timeout on a request.
func NewRepoDeleteTagProtectionParamsWithTimeout(timeout time.Duration) *RepoDeleteTagProtectionParams {
return &RepoDeleteTagProtectionParams{
timeout: timeout,
}
}
// NewRepoDeleteTagProtectionParamsWithContext creates a new RepoDeleteTagProtectionParams object
// with the ability to set a context for a request.
func NewRepoDeleteTagProtectionParamsWithContext(ctx context.Context) *RepoDeleteTagProtectionParams {
return &RepoDeleteTagProtectionParams{
Context: ctx,
}
}
// NewRepoDeleteTagProtectionParamsWithHTTPClient creates a new RepoDeleteTagProtectionParams object
// with the ability to set a custom HTTPClient for a request.
func NewRepoDeleteTagProtectionParamsWithHTTPClient(client *http.Client) *RepoDeleteTagProtectionParams {
return &RepoDeleteTagProtectionParams{
HTTPClient: client,
}
}
/*
RepoDeleteTagProtectionParams contains all the parameters to send to the API endpoint
for the repo delete tag protection operation.
Typically these are written to a http.Request.
*/
type RepoDeleteTagProtectionParams struct {
/* ID.
id of protected tag
*/
ID int64
/* Owner.
owner of the repo
*/
Owner string
/* Repo.
name of the repo
*/
Repo string
timeout time.Duration
Context context.Context
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the repo delete tag protection params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoDeleteTagProtectionParams) WithDefaults() *RepoDeleteTagProtectionParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the repo delete tag protection params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoDeleteTagProtectionParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the repo delete tag protection params
func (o *RepoDeleteTagProtectionParams) WithTimeout(timeout time.Duration) *RepoDeleteTagProtectionParams {
o.SetTimeout(timeout)
return o
}
// SetTimeout adds the timeout to the repo delete tag protection params
func (o *RepoDeleteTagProtectionParams) SetTimeout(timeout time.Duration) {
o.timeout = timeout
}
// WithContext adds the context to the repo delete tag protection params
func (o *RepoDeleteTagProtectionParams) WithContext(ctx context.Context) *RepoDeleteTagProtectionParams {
o.SetContext(ctx)
return o
}
// SetContext adds the context to the repo delete tag protection params
func (o *RepoDeleteTagProtectionParams) SetContext(ctx context.Context) {
o.Context = ctx
}
// WithHTTPClient adds the HTTPClient to the repo delete tag protection params
func (o *RepoDeleteTagProtectionParams) WithHTTPClient(client *http.Client) *RepoDeleteTagProtectionParams {
o.SetHTTPClient(client)
return o
}
// SetHTTPClient adds the HTTPClient to the repo delete tag protection params
func (o *RepoDeleteTagProtectionParams) SetHTTPClient(client *http.Client) {
o.HTTPClient = client
}
// WithID adds the id to the repo delete tag protection params
func (o *RepoDeleteTagProtectionParams) WithID(id int64) *RepoDeleteTagProtectionParams {
o.SetID(id)
return o
}
// SetID adds the id to the repo delete tag protection params
func (o *RepoDeleteTagProtectionParams) SetID(id int64) {
o.ID = id
}
// WithOwner adds the owner to the repo delete tag protection params
func (o *RepoDeleteTagProtectionParams) WithOwner(owner string) *RepoDeleteTagProtectionParams {
o.SetOwner(owner)
return o
}
// SetOwner adds the owner to the repo delete tag protection params
func (o *RepoDeleteTagProtectionParams) SetOwner(owner string) {
o.Owner = owner
}
// WithRepo adds the repo to the repo delete tag protection params
func (o *RepoDeleteTagProtectionParams) WithRepo(repo string) *RepoDeleteTagProtectionParams {
o.SetRepo(repo)
return o
}
// SetRepo adds the repo to the repo delete tag protection params
func (o *RepoDeleteTagProtectionParams) SetRepo(repo string) {
o.Repo = repo
}
// WriteToRequest writes these params to a swagger request
func (o *RepoDeleteTagProtectionParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
if err := r.SetTimeout(o.timeout); err != nil {
return err
}
var res []error
// path param id
if err := r.SetPathParam("id", swag.FormatInt64(o.ID)); err != nil {
return err
}
// path param owner
if err := r.SetPathParam("owner", o.Owner); err != nil {
return err
}
// path param repo
if err := r.SetPathParam("repo", o.Repo); err != nil {
return err
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,150 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"fmt"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
)
// RepoDeleteTagProtectionReader is a Reader for the RepoDeleteTagProtection structure.
type RepoDeleteTagProtectionReader struct {
formats strfmt.Registry
}
// ReadResponse reads a server response into the received o.
func (o *RepoDeleteTagProtectionReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 204:
result := NewRepoDeleteTagProtectionNoContent()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
case 404:
result := NewRepoDeleteTagProtectionNotFound()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("[DELETE /repos/{owner}/{repo}/tag_protections/{id}] repoDeleteTagProtection", response, response.Code())
}
}
// NewRepoDeleteTagProtectionNoContent creates a RepoDeleteTagProtectionNoContent with default headers values
func NewRepoDeleteTagProtectionNoContent() *RepoDeleteTagProtectionNoContent {
return &RepoDeleteTagProtectionNoContent{}
}
/*
RepoDeleteTagProtectionNoContent describes a response with status code 204, with default header values.
APIEmpty is an empty response
*/
type RepoDeleteTagProtectionNoContent struct {
}
// IsSuccess returns true when this repo delete tag protection no content response has a 2xx status code
func (o *RepoDeleteTagProtectionNoContent) IsSuccess() bool {
return true
}
// IsRedirect returns true when this repo delete tag protection no content response has a 3xx status code
func (o *RepoDeleteTagProtectionNoContent) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo delete tag protection no content response has a 4xx status code
func (o *RepoDeleteTagProtectionNoContent) IsClientError() bool {
return false
}
// IsServerError returns true when this repo delete tag protection no content response has a 5xx status code
func (o *RepoDeleteTagProtectionNoContent) IsServerError() bool {
return false
}
// IsCode returns true when this repo delete tag protection no content response a status code equal to that given
func (o *RepoDeleteTagProtectionNoContent) IsCode(code int) bool {
return code == 204
}
// Code gets the status code for the repo delete tag protection no content response
func (o *RepoDeleteTagProtectionNoContent) Code() int {
return 204
}
func (o *RepoDeleteTagProtectionNoContent) Error() string {
return fmt.Sprintf("[DELETE /repos/{owner}/{repo}/tag_protections/{id}][%d] repoDeleteTagProtectionNoContent", 204)
}
func (o *RepoDeleteTagProtectionNoContent) String() string {
return fmt.Sprintf("[DELETE /repos/{owner}/{repo}/tag_protections/{id}][%d] repoDeleteTagProtectionNoContent", 204)
}
func (o *RepoDeleteTagProtectionNoContent) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}
// NewRepoDeleteTagProtectionNotFound creates a RepoDeleteTagProtectionNotFound with default headers values
func NewRepoDeleteTagProtectionNotFound() *RepoDeleteTagProtectionNotFound {
return &RepoDeleteTagProtectionNotFound{}
}
/*
RepoDeleteTagProtectionNotFound describes a response with status code 404, with default header values.
APINotFound is a not found empty response
*/
type RepoDeleteTagProtectionNotFound struct {
}
// IsSuccess returns true when this repo delete tag protection not found response has a 2xx status code
func (o *RepoDeleteTagProtectionNotFound) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo delete tag protection not found response has a 3xx status code
func (o *RepoDeleteTagProtectionNotFound) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo delete tag protection not found response has a 4xx status code
func (o *RepoDeleteTagProtectionNotFound) IsClientError() bool {
return true
}
// IsServerError returns true when this repo delete tag protection not found response has a 5xx status code
func (o *RepoDeleteTagProtectionNotFound) IsServerError() bool {
return false
}
// IsCode returns true when this repo delete tag protection not found response a status code equal to that given
func (o *RepoDeleteTagProtectionNotFound) IsCode(code int) bool {
return code == 404
}
// Code gets the status code for the repo delete tag protection not found response
func (o *RepoDeleteTagProtectionNotFound) Code() int {
return 404
}
func (o *RepoDeleteTagProtectionNotFound) Error() string {
return fmt.Sprintf("[DELETE /repos/{owner}/{repo}/tag_protections/{id}][%d] repoDeleteTagProtectionNotFound", 404)
}
func (o *RepoDeleteTagProtectionNotFound) String() string {
return fmt.Sprintf("[DELETE /repos/{owner}/{repo}/tag_protections/{id}][%d] repoDeleteTagProtectionNotFound", 404)
}
func (o *RepoDeleteTagProtectionNotFound) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}

View File

@@ -36,6 +36,12 @@ func (o *RepoEditReleaseAttachmentReader) ReadResponse(response runtime.ClientRe
return nil, err
}
return nil, result
case 422:
result := NewRepoEditReleaseAttachmentUnprocessableEntity()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("[PATCH /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id}] repoEditReleaseAttachment", response, response.Code())
}
@@ -166,3 +172,75 @@ func (o *RepoEditReleaseAttachmentNotFound) readResponse(response runtime.Client
return nil
}
// NewRepoEditReleaseAttachmentUnprocessableEntity creates a RepoEditReleaseAttachmentUnprocessableEntity with default headers values
func NewRepoEditReleaseAttachmentUnprocessableEntity() *RepoEditReleaseAttachmentUnprocessableEntity {
return &RepoEditReleaseAttachmentUnprocessableEntity{}
}
/*
RepoEditReleaseAttachmentUnprocessableEntity describes a response with status code 422, with default header values.
APIValidationError is error format response related to input validation
*/
type RepoEditReleaseAttachmentUnprocessableEntity struct {
Message string
URL string
}
// IsSuccess returns true when this repo edit release attachment unprocessable entity response has a 2xx status code
func (o *RepoEditReleaseAttachmentUnprocessableEntity) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo edit release attachment unprocessable entity response has a 3xx status code
func (o *RepoEditReleaseAttachmentUnprocessableEntity) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo edit release attachment unprocessable entity response has a 4xx status code
func (o *RepoEditReleaseAttachmentUnprocessableEntity) IsClientError() bool {
return true
}
// IsServerError returns true when this repo edit release attachment unprocessable entity response has a 5xx status code
func (o *RepoEditReleaseAttachmentUnprocessableEntity) IsServerError() bool {
return false
}
// IsCode returns true when this repo edit release attachment unprocessable entity response a status code equal to that given
func (o *RepoEditReleaseAttachmentUnprocessableEntity) IsCode(code int) bool {
return code == 422
}
// Code gets the status code for the repo edit release attachment unprocessable entity response
func (o *RepoEditReleaseAttachmentUnprocessableEntity) Code() int {
return 422
}
func (o *RepoEditReleaseAttachmentUnprocessableEntity) Error() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id}][%d] repoEditReleaseAttachmentUnprocessableEntity", 422)
}
func (o *RepoEditReleaseAttachmentUnprocessableEntity) String() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id}][%d] repoEditReleaseAttachmentUnprocessableEntity", 422)
}
func (o *RepoEditReleaseAttachmentUnprocessableEntity) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}

View File

@@ -0,0 +1,217 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
// NewRepoEditTagProtectionParams creates a new RepoEditTagProtectionParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewRepoEditTagProtectionParams() *RepoEditTagProtectionParams {
return &RepoEditTagProtectionParams{
timeout: cr.DefaultTimeout,
}
}
// NewRepoEditTagProtectionParamsWithTimeout creates a new RepoEditTagProtectionParams object
// with the ability to set a timeout on a request.
func NewRepoEditTagProtectionParamsWithTimeout(timeout time.Duration) *RepoEditTagProtectionParams {
return &RepoEditTagProtectionParams{
timeout: timeout,
}
}
// NewRepoEditTagProtectionParamsWithContext creates a new RepoEditTagProtectionParams object
// with the ability to set a context for a request.
func NewRepoEditTagProtectionParamsWithContext(ctx context.Context) *RepoEditTagProtectionParams {
return &RepoEditTagProtectionParams{
Context: ctx,
}
}
// NewRepoEditTagProtectionParamsWithHTTPClient creates a new RepoEditTagProtectionParams object
// with the ability to set a custom HTTPClient for a request.
func NewRepoEditTagProtectionParamsWithHTTPClient(client *http.Client) *RepoEditTagProtectionParams {
return &RepoEditTagProtectionParams{
HTTPClient: client,
}
}
/*
RepoEditTagProtectionParams contains all the parameters to send to the API endpoint
for the repo edit tag protection operation.
Typically these are written to a http.Request.
*/
type RepoEditTagProtectionParams struct {
// Body.
Body *models.EditTagProtectionOption
/* ID.
id of protected tag
*/
ID int64
/* Owner.
owner of the repo
*/
Owner string
/* Repo.
name of the repo
*/
Repo string
timeout time.Duration
Context context.Context
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the repo edit tag protection params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoEditTagProtectionParams) WithDefaults() *RepoEditTagProtectionParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the repo edit tag protection params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoEditTagProtectionParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the repo edit tag protection params
func (o *RepoEditTagProtectionParams) WithTimeout(timeout time.Duration) *RepoEditTagProtectionParams {
o.SetTimeout(timeout)
return o
}
// SetTimeout adds the timeout to the repo edit tag protection params
func (o *RepoEditTagProtectionParams) SetTimeout(timeout time.Duration) {
o.timeout = timeout
}
// WithContext adds the context to the repo edit tag protection params
func (o *RepoEditTagProtectionParams) WithContext(ctx context.Context) *RepoEditTagProtectionParams {
o.SetContext(ctx)
return o
}
// SetContext adds the context to the repo edit tag protection params
func (o *RepoEditTagProtectionParams) SetContext(ctx context.Context) {
o.Context = ctx
}
// WithHTTPClient adds the HTTPClient to the repo edit tag protection params
func (o *RepoEditTagProtectionParams) WithHTTPClient(client *http.Client) *RepoEditTagProtectionParams {
o.SetHTTPClient(client)
return o
}
// SetHTTPClient adds the HTTPClient to the repo edit tag protection params
func (o *RepoEditTagProtectionParams) SetHTTPClient(client *http.Client) {
o.HTTPClient = client
}
// WithBody adds the body to the repo edit tag protection params
func (o *RepoEditTagProtectionParams) WithBody(body *models.EditTagProtectionOption) *RepoEditTagProtectionParams {
o.SetBody(body)
return o
}
// SetBody adds the body to the repo edit tag protection params
func (o *RepoEditTagProtectionParams) SetBody(body *models.EditTagProtectionOption) {
o.Body = body
}
// WithID adds the id to the repo edit tag protection params
func (o *RepoEditTagProtectionParams) WithID(id int64) *RepoEditTagProtectionParams {
o.SetID(id)
return o
}
// SetID adds the id to the repo edit tag protection params
func (o *RepoEditTagProtectionParams) SetID(id int64) {
o.ID = id
}
// WithOwner adds the owner to the repo edit tag protection params
func (o *RepoEditTagProtectionParams) WithOwner(owner string) *RepoEditTagProtectionParams {
o.SetOwner(owner)
return o
}
// SetOwner adds the owner to the repo edit tag protection params
func (o *RepoEditTagProtectionParams) SetOwner(owner string) {
o.Owner = owner
}
// WithRepo adds the repo to the repo edit tag protection params
func (o *RepoEditTagProtectionParams) WithRepo(repo string) *RepoEditTagProtectionParams {
o.SetRepo(repo)
return o
}
// SetRepo adds the repo to the repo edit tag protection params
func (o *RepoEditTagProtectionParams) SetRepo(repo string) {
o.Repo = repo
}
// WriteToRequest writes these params to a swagger request
func (o *RepoEditTagProtectionParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
if err := r.SetTimeout(o.timeout); err != nil {
return err
}
var res []error
if o.Body != nil {
if err := r.SetBodyParam(o.Body); err != nil {
return err
}
}
// path param id
if err := r.SetPathParam("id", swag.FormatInt64(o.ID)); err != nil {
return err
}
// path param owner
if err := r.SetPathParam("owner", o.Owner); err != nil {
return err
}
// path param repo
if err := r.SetPathParam("repo", o.Repo); err != nil {
return err
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,324 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"encoding/json"
"fmt"
"io"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
// RepoEditTagProtectionReader is a Reader for the RepoEditTagProtection structure.
type RepoEditTagProtectionReader struct {
formats strfmt.Registry
}
// ReadResponse reads a server response into the received o.
func (o *RepoEditTagProtectionReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 200:
result := NewRepoEditTagProtectionOK()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
case 404:
result := NewRepoEditTagProtectionNotFound()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 422:
result := NewRepoEditTagProtectionUnprocessableEntity()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 423:
result := NewRepoEditTagProtectionLocked()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("[PATCH /repos/{owner}/{repo}/tag_protections/{id}] repoEditTagProtection", response, response.Code())
}
}
// NewRepoEditTagProtectionOK creates a RepoEditTagProtectionOK with default headers values
func NewRepoEditTagProtectionOK() *RepoEditTagProtectionOK {
return &RepoEditTagProtectionOK{}
}
/*
RepoEditTagProtectionOK describes a response with status code 200, with default header values.
TagProtection
*/
type RepoEditTagProtectionOK struct {
Payload *models.TagProtection
}
// IsSuccess returns true when this repo edit tag protection o k response has a 2xx status code
func (o *RepoEditTagProtectionOK) IsSuccess() bool {
return true
}
// IsRedirect returns true when this repo edit tag protection o k response has a 3xx status code
func (o *RepoEditTagProtectionOK) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo edit tag protection o k response has a 4xx status code
func (o *RepoEditTagProtectionOK) IsClientError() bool {
return false
}
// IsServerError returns true when this repo edit tag protection o k response has a 5xx status code
func (o *RepoEditTagProtectionOK) IsServerError() bool {
return false
}
// IsCode returns true when this repo edit tag protection o k response a status code equal to that given
func (o *RepoEditTagProtectionOK) IsCode(code int) bool {
return code == 200
}
// Code gets the status code for the repo edit tag protection o k response
func (o *RepoEditTagProtectionOK) Code() int {
return 200
}
func (o *RepoEditTagProtectionOK) Error() string {
payload, _ := json.Marshal(o.Payload)
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/tag_protections/{id}][%d] repoEditTagProtectionOK %s", 200, payload)
}
func (o *RepoEditTagProtectionOK) String() string {
payload, _ := json.Marshal(o.Payload)
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/tag_protections/{id}][%d] repoEditTagProtectionOK %s", 200, payload)
}
func (o *RepoEditTagProtectionOK) GetPayload() *models.TagProtection {
return o.Payload
}
func (o *RepoEditTagProtectionOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.TagProtection)
// response payload
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
return err
}
return nil
}
// NewRepoEditTagProtectionNotFound creates a RepoEditTagProtectionNotFound with default headers values
func NewRepoEditTagProtectionNotFound() *RepoEditTagProtectionNotFound {
return &RepoEditTagProtectionNotFound{}
}
/*
RepoEditTagProtectionNotFound describes a response with status code 404, with default header values.
APINotFound is a not found empty response
*/
type RepoEditTagProtectionNotFound struct {
}
// IsSuccess returns true when this repo edit tag protection not found response has a 2xx status code
func (o *RepoEditTagProtectionNotFound) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo edit tag protection not found response has a 3xx status code
func (o *RepoEditTagProtectionNotFound) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo edit tag protection not found response has a 4xx status code
func (o *RepoEditTagProtectionNotFound) IsClientError() bool {
return true
}
// IsServerError returns true when this repo edit tag protection not found response has a 5xx status code
func (o *RepoEditTagProtectionNotFound) IsServerError() bool {
return false
}
// IsCode returns true when this repo edit tag protection not found response a status code equal to that given
func (o *RepoEditTagProtectionNotFound) IsCode(code int) bool {
return code == 404
}
// Code gets the status code for the repo edit tag protection not found response
func (o *RepoEditTagProtectionNotFound) Code() int {
return 404
}
func (o *RepoEditTagProtectionNotFound) Error() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/tag_protections/{id}][%d] repoEditTagProtectionNotFound", 404)
}
func (o *RepoEditTagProtectionNotFound) String() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/tag_protections/{id}][%d] repoEditTagProtectionNotFound", 404)
}
func (o *RepoEditTagProtectionNotFound) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}
// NewRepoEditTagProtectionUnprocessableEntity creates a RepoEditTagProtectionUnprocessableEntity with default headers values
func NewRepoEditTagProtectionUnprocessableEntity() *RepoEditTagProtectionUnprocessableEntity {
return &RepoEditTagProtectionUnprocessableEntity{}
}
/*
RepoEditTagProtectionUnprocessableEntity describes a response with status code 422, with default header values.
APIValidationError is error format response related to input validation
*/
type RepoEditTagProtectionUnprocessableEntity struct {
Message string
URL string
}
// IsSuccess returns true when this repo edit tag protection unprocessable entity response has a 2xx status code
func (o *RepoEditTagProtectionUnprocessableEntity) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo edit tag protection unprocessable entity response has a 3xx status code
func (o *RepoEditTagProtectionUnprocessableEntity) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo edit tag protection unprocessable entity response has a 4xx status code
func (o *RepoEditTagProtectionUnprocessableEntity) IsClientError() bool {
return true
}
// IsServerError returns true when this repo edit tag protection unprocessable entity response has a 5xx status code
func (o *RepoEditTagProtectionUnprocessableEntity) IsServerError() bool {
return false
}
// IsCode returns true when this repo edit tag protection unprocessable entity response a status code equal to that given
func (o *RepoEditTagProtectionUnprocessableEntity) IsCode(code int) bool {
return code == 422
}
// Code gets the status code for the repo edit tag protection unprocessable entity response
func (o *RepoEditTagProtectionUnprocessableEntity) Code() int {
return 422
}
func (o *RepoEditTagProtectionUnprocessableEntity) Error() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/tag_protections/{id}][%d] repoEditTagProtectionUnprocessableEntity", 422)
}
func (o *RepoEditTagProtectionUnprocessableEntity) String() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/tag_protections/{id}][%d] repoEditTagProtectionUnprocessableEntity", 422)
}
func (o *RepoEditTagProtectionUnprocessableEntity) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}
// NewRepoEditTagProtectionLocked creates a RepoEditTagProtectionLocked with default headers values
func NewRepoEditTagProtectionLocked() *RepoEditTagProtectionLocked {
return &RepoEditTagProtectionLocked{}
}
/*
RepoEditTagProtectionLocked describes a response with status code 423, with default header values.
APIRepoArchivedError is an error that is raised when an archived repo should be modified
*/
type RepoEditTagProtectionLocked struct {
Message string
URL string
}
// IsSuccess returns true when this repo edit tag protection locked response has a 2xx status code
func (o *RepoEditTagProtectionLocked) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo edit tag protection locked response has a 3xx status code
func (o *RepoEditTagProtectionLocked) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo edit tag protection locked response has a 4xx status code
func (o *RepoEditTagProtectionLocked) IsClientError() bool {
return true
}
// IsServerError returns true when this repo edit tag protection locked response has a 5xx status code
func (o *RepoEditTagProtectionLocked) IsServerError() bool {
return false
}
// IsCode returns true when this repo edit tag protection locked response a status code equal to that given
func (o *RepoEditTagProtectionLocked) IsCode(code int) bool {
return code == 423
}
// Code gets the status code for the repo edit tag protection locked response
func (o *RepoEditTagProtectionLocked) Code() int {
return 423
}
func (o *RepoEditTagProtectionLocked) Error() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/tag_protections/{id}][%d] repoEditTagProtectionLocked", 423)
}
func (o *RepoEditTagProtectionLocked) String() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/tag_protections/{id}][%d] repoEditTagProtectionLocked", 423)
}
func (o *RepoEditTagProtectionLocked) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}

View File

@@ -0,0 +1,173 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
)
// NewRepoGetLicensesParams creates a new RepoGetLicensesParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewRepoGetLicensesParams() *RepoGetLicensesParams {
return &RepoGetLicensesParams{
timeout: cr.DefaultTimeout,
}
}
// NewRepoGetLicensesParamsWithTimeout creates a new RepoGetLicensesParams object
// with the ability to set a timeout on a request.
func NewRepoGetLicensesParamsWithTimeout(timeout time.Duration) *RepoGetLicensesParams {
return &RepoGetLicensesParams{
timeout: timeout,
}
}
// NewRepoGetLicensesParamsWithContext creates a new RepoGetLicensesParams object
// with the ability to set a context for a request.
func NewRepoGetLicensesParamsWithContext(ctx context.Context) *RepoGetLicensesParams {
return &RepoGetLicensesParams{
Context: ctx,
}
}
// NewRepoGetLicensesParamsWithHTTPClient creates a new RepoGetLicensesParams object
// with the ability to set a custom HTTPClient for a request.
func NewRepoGetLicensesParamsWithHTTPClient(client *http.Client) *RepoGetLicensesParams {
return &RepoGetLicensesParams{
HTTPClient: client,
}
}
/*
RepoGetLicensesParams contains all the parameters to send to the API endpoint
for the repo get licenses operation.
Typically these are written to a http.Request.
*/
type RepoGetLicensesParams struct {
/* Owner.
owner of the repo
*/
Owner string
/* Repo.
name of the repo
*/
Repo string
timeout time.Duration
Context context.Context
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the repo get licenses params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoGetLicensesParams) WithDefaults() *RepoGetLicensesParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the repo get licenses params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoGetLicensesParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the repo get licenses params
func (o *RepoGetLicensesParams) WithTimeout(timeout time.Duration) *RepoGetLicensesParams {
o.SetTimeout(timeout)
return o
}
// SetTimeout adds the timeout to the repo get licenses params
func (o *RepoGetLicensesParams) SetTimeout(timeout time.Duration) {
o.timeout = timeout
}
// WithContext adds the context to the repo get licenses params
func (o *RepoGetLicensesParams) WithContext(ctx context.Context) *RepoGetLicensesParams {
o.SetContext(ctx)
return o
}
// SetContext adds the context to the repo get licenses params
func (o *RepoGetLicensesParams) SetContext(ctx context.Context) {
o.Context = ctx
}
// WithHTTPClient adds the HTTPClient to the repo get licenses params
func (o *RepoGetLicensesParams) WithHTTPClient(client *http.Client) *RepoGetLicensesParams {
o.SetHTTPClient(client)
return o
}
// SetHTTPClient adds the HTTPClient to the repo get licenses params
func (o *RepoGetLicensesParams) SetHTTPClient(client *http.Client) {
o.HTTPClient = client
}
// WithOwner adds the owner to the repo get licenses params
func (o *RepoGetLicensesParams) WithOwner(owner string) *RepoGetLicensesParams {
o.SetOwner(owner)
return o
}
// SetOwner adds the owner to the repo get licenses params
func (o *RepoGetLicensesParams) SetOwner(owner string) {
o.Owner = owner
}
// WithRepo adds the repo to the repo get licenses params
func (o *RepoGetLicensesParams) WithRepo(repo string) *RepoGetLicensesParams {
o.SetRepo(repo)
return o
}
// SetRepo adds the repo to the repo get licenses params
func (o *RepoGetLicensesParams) SetRepo(repo string) {
o.Repo = repo
}
// WriteToRequest writes these params to a swagger request
func (o *RepoGetLicensesParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
if err := r.SetTimeout(o.timeout); err != nil {
return err
}
var res []error
// path param owner
if err := r.SetPathParam("owner", o.Owner); err != nil {
return err
}
// path param repo
if err := r.SetPathParam("repo", o.Repo); err != nil {
return err
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,164 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"encoding/json"
"fmt"
"io"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
)
// RepoGetLicensesReader is a Reader for the RepoGetLicenses structure.
type RepoGetLicensesReader struct {
formats strfmt.Registry
}
// ReadResponse reads a server response into the received o.
func (o *RepoGetLicensesReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 200:
result := NewRepoGetLicensesOK()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
case 404:
result := NewRepoGetLicensesNotFound()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("[GET /repos/{owner}/{repo}/licenses] repoGetLicenses", response, response.Code())
}
}
// NewRepoGetLicensesOK creates a RepoGetLicensesOK with default headers values
func NewRepoGetLicensesOK() *RepoGetLicensesOK {
return &RepoGetLicensesOK{}
}
/*
RepoGetLicensesOK describes a response with status code 200, with default header values.
LicensesList
*/
type RepoGetLicensesOK struct {
Payload []string
}
// IsSuccess returns true when this repo get licenses o k response has a 2xx status code
func (o *RepoGetLicensesOK) IsSuccess() bool {
return true
}
// IsRedirect returns true when this repo get licenses o k response has a 3xx status code
func (o *RepoGetLicensesOK) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo get licenses o k response has a 4xx status code
func (o *RepoGetLicensesOK) IsClientError() bool {
return false
}
// IsServerError returns true when this repo get licenses o k response has a 5xx status code
func (o *RepoGetLicensesOK) IsServerError() bool {
return false
}
// IsCode returns true when this repo get licenses o k response a status code equal to that given
func (o *RepoGetLicensesOK) IsCode(code int) bool {
return code == 200
}
// Code gets the status code for the repo get licenses o k response
func (o *RepoGetLicensesOK) Code() int {
return 200
}
func (o *RepoGetLicensesOK) Error() string {
payload, _ := json.Marshal(o.Payload)
return fmt.Sprintf("[GET /repos/{owner}/{repo}/licenses][%d] repoGetLicensesOK %s", 200, payload)
}
func (o *RepoGetLicensesOK) String() string {
payload, _ := json.Marshal(o.Payload)
return fmt.Sprintf("[GET /repos/{owner}/{repo}/licenses][%d] repoGetLicensesOK %s", 200, payload)
}
func (o *RepoGetLicensesOK) GetPayload() []string {
return o.Payload
}
func (o *RepoGetLicensesOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// response payload
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
return err
}
return nil
}
// NewRepoGetLicensesNotFound creates a RepoGetLicensesNotFound with default headers values
func NewRepoGetLicensesNotFound() *RepoGetLicensesNotFound {
return &RepoGetLicensesNotFound{}
}
/*
RepoGetLicensesNotFound describes a response with status code 404, with default header values.
APINotFound is a not found empty response
*/
type RepoGetLicensesNotFound struct {
}
// IsSuccess returns true when this repo get licenses not found response has a 2xx status code
func (o *RepoGetLicensesNotFound) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo get licenses not found response has a 3xx status code
func (o *RepoGetLicensesNotFound) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo get licenses not found response has a 4xx status code
func (o *RepoGetLicensesNotFound) IsClientError() bool {
return true
}
// IsServerError returns true when this repo get licenses not found response has a 5xx status code
func (o *RepoGetLicensesNotFound) IsServerError() bool {
return false
}
// IsCode returns true when this repo get licenses not found response a status code equal to that given
func (o *RepoGetLicensesNotFound) IsCode(code int) bool {
return code == 404
}
// Code gets the status code for the repo get licenses not found response
func (o *RepoGetLicensesNotFound) Code() int {
return 404
}
func (o *RepoGetLicensesNotFound) Error() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/licenses][%d] repoGetLicensesNotFound", 404)
}
func (o *RepoGetLicensesNotFound) String() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/licenses][%d] repoGetLicensesNotFound", 404)
}
func (o *RepoGetLicensesNotFound) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}

View File

@@ -63,7 +63,7 @@ type RepoGetRawFileOrLFSParams struct {
/* Filepath.
filepath of the file to get
path of the file to get, it should be "{ref}/{filepath}". If there is no ref could be inferred, it will be treated as the default branch
*/
Filepath string
@@ -75,7 +75,7 @@ type RepoGetRawFileOrLFSParams struct {
/* Ref.
The name of the commit/branch/tag. Default the repositorys default branch (usually master)
The name of the commit/branch/tag. Default the repositorys default branch
*/
Ref *string

View File

@@ -63,7 +63,7 @@ type RepoGetRawFileParams struct {
/* Filepath.
filepath of the file to get
path of the file to get, it should be "{ref}/{filepath}". If there is no ref could be inferred, it will be treated as the default branch
*/
Filepath string
@@ -75,7 +75,7 @@ type RepoGetRawFileParams struct {
/* Ref.
The name of the commit/branch/tag. Default the repositorys default branch (usually master)
The name of the commit/branch/tag. Default the repositorys default branch
*/
Ref *string

View File

@@ -27,7 +27,7 @@ func (o *RepoGetRunnerRegistrationTokenReader) ReadResponse(response runtime.Cli
}
return result, nil
default:
return nil, runtime.NewAPIError("[GET /repos/{owner}/{repo}/runners/registration-token] repoGetRunnerRegistrationToken", response, response.Code())
return nil, runtime.NewAPIError("[GET /repos/{owner}/{repo}/actions/runners/registration-token] repoGetRunnerRegistrationToken", response, response.Code())
}
}
@@ -76,11 +76,11 @@ func (o *RepoGetRunnerRegistrationTokenOK) Code() int {
}
func (o *RepoGetRunnerRegistrationTokenOK) Error() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/runners/registration-token][%d] repoGetRunnerRegistrationTokenOK", 200)
return fmt.Sprintf("[GET /repos/{owner}/{repo}/actions/runners/registration-token][%d] repoGetRunnerRegistrationTokenOK", 200)
}
func (o *RepoGetRunnerRegistrationTokenOK) String() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/runners/registration-token][%d] repoGetRunnerRegistrationTokenOK", 200)
return fmt.Sprintf("[GET /repos/{owner}/{repo}/actions/runners/registration-token][%d] repoGetRunnerRegistrationTokenOK", 200)
}
func (o *RepoGetRunnerRegistrationTokenOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {

View File

@@ -0,0 +1,196 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// NewRepoGetTagProtectionParams creates a new RepoGetTagProtectionParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewRepoGetTagProtectionParams() *RepoGetTagProtectionParams {
return &RepoGetTagProtectionParams{
timeout: cr.DefaultTimeout,
}
}
// NewRepoGetTagProtectionParamsWithTimeout creates a new RepoGetTagProtectionParams object
// with the ability to set a timeout on a request.
func NewRepoGetTagProtectionParamsWithTimeout(timeout time.Duration) *RepoGetTagProtectionParams {
return &RepoGetTagProtectionParams{
timeout: timeout,
}
}
// NewRepoGetTagProtectionParamsWithContext creates a new RepoGetTagProtectionParams object
// with the ability to set a context for a request.
func NewRepoGetTagProtectionParamsWithContext(ctx context.Context) *RepoGetTagProtectionParams {
return &RepoGetTagProtectionParams{
Context: ctx,
}
}
// NewRepoGetTagProtectionParamsWithHTTPClient creates a new RepoGetTagProtectionParams object
// with the ability to set a custom HTTPClient for a request.
func NewRepoGetTagProtectionParamsWithHTTPClient(client *http.Client) *RepoGetTagProtectionParams {
return &RepoGetTagProtectionParams{
HTTPClient: client,
}
}
/*
RepoGetTagProtectionParams contains all the parameters to send to the API endpoint
for the repo get tag protection operation.
Typically these are written to a http.Request.
*/
type RepoGetTagProtectionParams struct {
/* ID.
id of the tag protect to get
*/
ID int64
/* Owner.
owner of the repo
*/
Owner string
/* Repo.
name of the repo
*/
Repo string
timeout time.Duration
Context context.Context
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the repo get tag protection params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoGetTagProtectionParams) WithDefaults() *RepoGetTagProtectionParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the repo get tag protection params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoGetTagProtectionParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the repo get tag protection params
func (o *RepoGetTagProtectionParams) WithTimeout(timeout time.Duration) *RepoGetTagProtectionParams {
o.SetTimeout(timeout)
return o
}
// SetTimeout adds the timeout to the repo get tag protection params
func (o *RepoGetTagProtectionParams) SetTimeout(timeout time.Duration) {
o.timeout = timeout
}
// WithContext adds the context to the repo get tag protection params
func (o *RepoGetTagProtectionParams) WithContext(ctx context.Context) *RepoGetTagProtectionParams {
o.SetContext(ctx)
return o
}
// SetContext adds the context to the repo get tag protection params
func (o *RepoGetTagProtectionParams) SetContext(ctx context.Context) {
o.Context = ctx
}
// WithHTTPClient adds the HTTPClient to the repo get tag protection params
func (o *RepoGetTagProtectionParams) WithHTTPClient(client *http.Client) *RepoGetTagProtectionParams {
o.SetHTTPClient(client)
return o
}
// SetHTTPClient adds the HTTPClient to the repo get tag protection params
func (o *RepoGetTagProtectionParams) SetHTTPClient(client *http.Client) {
o.HTTPClient = client
}
// WithID adds the id to the repo get tag protection params
func (o *RepoGetTagProtectionParams) WithID(id int64) *RepoGetTagProtectionParams {
o.SetID(id)
return o
}
// SetID adds the id to the repo get tag protection params
func (o *RepoGetTagProtectionParams) SetID(id int64) {
o.ID = id
}
// WithOwner adds the owner to the repo get tag protection params
func (o *RepoGetTagProtectionParams) WithOwner(owner string) *RepoGetTagProtectionParams {
o.SetOwner(owner)
return o
}
// SetOwner adds the owner to the repo get tag protection params
func (o *RepoGetTagProtectionParams) SetOwner(owner string) {
o.Owner = owner
}
// WithRepo adds the repo to the repo get tag protection params
func (o *RepoGetTagProtectionParams) WithRepo(repo string) *RepoGetTagProtectionParams {
o.SetRepo(repo)
return o
}
// SetRepo adds the repo to the repo get tag protection params
func (o *RepoGetTagProtectionParams) SetRepo(repo string) {
o.Repo = repo
}
// WriteToRequest writes these params to a swagger request
func (o *RepoGetTagProtectionParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
if err := r.SetTimeout(o.timeout); err != nil {
return err
}
var res []error
// path param id
if err := r.SetPathParam("id", swag.FormatInt64(o.ID)); err != nil {
return err
}
// path param owner
if err := r.SetPathParam("owner", o.Owner); err != nil {
return err
}
// path param repo
if err := r.SetPathParam("repo", o.Repo); err != nil {
return err
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,168 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"encoding/json"
"fmt"
"io"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
// RepoGetTagProtectionReader is a Reader for the RepoGetTagProtection structure.
type RepoGetTagProtectionReader struct {
formats strfmt.Registry
}
// ReadResponse reads a server response into the received o.
func (o *RepoGetTagProtectionReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 200:
result := NewRepoGetTagProtectionOK()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
case 404:
result := NewRepoGetTagProtectionNotFound()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("[GET /repos/{owner}/{repo}/tag_protections/{id}] repoGetTagProtection", response, response.Code())
}
}
// NewRepoGetTagProtectionOK creates a RepoGetTagProtectionOK with default headers values
func NewRepoGetTagProtectionOK() *RepoGetTagProtectionOK {
return &RepoGetTagProtectionOK{}
}
/*
RepoGetTagProtectionOK describes a response with status code 200, with default header values.
TagProtection
*/
type RepoGetTagProtectionOK struct {
Payload *models.TagProtection
}
// IsSuccess returns true when this repo get tag protection o k response has a 2xx status code
func (o *RepoGetTagProtectionOK) IsSuccess() bool {
return true
}
// IsRedirect returns true when this repo get tag protection o k response has a 3xx status code
func (o *RepoGetTagProtectionOK) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo get tag protection o k response has a 4xx status code
func (o *RepoGetTagProtectionOK) IsClientError() bool {
return false
}
// IsServerError returns true when this repo get tag protection o k response has a 5xx status code
func (o *RepoGetTagProtectionOK) IsServerError() bool {
return false
}
// IsCode returns true when this repo get tag protection o k response a status code equal to that given
func (o *RepoGetTagProtectionOK) IsCode(code int) bool {
return code == 200
}
// Code gets the status code for the repo get tag protection o k response
func (o *RepoGetTagProtectionOK) Code() int {
return 200
}
func (o *RepoGetTagProtectionOK) Error() string {
payload, _ := json.Marshal(o.Payload)
return fmt.Sprintf("[GET /repos/{owner}/{repo}/tag_protections/{id}][%d] repoGetTagProtectionOK %s", 200, payload)
}
func (o *RepoGetTagProtectionOK) String() string {
payload, _ := json.Marshal(o.Payload)
return fmt.Sprintf("[GET /repos/{owner}/{repo}/tag_protections/{id}][%d] repoGetTagProtectionOK %s", 200, payload)
}
func (o *RepoGetTagProtectionOK) GetPayload() *models.TagProtection {
return o.Payload
}
func (o *RepoGetTagProtectionOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.TagProtection)
// response payload
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
return err
}
return nil
}
// NewRepoGetTagProtectionNotFound creates a RepoGetTagProtectionNotFound with default headers values
func NewRepoGetTagProtectionNotFound() *RepoGetTagProtectionNotFound {
return &RepoGetTagProtectionNotFound{}
}
/*
RepoGetTagProtectionNotFound describes a response with status code 404, with default header values.
APINotFound is a not found empty response
*/
type RepoGetTagProtectionNotFound struct {
}
// IsSuccess returns true when this repo get tag protection not found response has a 2xx status code
func (o *RepoGetTagProtectionNotFound) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo get tag protection not found response has a 3xx status code
func (o *RepoGetTagProtectionNotFound) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo get tag protection not found response has a 4xx status code
func (o *RepoGetTagProtectionNotFound) IsClientError() bool {
return true
}
// IsServerError returns true when this repo get tag protection not found response has a 5xx status code
func (o *RepoGetTagProtectionNotFound) IsServerError() bool {
return false
}
// IsCode returns true when this repo get tag protection not found response a status code equal to that given
func (o *RepoGetTagProtectionNotFound) IsCode(code int) bool {
return code == 404
}
// Code gets the status code for the repo get tag protection not found response
func (o *RepoGetTagProtectionNotFound) Code() int {
return 404
}
func (o *RepoGetTagProtectionNotFound) Error() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/tag_protections/{id}][%d] repoGetTagProtectionNotFound", 404)
}
func (o *RepoGetTagProtectionNotFound) String() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/tag_protections/{id}][%d] repoGetTagProtectionNotFound", 404)
}
func (o *RepoGetTagProtectionNotFound) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}

View File

@@ -70,7 +70,7 @@ type RepoListPullRequestsParams struct {
/* Limit.
page size of results
Page size of results
*/
Limit *int64
@@ -84,19 +84,27 @@ type RepoListPullRequestsParams struct {
/* Owner.
owner of the repo
Owner of the repo
*/
Owner string
/* Page.
page number of results to return (1-based)
Page number of results to return (1-based)
Default: 1
*/
Page *int64
/* Poster.
Filter by pull request author
*/
Poster *string
/* Repo.
name of the repo
Name of the repo
*/
Repo string
@@ -108,7 +116,9 @@ type RepoListPullRequestsParams struct {
/* State.
State of pull request: open or closed (optional)
State of pull request
Default: "open"
*/
State *string
@@ -129,7 +139,21 @@ func (o *RepoListPullRequestsParams) WithDefaults() *RepoListPullRequestsParams
//
// All values with no default are reset to their zero value.
func (o *RepoListPullRequestsParams) SetDefaults() {
// no default values defined for this parameter
var (
pageDefault = int64(1)
stateDefault = string("open")
)
val := RepoListPullRequestsParams{
Page: &pageDefault,
State: &stateDefault,
}
val.timeout = o.timeout
val.Context = o.Context
val.HTTPClient = o.HTTPClient
*o = val
}
// WithTimeout adds the timeout to the repo list pull requests params
@@ -220,6 +244,17 @@ func (o *RepoListPullRequestsParams) SetPage(page *int64) {
o.Page = page
}
// WithPoster adds the poster to the repo list pull requests params
func (o *RepoListPullRequestsParams) WithPoster(poster *string) *RepoListPullRequestsParams {
o.SetPoster(poster)
return o
}
// SetPoster adds the poster to the repo list pull requests params
func (o *RepoListPullRequestsParams) SetPoster(poster *string) {
o.Poster = poster
}
// WithRepo adds the repo to the repo list pull requests params
func (o *RepoListPullRequestsParams) WithRepo(repo string) *RepoListPullRequestsParams {
o.SetRepo(repo)
@@ -328,6 +363,23 @@ func (o *RepoListPullRequestsParams) WriteToRequest(r runtime.ClientRequest, reg
}
}
if o.Poster != nil {
// query param poster
var qrPoster string
if o.Poster != nil {
qrPoster = *o.Poster
}
qPoster := qrPoster
if qPoster != "" {
if err := r.SetQueryParam("poster", qPoster); err != nil {
return err
}
}
}
// path param repo
if err := r.SetPathParam("repo", o.Repo); err != nil {
return err

View File

@@ -36,6 +36,12 @@ func (o *RepoListPullRequestsReader) ReadResponse(response runtime.ClientRespons
return nil, err
}
return nil, result
case 500:
result := NewRepoListPullRequestsInternalServerError()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("[GET /repos/{owner}/{repo}/pulls] repoListPullRequests", response, response.Code())
}
@@ -164,3 +170,75 @@ func (o *RepoListPullRequestsNotFound) readResponse(response runtime.ClientRespo
return nil
}
// NewRepoListPullRequestsInternalServerError creates a RepoListPullRequestsInternalServerError with default headers values
func NewRepoListPullRequestsInternalServerError() *RepoListPullRequestsInternalServerError {
return &RepoListPullRequestsInternalServerError{}
}
/*
RepoListPullRequestsInternalServerError describes a response with status code 500, with default header values.
APIError is error format response
*/
type RepoListPullRequestsInternalServerError struct {
Message string
URL string
}
// IsSuccess returns true when this repo list pull requests internal server error response has a 2xx status code
func (o *RepoListPullRequestsInternalServerError) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo list pull requests internal server error response has a 3xx status code
func (o *RepoListPullRequestsInternalServerError) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo list pull requests internal server error response has a 4xx status code
func (o *RepoListPullRequestsInternalServerError) IsClientError() bool {
return false
}
// IsServerError returns true when this repo list pull requests internal server error response has a 5xx status code
func (o *RepoListPullRequestsInternalServerError) IsServerError() bool {
return true
}
// IsCode returns true when this repo list pull requests internal server error response a status code equal to that given
func (o *RepoListPullRequestsInternalServerError) IsCode(code int) bool {
return code == 500
}
// Code gets the status code for the repo list pull requests internal server error response
func (o *RepoListPullRequestsInternalServerError) Code() int {
return 500
}
func (o *RepoListPullRequestsInternalServerError) Error() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/pulls][%d] repoListPullRequestsInternalServerError", 500)
}
func (o *RepoListPullRequestsInternalServerError) String() string {
return fmt.Sprintf("[GET /repos/{owner}/{repo}/pulls][%d] repoListPullRequestsInternalServerError", 500)
}
func (o *RepoListPullRequestsInternalServerError) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}

View File

@@ -0,0 +1,173 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
)
// NewRepoListTagProtectionParams creates a new RepoListTagProtectionParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewRepoListTagProtectionParams() *RepoListTagProtectionParams {
return &RepoListTagProtectionParams{
timeout: cr.DefaultTimeout,
}
}
// NewRepoListTagProtectionParamsWithTimeout creates a new RepoListTagProtectionParams object
// with the ability to set a timeout on a request.
func NewRepoListTagProtectionParamsWithTimeout(timeout time.Duration) *RepoListTagProtectionParams {
return &RepoListTagProtectionParams{
timeout: timeout,
}
}
// NewRepoListTagProtectionParamsWithContext creates a new RepoListTagProtectionParams object
// with the ability to set a context for a request.
func NewRepoListTagProtectionParamsWithContext(ctx context.Context) *RepoListTagProtectionParams {
return &RepoListTagProtectionParams{
Context: ctx,
}
}
// NewRepoListTagProtectionParamsWithHTTPClient creates a new RepoListTagProtectionParams object
// with the ability to set a custom HTTPClient for a request.
func NewRepoListTagProtectionParamsWithHTTPClient(client *http.Client) *RepoListTagProtectionParams {
return &RepoListTagProtectionParams{
HTTPClient: client,
}
}
/*
RepoListTagProtectionParams contains all the parameters to send to the API endpoint
for the repo list tag protection operation.
Typically these are written to a http.Request.
*/
type RepoListTagProtectionParams struct {
/* Owner.
owner of the repo
*/
Owner string
/* Repo.
name of the repo
*/
Repo string
timeout time.Duration
Context context.Context
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the repo list tag protection params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoListTagProtectionParams) WithDefaults() *RepoListTagProtectionParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the repo list tag protection params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoListTagProtectionParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the repo list tag protection params
func (o *RepoListTagProtectionParams) WithTimeout(timeout time.Duration) *RepoListTagProtectionParams {
o.SetTimeout(timeout)
return o
}
// SetTimeout adds the timeout to the repo list tag protection params
func (o *RepoListTagProtectionParams) SetTimeout(timeout time.Duration) {
o.timeout = timeout
}
// WithContext adds the context to the repo list tag protection params
func (o *RepoListTagProtectionParams) WithContext(ctx context.Context) *RepoListTagProtectionParams {
o.SetContext(ctx)
return o
}
// SetContext adds the context to the repo list tag protection params
func (o *RepoListTagProtectionParams) SetContext(ctx context.Context) {
o.Context = ctx
}
// WithHTTPClient adds the HTTPClient to the repo list tag protection params
func (o *RepoListTagProtectionParams) WithHTTPClient(client *http.Client) *RepoListTagProtectionParams {
o.SetHTTPClient(client)
return o
}
// SetHTTPClient adds the HTTPClient to the repo list tag protection params
func (o *RepoListTagProtectionParams) SetHTTPClient(client *http.Client) {
o.HTTPClient = client
}
// WithOwner adds the owner to the repo list tag protection params
func (o *RepoListTagProtectionParams) WithOwner(owner string) *RepoListTagProtectionParams {
o.SetOwner(owner)
return o
}
// SetOwner adds the owner to the repo list tag protection params
func (o *RepoListTagProtectionParams) SetOwner(owner string) {
o.Owner = owner
}
// WithRepo adds the repo to the repo list tag protection params
func (o *RepoListTagProtectionParams) WithRepo(repo string) *RepoListTagProtectionParams {
o.SetRepo(repo)
return o
}
// SetRepo adds the repo to the repo list tag protection params
func (o *RepoListTagProtectionParams) SetRepo(repo string) {
o.Repo = repo
}
// WriteToRequest writes these params to a swagger request
func (o *RepoListTagProtectionParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
if err := r.SetTimeout(o.timeout); err != nil {
return err
}
var res []error
// path param owner
if err := r.SetPathParam("owner", o.Owner); err != nil {
return err
}
// path param repo
if err := r.SetPathParam("repo", o.Repo); err != nil {
return err
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,104 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"encoding/json"
"fmt"
"io"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
// RepoListTagProtectionReader is a Reader for the RepoListTagProtection structure.
type RepoListTagProtectionReader struct {
formats strfmt.Registry
}
// ReadResponse reads a server response into the received o.
func (o *RepoListTagProtectionReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 200:
result := NewRepoListTagProtectionOK()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
default:
return nil, runtime.NewAPIError("[GET /repos/{owner}/{repo}/tag_protections] repoListTagProtection", response, response.Code())
}
}
// NewRepoListTagProtectionOK creates a RepoListTagProtectionOK with default headers values
func NewRepoListTagProtectionOK() *RepoListTagProtectionOK {
return &RepoListTagProtectionOK{}
}
/*
RepoListTagProtectionOK describes a response with status code 200, with default header values.
TagProtectionList
*/
type RepoListTagProtectionOK struct {
Payload []*models.TagProtection
}
// IsSuccess returns true when this repo list tag protection o k response has a 2xx status code
func (o *RepoListTagProtectionOK) IsSuccess() bool {
return true
}
// IsRedirect returns true when this repo list tag protection o k response has a 3xx status code
func (o *RepoListTagProtectionOK) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo list tag protection o k response has a 4xx status code
func (o *RepoListTagProtectionOK) IsClientError() bool {
return false
}
// IsServerError returns true when this repo list tag protection o k response has a 5xx status code
func (o *RepoListTagProtectionOK) IsServerError() bool {
return false
}
// IsCode returns true when this repo list tag protection o k response a status code equal to that given
func (o *RepoListTagProtectionOK) IsCode(code int) bool {
return code == 200
}
// Code gets the status code for the repo list tag protection o k response
func (o *RepoListTagProtectionOK) Code() int {
return 200
}
func (o *RepoListTagProtectionOK) Error() string {
payload, _ := json.Marshal(o.Payload)
return fmt.Sprintf("[GET /repos/{owner}/{repo}/tag_protections][%d] repoListTagProtectionOK %s", 200, payload)
}
func (o *RepoListTagProtectionOK) String() string {
payload, _ := json.Marshal(o.Payload)
return fmt.Sprintf("[GET /repos/{owner}/{repo}/tag_protections][%d] repoListTagProtectionOK %s", 200, payload)
}
func (o *RepoListTagProtectionOK) GetPayload() []*models.TagProtection {
return o.Payload
}
func (o *RepoListTagProtectionOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// response payload
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
return err
}
return nil
}

View File

@@ -0,0 +1,194 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
// NewRepoMergeUpstreamParams creates a new RepoMergeUpstreamParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewRepoMergeUpstreamParams() *RepoMergeUpstreamParams {
return &RepoMergeUpstreamParams{
timeout: cr.DefaultTimeout,
}
}
// NewRepoMergeUpstreamParamsWithTimeout creates a new RepoMergeUpstreamParams object
// with the ability to set a timeout on a request.
func NewRepoMergeUpstreamParamsWithTimeout(timeout time.Duration) *RepoMergeUpstreamParams {
return &RepoMergeUpstreamParams{
timeout: timeout,
}
}
// NewRepoMergeUpstreamParamsWithContext creates a new RepoMergeUpstreamParams object
// with the ability to set a context for a request.
func NewRepoMergeUpstreamParamsWithContext(ctx context.Context) *RepoMergeUpstreamParams {
return &RepoMergeUpstreamParams{
Context: ctx,
}
}
// NewRepoMergeUpstreamParamsWithHTTPClient creates a new RepoMergeUpstreamParams object
// with the ability to set a custom HTTPClient for a request.
func NewRepoMergeUpstreamParamsWithHTTPClient(client *http.Client) *RepoMergeUpstreamParams {
return &RepoMergeUpstreamParams{
HTTPClient: client,
}
}
/*
RepoMergeUpstreamParams contains all the parameters to send to the API endpoint
for the repo merge upstream operation.
Typically these are written to a http.Request.
*/
type RepoMergeUpstreamParams struct {
// Body.
Body *models.MergeUpstreamRequest
/* Owner.
owner of the repo
*/
Owner string
/* Repo.
name of the repo
*/
Repo string
timeout time.Duration
Context context.Context
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the repo merge upstream params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoMergeUpstreamParams) WithDefaults() *RepoMergeUpstreamParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the repo merge upstream params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoMergeUpstreamParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the repo merge upstream params
func (o *RepoMergeUpstreamParams) WithTimeout(timeout time.Duration) *RepoMergeUpstreamParams {
o.SetTimeout(timeout)
return o
}
// SetTimeout adds the timeout to the repo merge upstream params
func (o *RepoMergeUpstreamParams) SetTimeout(timeout time.Duration) {
o.timeout = timeout
}
// WithContext adds the context to the repo merge upstream params
func (o *RepoMergeUpstreamParams) WithContext(ctx context.Context) *RepoMergeUpstreamParams {
o.SetContext(ctx)
return o
}
// SetContext adds the context to the repo merge upstream params
func (o *RepoMergeUpstreamParams) SetContext(ctx context.Context) {
o.Context = ctx
}
// WithHTTPClient adds the HTTPClient to the repo merge upstream params
func (o *RepoMergeUpstreamParams) WithHTTPClient(client *http.Client) *RepoMergeUpstreamParams {
o.SetHTTPClient(client)
return o
}
// SetHTTPClient adds the HTTPClient to the repo merge upstream params
func (o *RepoMergeUpstreamParams) SetHTTPClient(client *http.Client) {
o.HTTPClient = client
}
// WithBody adds the body to the repo merge upstream params
func (o *RepoMergeUpstreamParams) WithBody(body *models.MergeUpstreamRequest) *RepoMergeUpstreamParams {
o.SetBody(body)
return o
}
// SetBody adds the body to the repo merge upstream params
func (o *RepoMergeUpstreamParams) SetBody(body *models.MergeUpstreamRequest) {
o.Body = body
}
// WithOwner adds the owner to the repo merge upstream params
func (o *RepoMergeUpstreamParams) WithOwner(owner string) *RepoMergeUpstreamParams {
o.SetOwner(owner)
return o
}
// SetOwner adds the owner to the repo merge upstream params
func (o *RepoMergeUpstreamParams) SetOwner(owner string) {
o.Owner = owner
}
// WithRepo adds the repo to the repo merge upstream params
func (o *RepoMergeUpstreamParams) WithRepo(repo string) *RepoMergeUpstreamParams {
o.SetRepo(repo)
return o
}
// SetRepo adds the repo to the repo merge upstream params
func (o *RepoMergeUpstreamParams) SetRepo(repo string) {
o.Repo = repo
}
// WriteToRequest writes these params to a swagger request
func (o *RepoMergeUpstreamParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
if err := r.SetTimeout(o.timeout); err != nil {
return err
}
var res []error
if o.Body != nil {
if err := r.SetBodyParam(o.Body); err != nil {
return err
}
}
// path param owner
if err := r.SetPathParam("owner", o.Owner); err != nil {
return err
}
// path param repo
if err := r.SetPathParam("repo", o.Repo); err != nil {
return err
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,246 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"encoding/json"
"fmt"
"io"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
// RepoMergeUpstreamReader is a Reader for the RepoMergeUpstream structure.
type RepoMergeUpstreamReader struct {
formats strfmt.Registry
}
// ReadResponse reads a server response into the received o.
func (o *RepoMergeUpstreamReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 200:
result := NewRepoMergeUpstreamOK()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
case 400:
result := NewRepoMergeUpstreamBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 404:
result := NewRepoMergeUpstreamNotFound()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("[POST /repos/{owner}/{repo}/merge-upstream] repoMergeUpstream", response, response.Code())
}
}
// NewRepoMergeUpstreamOK creates a RepoMergeUpstreamOK with default headers values
func NewRepoMergeUpstreamOK() *RepoMergeUpstreamOK {
return &RepoMergeUpstreamOK{}
}
/*
RepoMergeUpstreamOK describes a response with status code 200, with default header values.
RepoMergeUpstreamOK repo merge upstream o k
*/
type RepoMergeUpstreamOK struct {
Payload *models.MergeUpstreamResponse
}
// IsSuccess returns true when this repo merge upstream o k response has a 2xx status code
func (o *RepoMergeUpstreamOK) IsSuccess() bool {
return true
}
// IsRedirect returns true when this repo merge upstream o k response has a 3xx status code
func (o *RepoMergeUpstreamOK) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo merge upstream o k response has a 4xx status code
func (o *RepoMergeUpstreamOK) IsClientError() bool {
return false
}
// IsServerError returns true when this repo merge upstream o k response has a 5xx status code
func (o *RepoMergeUpstreamOK) IsServerError() bool {
return false
}
// IsCode returns true when this repo merge upstream o k response a status code equal to that given
func (o *RepoMergeUpstreamOK) IsCode(code int) bool {
return code == 200
}
// Code gets the status code for the repo merge upstream o k response
func (o *RepoMergeUpstreamOK) Code() int {
return 200
}
func (o *RepoMergeUpstreamOK) Error() string {
payload, _ := json.Marshal(o.Payload)
return fmt.Sprintf("[POST /repos/{owner}/{repo}/merge-upstream][%d] repoMergeUpstreamOK %s", 200, payload)
}
func (o *RepoMergeUpstreamOK) String() string {
payload, _ := json.Marshal(o.Payload)
return fmt.Sprintf("[POST /repos/{owner}/{repo}/merge-upstream][%d] repoMergeUpstreamOK %s", 200, payload)
}
func (o *RepoMergeUpstreamOK) GetPayload() *models.MergeUpstreamResponse {
return o.Payload
}
func (o *RepoMergeUpstreamOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.MergeUpstreamResponse)
// response payload
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
return err
}
return nil
}
// NewRepoMergeUpstreamBadRequest creates a RepoMergeUpstreamBadRequest with default headers values
func NewRepoMergeUpstreamBadRequest() *RepoMergeUpstreamBadRequest {
return &RepoMergeUpstreamBadRequest{}
}
/*
RepoMergeUpstreamBadRequest describes a response with status code 400, with default header values.
APIError is error format response
*/
type RepoMergeUpstreamBadRequest struct {
Message string
URL string
}
// IsSuccess returns true when this repo merge upstream bad request response has a 2xx status code
func (o *RepoMergeUpstreamBadRequest) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo merge upstream bad request response has a 3xx status code
func (o *RepoMergeUpstreamBadRequest) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo merge upstream bad request response has a 4xx status code
func (o *RepoMergeUpstreamBadRequest) IsClientError() bool {
return true
}
// IsServerError returns true when this repo merge upstream bad request response has a 5xx status code
func (o *RepoMergeUpstreamBadRequest) IsServerError() bool {
return false
}
// IsCode returns true when this repo merge upstream bad request response a status code equal to that given
func (o *RepoMergeUpstreamBadRequest) IsCode(code int) bool {
return code == 400
}
// Code gets the status code for the repo merge upstream bad request response
func (o *RepoMergeUpstreamBadRequest) Code() int {
return 400
}
func (o *RepoMergeUpstreamBadRequest) Error() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/merge-upstream][%d] repoMergeUpstreamBadRequest", 400)
}
func (o *RepoMergeUpstreamBadRequest) String() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/merge-upstream][%d] repoMergeUpstreamBadRequest", 400)
}
func (o *RepoMergeUpstreamBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}
// NewRepoMergeUpstreamNotFound creates a RepoMergeUpstreamNotFound with default headers values
func NewRepoMergeUpstreamNotFound() *RepoMergeUpstreamNotFound {
return &RepoMergeUpstreamNotFound{}
}
/*
RepoMergeUpstreamNotFound describes a response with status code 404, with default header values.
APINotFound is a not found empty response
*/
type RepoMergeUpstreamNotFound struct {
}
// IsSuccess returns true when this repo merge upstream not found response has a 2xx status code
func (o *RepoMergeUpstreamNotFound) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo merge upstream not found response has a 3xx status code
func (o *RepoMergeUpstreamNotFound) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo merge upstream not found response has a 4xx status code
func (o *RepoMergeUpstreamNotFound) IsClientError() bool {
return true
}
// IsServerError returns true when this repo merge upstream not found response has a 5xx status code
func (o *RepoMergeUpstreamNotFound) IsServerError() bool {
return false
}
// IsCode returns true when this repo merge upstream not found response a status code equal to that given
func (o *RepoMergeUpstreamNotFound) IsCode(code int) bool {
return code == 404
}
// Code gets the status code for the repo merge upstream not found response
func (o *RepoMergeUpstreamNotFound) Code() int {
return 404
}
func (o *RepoMergeUpstreamNotFound) Error() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/merge-upstream][%d] repoMergeUpstreamNotFound", 404)
}
func (o *RepoMergeUpstreamNotFound) String() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/merge-upstream][%d] repoMergeUpstreamNotFound", 404)
}
func (o *RepoMergeUpstreamNotFound) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}

View File

@@ -132,7 +132,7 @@ type RepoSearchParams struct {
/* Sort.
sort repos by attribute. Supported values are "alpha", "created", "updated", "size", and "id". Default is "alpha"
sort repos by attribute. Supported values are "alpha", "created", "updated", "size", "git_size", "lfs_size", "stars", "forks" and "id". Default is "alpha"
*/
Sort *string

View File

@@ -0,0 +1,216 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
// NewRepoUpdateBranchParams creates a new RepoUpdateBranchParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewRepoUpdateBranchParams() *RepoUpdateBranchParams {
return &RepoUpdateBranchParams{
timeout: cr.DefaultTimeout,
}
}
// NewRepoUpdateBranchParamsWithTimeout creates a new RepoUpdateBranchParams object
// with the ability to set a timeout on a request.
func NewRepoUpdateBranchParamsWithTimeout(timeout time.Duration) *RepoUpdateBranchParams {
return &RepoUpdateBranchParams{
timeout: timeout,
}
}
// NewRepoUpdateBranchParamsWithContext creates a new RepoUpdateBranchParams object
// with the ability to set a context for a request.
func NewRepoUpdateBranchParamsWithContext(ctx context.Context) *RepoUpdateBranchParams {
return &RepoUpdateBranchParams{
Context: ctx,
}
}
// NewRepoUpdateBranchParamsWithHTTPClient creates a new RepoUpdateBranchParams object
// with the ability to set a custom HTTPClient for a request.
func NewRepoUpdateBranchParamsWithHTTPClient(client *http.Client) *RepoUpdateBranchParams {
return &RepoUpdateBranchParams{
HTTPClient: client,
}
}
/*
RepoUpdateBranchParams contains all the parameters to send to the API endpoint
for the repo update branch operation.
Typically these are written to a http.Request.
*/
type RepoUpdateBranchParams struct {
// Body.
Body *models.UpdateBranchRepoOption
/* Branch.
name of the branch
*/
Branch string
/* Owner.
owner of the repo
*/
Owner string
/* Repo.
name of the repo
*/
Repo string
timeout time.Duration
Context context.Context
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the repo update branch params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoUpdateBranchParams) WithDefaults() *RepoUpdateBranchParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the repo update branch params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoUpdateBranchParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the repo update branch params
func (o *RepoUpdateBranchParams) WithTimeout(timeout time.Duration) *RepoUpdateBranchParams {
o.SetTimeout(timeout)
return o
}
// SetTimeout adds the timeout to the repo update branch params
func (o *RepoUpdateBranchParams) SetTimeout(timeout time.Duration) {
o.timeout = timeout
}
// WithContext adds the context to the repo update branch params
func (o *RepoUpdateBranchParams) WithContext(ctx context.Context) *RepoUpdateBranchParams {
o.SetContext(ctx)
return o
}
// SetContext adds the context to the repo update branch params
func (o *RepoUpdateBranchParams) SetContext(ctx context.Context) {
o.Context = ctx
}
// WithHTTPClient adds the HTTPClient to the repo update branch params
func (o *RepoUpdateBranchParams) WithHTTPClient(client *http.Client) *RepoUpdateBranchParams {
o.SetHTTPClient(client)
return o
}
// SetHTTPClient adds the HTTPClient to the repo update branch params
func (o *RepoUpdateBranchParams) SetHTTPClient(client *http.Client) {
o.HTTPClient = client
}
// WithBody adds the body to the repo update branch params
func (o *RepoUpdateBranchParams) WithBody(body *models.UpdateBranchRepoOption) *RepoUpdateBranchParams {
o.SetBody(body)
return o
}
// SetBody adds the body to the repo update branch params
func (o *RepoUpdateBranchParams) SetBody(body *models.UpdateBranchRepoOption) {
o.Body = body
}
// WithBranch adds the branch to the repo update branch params
func (o *RepoUpdateBranchParams) WithBranch(branch string) *RepoUpdateBranchParams {
o.SetBranch(branch)
return o
}
// SetBranch adds the branch to the repo update branch params
func (o *RepoUpdateBranchParams) SetBranch(branch string) {
o.Branch = branch
}
// WithOwner adds the owner to the repo update branch params
func (o *RepoUpdateBranchParams) WithOwner(owner string) *RepoUpdateBranchParams {
o.SetOwner(owner)
return o
}
// SetOwner adds the owner to the repo update branch params
func (o *RepoUpdateBranchParams) SetOwner(owner string) {
o.Owner = owner
}
// WithRepo adds the repo to the repo update branch params
func (o *RepoUpdateBranchParams) WithRepo(repo string) *RepoUpdateBranchParams {
o.SetRepo(repo)
return o
}
// SetRepo adds the repo to the repo update branch params
func (o *RepoUpdateBranchParams) SetRepo(repo string) {
o.Repo = repo
}
// WriteToRequest writes these params to a swagger request
func (o *RepoUpdateBranchParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
if err := r.SetTimeout(o.timeout); err != nil {
return err
}
var res []error
if o.Body != nil {
if err := r.SetBodyParam(o.Body); err != nil {
return err
}
}
// path param branch
if err := r.SetPathParam("branch", o.Branch); err != nil {
return err
}
// path param owner
if err := r.SetPathParam("owner", o.Owner); err != nil {
return err
}
// path param repo
if err := r.SetPathParam("repo", o.Repo); err != nil {
return err
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,194 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
// NewRepoUpdateBranchProtectionPrioriesParams creates a new RepoUpdateBranchProtectionPrioriesParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewRepoUpdateBranchProtectionPrioriesParams() *RepoUpdateBranchProtectionPrioriesParams {
return &RepoUpdateBranchProtectionPrioriesParams{
timeout: cr.DefaultTimeout,
}
}
// NewRepoUpdateBranchProtectionPrioriesParamsWithTimeout creates a new RepoUpdateBranchProtectionPrioriesParams object
// with the ability to set a timeout on a request.
func NewRepoUpdateBranchProtectionPrioriesParamsWithTimeout(timeout time.Duration) *RepoUpdateBranchProtectionPrioriesParams {
return &RepoUpdateBranchProtectionPrioriesParams{
timeout: timeout,
}
}
// NewRepoUpdateBranchProtectionPrioriesParamsWithContext creates a new RepoUpdateBranchProtectionPrioriesParams object
// with the ability to set a context for a request.
func NewRepoUpdateBranchProtectionPrioriesParamsWithContext(ctx context.Context) *RepoUpdateBranchProtectionPrioriesParams {
return &RepoUpdateBranchProtectionPrioriesParams{
Context: ctx,
}
}
// NewRepoUpdateBranchProtectionPrioriesParamsWithHTTPClient creates a new RepoUpdateBranchProtectionPrioriesParams object
// with the ability to set a custom HTTPClient for a request.
func NewRepoUpdateBranchProtectionPrioriesParamsWithHTTPClient(client *http.Client) *RepoUpdateBranchProtectionPrioriesParams {
return &RepoUpdateBranchProtectionPrioriesParams{
HTTPClient: client,
}
}
/*
RepoUpdateBranchProtectionPrioriesParams contains all the parameters to send to the API endpoint
for the repo update branch protection priories operation.
Typically these are written to a http.Request.
*/
type RepoUpdateBranchProtectionPrioriesParams struct {
// Body.
Body *models.UpdateBranchProtectionPriories
/* Owner.
owner of the repo
*/
Owner string
/* Repo.
name of the repo
*/
Repo string
timeout time.Duration
Context context.Context
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the repo update branch protection priories params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoUpdateBranchProtectionPrioriesParams) WithDefaults() *RepoUpdateBranchProtectionPrioriesParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the repo update branch protection priories params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *RepoUpdateBranchProtectionPrioriesParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the repo update branch protection priories params
func (o *RepoUpdateBranchProtectionPrioriesParams) WithTimeout(timeout time.Duration) *RepoUpdateBranchProtectionPrioriesParams {
o.SetTimeout(timeout)
return o
}
// SetTimeout adds the timeout to the repo update branch protection priories params
func (o *RepoUpdateBranchProtectionPrioriesParams) SetTimeout(timeout time.Duration) {
o.timeout = timeout
}
// WithContext adds the context to the repo update branch protection priories params
func (o *RepoUpdateBranchProtectionPrioriesParams) WithContext(ctx context.Context) *RepoUpdateBranchProtectionPrioriesParams {
o.SetContext(ctx)
return o
}
// SetContext adds the context to the repo update branch protection priories params
func (o *RepoUpdateBranchProtectionPrioriesParams) SetContext(ctx context.Context) {
o.Context = ctx
}
// WithHTTPClient adds the HTTPClient to the repo update branch protection priories params
func (o *RepoUpdateBranchProtectionPrioriesParams) WithHTTPClient(client *http.Client) *RepoUpdateBranchProtectionPrioriesParams {
o.SetHTTPClient(client)
return o
}
// SetHTTPClient adds the HTTPClient to the repo update branch protection priories params
func (o *RepoUpdateBranchProtectionPrioriesParams) SetHTTPClient(client *http.Client) {
o.HTTPClient = client
}
// WithBody adds the body to the repo update branch protection priories params
func (o *RepoUpdateBranchProtectionPrioriesParams) WithBody(body *models.UpdateBranchProtectionPriories) *RepoUpdateBranchProtectionPrioriesParams {
o.SetBody(body)
return o
}
// SetBody adds the body to the repo update branch protection priories params
func (o *RepoUpdateBranchProtectionPrioriesParams) SetBody(body *models.UpdateBranchProtectionPriories) {
o.Body = body
}
// WithOwner adds the owner to the repo update branch protection priories params
func (o *RepoUpdateBranchProtectionPrioriesParams) WithOwner(owner string) *RepoUpdateBranchProtectionPrioriesParams {
o.SetOwner(owner)
return o
}
// SetOwner adds the owner to the repo update branch protection priories params
func (o *RepoUpdateBranchProtectionPrioriesParams) SetOwner(owner string) {
o.Owner = owner
}
// WithRepo adds the repo to the repo update branch protection priories params
func (o *RepoUpdateBranchProtectionPrioriesParams) WithRepo(repo string) *RepoUpdateBranchProtectionPrioriesParams {
o.SetRepo(repo)
return o
}
// SetRepo adds the repo to the repo update branch protection priories params
func (o *RepoUpdateBranchProtectionPrioriesParams) SetRepo(repo string) {
o.Repo = repo
}
// WriteToRequest writes these params to a swagger request
func (o *RepoUpdateBranchProtectionPrioriesParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
if err := r.SetTimeout(o.timeout); err != nil {
return err
}
var res []error
if o.Body != nil {
if err := r.SetBodyParam(o.Body); err != nil {
return err
}
}
// path param owner
if err := r.SetPathParam("owner", o.Owner); err != nil {
return err
}
// path param repo
if err := r.SetPathParam("repo", o.Repo); err != nil {
return err
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,306 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"fmt"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
)
// RepoUpdateBranchProtectionPrioriesReader is a Reader for the RepoUpdateBranchProtectionPriories structure.
type RepoUpdateBranchProtectionPrioriesReader struct {
formats strfmt.Registry
}
// ReadResponse reads a server response into the received o.
func (o *RepoUpdateBranchProtectionPrioriesReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 204:
result := NewRepoUpdateBranchProtectionPrioriesNoContent()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
case 404:
result := NewRepoUpdateBranchProtectionPrioriesNotFound()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 422:
result := NewRepoUpdateBranchProtectionPrioriesUnprocessableEntity()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 423:
result := NewRepoUpdateBranchProtectionPrioriesLocked()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("[POST /repos/{owner}/{repo}/branch_protections/priority] repoUpdateBranchProtectionPriories", response, response.Code())
}
}
// NewRepoUpdateBranchProtectionPrioriesNoContent creates a RepoUpdateBranchProtectionPrioriesNoContent with default headers values
func NewRepoUpdateBranchProtectionPrioriesNoContent() *RepoUpdateBranchProtectionPrioriesNoContent {
return &RepoUpdateBranchProtectionPrioriesNoContent{}
}
/*
RepoUpdateBranchProtectionPrioriesNoContent describes a response with status code 204, with default header values.
APIEmpty is an empty response
*/
type RepoUpdateBranchProtectionPrioriesNoContent struct {
}
// IsSuccess returns true when this repo update branch protection priories no content response has a 2xx status code
func (o *RepoUpdateBranchProtectionPrioriesNoContent) IsSuccess() bool {
return true
}
// IsRedirect returns true when this repo update branch protection priories no content response has a 3xx status code
func (o *RepoUpdateBranchProtectionPrioriesNoContent) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo update branch protection priories no content response has a 4xx status code
func (o *RepoUpdateBranchProtectionPrioriesNoContent) IsClientError() bool {
return false
}
// IsServerError returns true when this repo update branch protection priories no content response has a 5xx status code
func (o *RepoUpdateBranchProtectionPrioriesNoContent) IsServerError() bool {
return false
}
// IsCode returns true when this repo update branch protection priories no content response a status code equal to that given
func (o *RepoUpdateBranchProtectionPrioriesNoContent) IsCode(code int) bool {
return code == 204
}
// Code gets the status code for the repo update branch protection priories no content response
func (o *RepoUpdateBranchProtectionPrioriesNoContent) Code() int {
return 204
}
func (o *RepoUpdateBranchProtectionPrioriesNoContent) Error() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/branch_protections/priority][%d] repoUpdateBranchProtectionPrioriesNoContent", 204)
}
func (o *RepoUpdateBranchProtectionPrioriesNoContent) String() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/branch_protections/priority][%d] repoUpdateBranchProtectionPrioriesNoContent", 204)
}
func (o *RepoUpdateBranchProtectionPrioriesNoContent) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}
// NewRepoUpdateBranchProtectionPrioriesNotFound creates a RepoUpdateBranchProtectionPrioriesNotFound with default headers values
func NewRepoUpdateBranchProtectionPrioriesNotFound() *RepoUpdateBranchProtectionPrioriesNotFound {
return &RepoUpdateBranchProtectionPrioriesNotFound{}
}
/*
RepoUpdateBranchProtectionPrioriesNotFound describes a response with status code 404, with default header values.
APINotFound is a not found empty response
*/
type RepoUpdateBranchProtectionPrioriesNotFound struct {
}
// IsSuccess returns true when this repo update branch protection priories not found response has a 2xx status code
func (o *RepoUpdateBranchProtectionPrioriesNotFound) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo update branch protection priories not found response has a 3xx status code
func (o *RepoUpdateBranchProtectionPrioriesNotFound) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo update branch protection priories not found response has a 4xx status code
func (o *RepoUpdateBranchProtectionPrioriesNotFound) IsClientError() bool {
return true
}
// IsServerError returns true when this repo update branch protection priories not found response has a 5xx status code
func (o *RepoUpdateBranchProtectionPrioriesNotFound) IsServerError() bool {
return false
}
// IsCode returns true when this repo update branch protection priories not found response a status code equal to that given
func (o *RepoUpdateBranchProtectionPrioriesNotFound) IsCode(code int) bool {
return code == 404
}
// Code gets the status code for the repo update branch protection priories not found response
func (o *RepoUpdateBranchProtectionPrioriesNotFound) Code() int {
return 404
}
func (o *RepoUpdateBranchProtectionPrioriesNotFound) Error() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/branch_protections/priority][%d] repoUpdateBranchProtectionPrioriesNotFound", 404)
}
func (o *RepoUpdateBranchProtectionPrioriesNotFound) String() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/branch_protections/priority][%d] repoUpdateBranchProtectionPrioriesNotFound", 404)
}
func (o *RepoUpdateBranchProtectionPrioriesNotFound) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}
// NewRepoUpdateBranchProtectionPrioriesUnprocessableEntity creates a RepoUpdateBranchProtectionPrioriesUnprocessableEntity with default headers values
func NewRepoUpdateBranchProtectionPrioriesUnprocessableEntity() *RepoUpdateBranchProtectionPrioriesUnprocessableEntity {
return &RepoUpdateBranchProtectionPrioriesUnprocessableEntity{}
}
/*
RepoUpdateBranchProtectionPrioriesUnprocessableEntity describes a response with status code 422, with default header values.
APIValidationError is error format response related to input validation
*/
type RepoUpdateBranchProtectionPrioriesUnprocessableEntity struct {
Message string
URL string
}
// IsSuccess returns true when this repo update branch protection priories unprocessable entity response has a 2xx status code
func (o *RepoUpdateBranchProtectionPrioriesUnprocessableEntity) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo update branch protection priories unprocessable entity response has a 3xx status code
func (o *RepoUpdateBranchProtectionPrioriesUnprocessableEntity) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo update branch protection priories unprocessable entity response has a 4xx status code
func (o *RepoUpdateBranchProtectionPrioriesUnprocessableEntity) IsClientError() bool {
return true
}
// IsServerError returns true when this repo update branch protection priories unprocessable entity response has a 5xx status code
func (o *RepoUpdateBranchProtectionPrioriesUnprocessableEntity) IsServerError() bool {
return false
}
// IsCode returns true when this repo update branch protection priories unprocessable entity response a status code equal to that given
func (o *RepoUpdateBranchProtectionPrioriesUnprocessableEntity) IsCode(code int) bool {
return code == 422
}
// Code gets the status code for the repo update branch protection priories unprocessable entity response
func (o *RepoUpdateBranchProtectionPrioriesUnprocessableEntity) Code() int {
return 422
}
func (o *RepoUpdateBranchProtectionPrioriesUnprocessableEntity) Error() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/branch_protections/priority][%d] repoUpdateBranchProtectionPrioriesUnprocessableEntity", 422)
}
func (o *RepoUpdateBranchProtectionPrioriesUnprocessableEntity) String() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/branch_protections/priority][%d] repoUpdateBranchProtectionPrioriesUnprocessableEntity", 422)
}
func (o *RepoUpdateBranchProtectionPrioriesUnprocessableEntity) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}
// NewRepoUpdateBranchProtectionPrioriesLocked creates a RepoUpdateBranchProtectionPrioriesLocked with default headers values
func NewRepoUpdateBranchProtectionPrioriesLocked() *RepoUpdateBranchProtectionPrioriesLocked {
return &RepoUpdateBranchProtectionPrioriesLocked{}
}
/*
RepoUpdateBranchProtectionPrioriesLocked describes a response with status code 423, with default header values.
APIRepoArchivedError is an error that is raised when an archived repo should be modified
*/
type RepoUpdateBranchProtectionPrioriesLocked struct {
Message string
URL string
}
// IsSuccess returns true when this repo update branch protection priories locked response has a 2xx status code
func (o *RepoUpdateBranchProtectionPrioriesLocked) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo update branch protection priories locked response has a 3xx status code
func (o *RepoUpdateBranchProtectionPrioriesLocked) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo update branch protection priories locked response has a 4xx status code
func (o *RepoUpdateBranchProtectionPrioriesLocked) IsClientError() bool {
return true
}
// IsServerError returns true when this repo update branch protection priories locked response has a 5xx status code
func (o *RepoUpdateBranchProtectionPrioriesLocked) IsServerError() bool {
return false
}
// IsCode returns true when this repo update branch protection priories locked response a status code equal to that given
func (o *RepoUpdateBranchProtectionPrioriesLocked) IsCode(code int) bool {
return code == 423
}
// Code gets the status code for the repo update branch protection priories locked response
func (o *RepoUpdateBranchProtectionPrioriesLocked) Code() int {
return 423
}
func (o *RepoUpdateBranchProtectionPrioriesLocked) Error() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/branch_protections/priority][%d] repoUpdateBranchProtectionPrioriesLocked", 423)
}
func (o *RepoUpdateBranchProtectionPrioriesLocked) String() string {
return fmt.Sprintf("[POST /repos/{owner}/{repo}/branch_protections/priority][%d] repoUpdateBranchProtectionPrioriesLocked", 423)
}
func (o *RepoUpdateBranchProtectionPrioriesLocked) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}

View File

@@ -0,0 +1,306 @@
// Code generated by go-swagger; DO NOT EDIT.
package repository
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"fmt"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
)
// RepoUpdateBranchReader is a Reader for the RepoUpdateBranch structure.
type RepoUpdateBranchReader struct {
formats strfmt.Registry
}
// ReadResponse reads a server response into the received o.
func (o *RepoUpdateBranchReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 204:
result := NewRepoUpdateBranchNoContent()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
case 403:
result := NewRepoUpdateBranchForbidden()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 404:
result := NewRepoUpdateBranchNotFound()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 422:
result := NewRepoUpdateBranchUnprocessableEntity()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("[PATCH /repos/{owner}/{repo}/branches/{branch}] repoUpdateBranch", response, response.Code())
}
}
// NewRepoUpdateBranchNoContent creates a RepoUpdateBranchNoContent with default headers values
func NewRepoUpdateBranchNoContent() *RepoUpdateBranchNoContent {
return &RepoUpdateBranchNoContent{}
}
/*
RepoUpdateBranchNoContent describes a response with status code 204, with default header values.
APIEmpty is an empty response
*/
type RepoUpdateBranchNoContent struct {
}
// IsSuccess returns true when this repo update branch no content response has a 2xx status code
func (o *RepoUpdateBranchNoContent) IsSuccess() bool {
return true
}
// IsRedirect returns true when this repo update branch no content response has a 3xx status code
func (o *RepoUpdateBranchNoContent) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo update branch no content response has a 4xx status code
func (o *RepoUpdateBranchNoContent) IsClientError() bool {
return false
}
// IsServerError returns true when this repo update branch no content response has a 5xx status code
func (o *RepoUpdateBranchNoContent) IsServerError() bool {
return false
}
// IsCode returns true when this repo update branch no content response a status code equal to that given
func (o *RepoUpdateBranchNoContent) IsCode(code int) bool {
return code == 204
}
// Code gets the status code for the repo update branch no content response
func (o *RepoUpdateBranchNoContent) Code() int {
return 204
}
func (o *RepoUpdateBranchNoContent) Error() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/branches/{branch}][%d] repoUpdateBranchNoContent", 204)
}
func (o *RepoUpdateBranchNoContent) String() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/branches/{branch}][%d] repoUpdateBranchNoContent", 204)
}
func (o *RepoUpdateBranchNoContent) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}
// NewRepoUpdateBranchForbidden creates a RepoUpdateBranchForbidden with default headers values
func NewRepoUpdateBranchForbidden() *RepoUpdateBranchForbidden {
return &RepoUpdateBranchForbidden{}
}
/*
RepoUpdateBranchForbidden describes a response with status code 403, with default header values.
APIForbiddenError is a forbidden error response
*/
type RepoUpdateBranchForbidden struct {
Message string
URL string
}
// IsSuccess returns true when this repo update branch forbidden response has a 2xx status code
func (o *RepoUpdateBranchForbidden) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo update branch forbidden response has a 3xx status code
func (o *RepoUpdateBranchForbidden) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo update branch forbidden response has a 4xx status code
func (o *RepoUpdateBranchForbidden) IsClientError() bool {
return true
}
// IsServerError returns true when this repo update branch forbidden response has a 5xx status code
func (o *RepoUpdateBranchForbidden) IsServerError() bool {
return false
}
// IsCode returns true when this repo update branch forbidden response a status code equal to that given
func (o *RepoUpdateBranchForbidden) IsCode(code int) bool {
return code == 403
}
// Code gets the status code for the repo update branch forbidden response
func (o *RepoUpdateBranchForbidden) Code() int {
return 403
}
func (o *RepoUpdateBranchForbidden) Error() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/branches/{branch}][%d] repoUpdateBranchForbidden", 403)
}
func (o *RepoUpdateBranchForbidden) String() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/branches/{branch}][%d] repoUpdateBranchForbidden", 403)
}
func (o *RepoUpdateBranchForbidden) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}
// NewRepoUpdateBranchNotFound creates a RepoUpdateBranchNotFound with default headers values
func NewRepoUpdateBranchNotFound() *RepoUpdateBranchNotFound {
return &RepoUpdateBranchNotFound{}
}
/*
RepoUpdateBranchNotFound describes a response with status code 404, with default header values.
APINotFound is a not found empty response
*/
type RepoUpdateBranchNotFound struct {
}
// IsSuccess returns true when this repo update branch not found response has a 2xx status code
func (o *RepoUpdateBranchNotFound) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo update branch not found response has a 3xx status code
func (o *RepoUpdateBranchNotFound) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo update branch not found response has a 4xx status code
func (o *RepoUpdateBranchNotFound) IsClientError() bool {
return true
}
// IsServerError returns true when this repo update branch not found response has a 5xx status code
func (o *RepoUpdateBranchNotFound) IsServerError() bool {
return false
}
// IsCode returns true when this repo update branch not found response a status code equal to that given
func (o *RepoUpdateBranchNotFound) IsCode(code int) bool {
return code == 404
}
// Code gets the status code for the repo update branch not found response
func (o *RepoUpdateBranchNotFound) Code() int {
return 404
}
func (o *RepoUpdateBranchNotFound) Error() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/branches/{branch}][%d] repoUpdateBranchNotFound", 404)
}
func (o *RepoUpdateBranchNotFound) String() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/branches/{branch}][%d] repoUpdateBranchNotFound", 404)
}
func (o *RepoUpdateBranchNotFound) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}
// NewRepoUpdateBranchUnprocessableEntity creates a RepoUpdateBranchUnprocessableEntity with default headers values
func NewRepoUpdateBranchUnprocessableEntity() *RepoUpdateBranchUnprocessableEntity {
return &RepoUpdateBranchUnprocessableEntity{}
}
/*
RepoUpdateBranchUnprocessableEntity describes a response with status code 422, with default header values.
APIValidationError is error format response related to input validation
*/
type RepoUpdateBranchUnprocessableEntity struct {
Message string
URL string
}
// IsSuccess returns true when this repo update branch unprocessable entity response has a 2xx status code
func (o *RepoUpdateBranchUnprocessableEntity) IsSuccess() bool {
return false
}
// IsRedirect returns true when this repo update branch unprocessable entity response has a 3xx status code
func (o *RepoUpdateBranchUnprocessableEntity) IsRedirect() bool {
return false
}
// IsClientError returns true when this repo update branch unprocessable entity response has a 4xx status code
func (o *RepoUpdateBranchUnprocessableEntity) IsClientError() bool {
return true
}
// IsServerError returns true when this repo update branch unprocessable entity response has a 5xx status code
func (o *RepoUpdateBranchUnprocessableEntity) IsServerError() bool {
return false
}
// IsCode returns true when this repo update branch unprocessable entity response a status code equal to that given
func (o *RepoUpdateBranchUnprocessableEntity) IsCode(code int) bool {
return code == 422
}
// Code gets the status code for the repo update branch unprocessable entity response
func (o *RepoUpdateBranchUnprocessableEntity) Code() int {
return 422
}
func (o *RepoUpdateBranchUnprocessableEntity) Error() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/branches/{branch}][%d] repoUpdateBranchUnprocessableEntity", 422)
}
func (o *RepoUpdateBranchUnprocessableEntity) String() string {
return fmt.Sprintf("[PATCH /repos/{owner}/{repo}/branches/{branch}][%d] repoUpdateBranchUnprocessableEntity", 422)
}
func (o *RepoUpdateBranchUnprocessableEntity) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// hydrates response header message
hdrMessage := response.GetHeader("message")
if hdrMessage != "" {
o.Message = hdrMessage
}
// hydrates response header url
hdrURL := response.GetHeader("url")
if hdrURL != "" {
o.URL = hdrURL
}
return nil
}

View File

@@ -127,6 +127,8 @@ type ClientService interface {
GetTree(params *GetTreeParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*GetTreeOK, error)
ListActionTasks(params *ListActionTasksParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListActionTasksOK, error)
AcceptRepoTransfer(params *AcceptRepoTransferParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*AcceptRepoTransferAccepted, error)
CreateCurrentUserRepo(params *CreateCurrentUserRepoParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*CreateCurrentUserRepoCreated, error)
@@ -193,6 +195,8 @@ type ClientService interface {
RepoCreateTag(params *RepoCreateTagParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoCreateTagOK, error)
RepoCreateTagProtection(params *RepoCreateTagProtectionParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoCreateTagProtectionCreated, error)
RepoCreateWikiPage(params *RepoCreateWikiPageParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoCreateWikiPageCreated, error)
RepoDelete(params *RepoDeleteParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoDeleteNoContent, error)
@@ -227,6 +231,8 @@ type ClientService interface {
RepoDeleteTag(params *RepoDeleteTagParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoDeleteTagNoContent, error)
RepoDeleteTagProtection(params *RepoDeleteTagProtectionParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoDeleteTagProtectionNoContent, error)
RepoDeleteTeam(params *RepoDeleteTeamParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoDeleteTeamNoContent, error)
RepoDeleteTopic(params *RepoDeleteTopicParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoDeleteTopicNoContent, error)
@@ -253,6 +259,8 @@ type ClientService interface {
RepoEditReleaseAttachment(params *RepoEditReleaseAttachmentParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoEditReleaseAttachmentCreated, error)
RepoEditTagProtection(params *RepoEditTagProtectionParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoEditTagProtectionOK, error)
RepoEditWikiPage(params *RepoEditWikiPageParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoEditWikiPageOK, error)
RepoGet(params *RepoGetParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetOK, error)
@@ -293,6 +301,8 @@ type ClientService interface {
RepoGetLatestRelease(params *RepoGetLatestReleaseParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetLatestReleaseOK, error)
RepoGetLicenses(params *RepoGetLicensesParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetLicensesOK, error)
RepoGetNote(params *RepoGetNoteParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetNoteOK, error)
RepoGetPullRequest(params *RepoGetPullRequestParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetPullRequestOK, error)
@@ -329,6 +339,8 @@ type ClientService interface {
RepoGetTag(params *RepoGetTagParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetTagOK, error)
RepoGetTagProtection(params *RepoGetTagProtectionParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetTagProtectionOK, error)
RepoGetWikiPage(params *RepoGetWikiPageParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetWikiPageOK, error)
RepoGetWikiPageRevisions(params *RepoGetWikiPageRevisionsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetWikiPageRevisionsOK, error)
@@ -377,6 +389,8 @@ type ClientService interface {
RepoListSubscribers(params *RepoListSubscribersParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoListSubscribersOK, error)
RepoListTagProtection(params *RepoListTagProtectionParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoListTagProtectionOK, error)
RepoListTags(params *RepoListTagsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoListTagsOK, error)
RepoListTeams(params *RepoListTeamsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoListTeamsOK, error)
@@ -385,6 +399,8 @@ type ClientService interface {
RepoMergePullRequest(params *RepoMergePullRequestParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoMergePullRequestOK, error)
RepoMergeUpstream(params *RepoMergeUpstreamParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoMergeUpstreamOK, error)
RepoMigrate(params *RepoMigrateParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoMigrateCreated, error)
RepoMirrorSync(params *RepoMirrorSyncParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoMirrorSyncOK, error)
@@ -411,6 +427,10 @@ type ClientService interface {
RepoUpdateAvatar(params *RepoUpdateAvatarParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoUpdateAvatarNoContent, error)
RepoUpdateBranch(params *RepoUpdateBranchParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoUpdateBranchNoContent, error)
RepoUpdateBranchProtectionPriories(params *RepoUpdateBranchProtectionPrioriesParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoUpdateBranchProtectionPrioriesNoContent, error)
RepoUpdateFile(params *RepoUpdateFileParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoUpdateFileOK, error)
RepoUpdatePullRequest(params *RepoUpdatePullRequestParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoUpdatePullRequestOK, error)
@@ -553,6 +573,45 @@ func (a *Client) GetTree(params *GetTreeParams, authInfo runtime.ClientAuthInfoW
panic(msg)
}
/*
ListActionTasks lists a repository s action tasks
*/
func (a *Client) ListActionTasks(params *ListActionTasksParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListActionTasksOK, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewListActionTasksParams()
}
op := &runtime.ClientOperation{
ID: "ListActionTasks",
Method: "GET",
PathPattern: "/repos/{owner}/{repo}/actions/tasks",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{"application/json", "text/plain"},
Schemes: []string{"http", "https"},
Params: params,
Reader: &ListActionTasksReader{formats: a.formats},
AuthInfo: authInfo,
Context: params.Context,
Client: params.HTTPClient,
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
success, ok := result.(*ListActionTasksOK)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for ListActionTasks: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
/*
AcceptRepoTransfer accepts a repo transfer
*/
@@ -987,7 +1046,7 @@ func (a *Client) RejectRepoTransfer(params *RejectRepoTransferParams, authInfo r
}
/*
RepoAddCollaborator adds a collaborator to a repository
RepoAddCollaborator adds or update a collaborator to a repository
*/
func (a *Client) RepoAddCollaborator(params *RepoAddCollaboratorParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoAddCollaboratorNoContent, error) {
// TODO: Validate the params before sending
@@ -1844,6 +1903,45 @@ func (a *Client) RepoCreateTag(params *RepoCreateTagParams, authInfo runtime.Cli
panic(msg)
}
/*
RepoCreateTagProtection creates a tag protections for a repository
*/
func (a *Client) RepoCreateTagProtection(params *RepoCreateTagProtectionParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoCreateTagProtectionCreated, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewRepoCreateTagProtectionParams()
}
op := &runtime.ClientOperation{
ID: "repoCreateTagProtection",
Method: "POST",
PathPattern: "/repos/{owner}/{repo}/tag_protections",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{"application/json"},
Schemes: []string{"http", "https"},
Params: params,
Reader: &RepoCreateTagProtectionReader{formats: a.formats},
AuthInfo: authInfo,
Context: params.Context,
Client: params.HTTPClient,
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
success, ok := result.(*RepoCreateTagProtectionCreated)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for repoCreateTagProtection: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
/*
RepoCreateWikiPage creates a wiki page
*/
@@ -2507,6 +2605,45 @@ func (a *Client) RepoDeleteTag(params *RepoDeleteTagParams, authInfo runtime.Cli
panic(msg)
}
/*
RepoDeleteTagProtection deletes a specific tag protection for the repository
*/
func (a *Client) RepoDeleteTagProtection(params *RepoDeleteTagProtectionParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoDeleteTagProtectionNoContent, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewRepoDeleteTagProtectionParams()
}
op := &runtime.ClientOperation{
ID: "repoDeleteTagProtection",
Method: "DELETE",
PathPattern: "/repos/{owner}/{repo}/tag_protections/{id}",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{"application/json", "text/plain"},
Schemes: []string{"http", "https"},
Params: params,
Reader: &RepoDeleteTagProtectionReader{formats: a.formats},
AuthInfo: authInfo,
Context: params.Context,
Client: params.HTTPClient,
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
success, ok := result.(*RepoDeleteTagProtectionNoContent)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for repoDeleteTagProtection: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
/*
RepoDeleteTeam deletes a team from a repository
*/
@@ -3014,6 +3151,45 @@ func (a *Client) RepoEditReleaseAttachment(params *RepoEditReleaseAttachmentPara
panic(msg)
}
/*
RepoEditTagProtection edits a tag protections for a repository only fields that are set will be changed
*/
func (a *Client) RepoEditTagProtection(params *RepoEditTagProtectionParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoEditTagProtectionOK, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewRepoEditTagProtectionParams()
}
op := &runtime.ClientOperation{
ID: "repoEditTagProtection",
Method: "PATCH",
PathPattern: "/repos/{owner}/{repo}/tag_protections/{id}",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{"application/json"},
Schemes: []string{"http", "https"},
Params: params,
Reader: &RepoEditTagProtectionReader{formats: a.formats},
AuthInfo: authInfo,
Context: params.Context,
Client: params.HTTPClient,
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
success, ok := result.(*RepoEditTagProtectionOK)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for repoEditTagProtection: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
/*
RepoEditWikiPage edits a wiki page
*/
@@ -3366,7 +3542,7 @@ func (a *Client) RepoGetCombinedStatusByRef(params *RepoGetCombinedStatusByRefPa
}
/*
RepoGetCommitPullRequest gets the pull request of the commit
RepoGetCommitPullRequest gets the merged pull request of the commit
*/
func (a *Client) RepoGetCommitPullRequest(params *RepoGetCommitPullRequestParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetCommitPullRequestOK, error) {
// TODO: Validate the params before sending
@@ -3794,6 +3970,45 @@ func (a *Client) RepoGetLatestRelease(params *RepoGetLatestReleaseParams, authIn
panic(msg)
}
/*
RepoGetLicenses gets repo licenses
*/
func (a *Client) RepoGetLicenses(params *RepoGetLicensesParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetLicensesOK, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewRepoGetLicensesParams()
}
op := &runtime.ClientOperation{
ID: "repoGetLicenses",
Method: "GET",
PathPattern: "/repos/{owner}/{repo}/licenses",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{"application/json", "text/plain"},
Schemes: []string{"http", "https"},
Params: params,
Reader: &RepoGetLicensesReader{formats: a.formats},
AuthInfo: authInfo,
Context: params.Context,
Client: params.HTTPClient,
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
success, ok := result.(*RepoGetLicensesOK)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for repoGetLicenses: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
/*
RepoGetNote gets a note corresponding to a single commit from a repository
*/
@@ -4119,7 +4334,7 @@ func (a *Client) RepoGetRawFile(params *RepoGetRawFileParams, authInfo runtime.C
Method: "GET",
PathPattern: "/repos/{owner}/{repo}/raw/{filepath}",
ProducesMediaTypes: []string{"application/octet-stream"},
ConsumesMediaTypes: []string{"application/octet-stream"},
ConsumesMediaTypes: []string{"application/json", "text/plain"},
Schemes: []string{"http", "https"},
Params: params,
Reader: &RepoGetRawFileReader{formats: a.formats, writer: writer},
@@ -4390,7 +4605,7 @@ func (a *Client) RepoGetRunnerRegistrationToken(params *RepoGetRunnerRegistratio
op := &runtime.ClientOperation{
ID: "repoGetRunnerRegistrationToken",
Method: "GET",
PathPattern: "/repos/{owner}/{repo}/runners/registration-token",
PathPattern: "/repos/{owner}/{repo}/actions/runners/registration-token",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{"application/json", "text/plain"},
Schemes: []string{"http", "https"},
@@ -4496,6 +4711,45 @@ func (a *Client) RepoGetTag(params *RepoGetTagParams, authInfo runtime.ClientAut
panic(msg)
}
/*
RepoGetTagProtection gets a specific tag protection for the repository
*/
func (a *Client) RepoGetTagProtection(params *RepoGetTagProtectionParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetTagProtectionOK, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewRepoGetTagProtectionParams()
}
op := &runtime.ClientOperation{
ID: "repoGetTagProtection",
Method: "GET",
PathPattern: "/repos/{owner}/{repo}/tag_protections/{id}",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{"application/json", "text/plain"},
Schemes: []string{"http", "https"},
Params: params,
Reader: &RepoGetTagProtectionReader{formats: a.formats},
AuthInfo: authInfo,
Context: params.Context,
Client: params.HTTPClient,
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
success, ok := result.(*RepoGetTagProtectionOK)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for repoGetTagProtection: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
/*
RepoGetWikiPage gets a wiki page
*/
@@ -5432,6 +5686,45 @@ func (a *Client) RepoListSubscribers(params *RepoListSubscribersParams, authInfo
panic(msg)
}
/*
RepoListTagProtection lists tag protections for a repository
*/
func (a *Client) RepoListTagProtection(params *RepoListTagProtectionParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoListTagProtectionOK, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewRepoListTagProtectionParams()
}
op := &runtime.ClientOperation{
ID: "repoListTagProtection",
Method: "GET",
PathPattern: "/repos/{owner}/{repo}/tag_protections",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{"application/json", "text/plain"},
Schemes: []string{"http", "https"},
Params: params,
Reader: &RepoListTagProtectionReader{formats: a.formats},
AuthInfo: authInfo,
Context: params.Context,
Client: params.HTTPClient,
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
success, ok := result.(*RepoListTagProtectionOK)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for repoListTagProtection: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
/*
RepoListTags lists a repository s tags
*/
@@ -5588,6 +5881,45 @@ func (a *Client) RepoMergePullRequest(params *RepoMergePullRequestParams, authIn
panic(msg)
}
/*
RepoMergeUpstream merges a branch from upstream
*/
func (a *Client) RepoMergeUpstream(params *RepoMergeUpstreamParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoMergeUpstreamOK, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewRepoMergeUpstreamParams()
}
op := &runtime.ClientOperation{
ID: "repoMergeUpstream",
Method: "POST",
PathPattern: "/repos/{owner}/{repo}/merge-upstream",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{"application/json", "text/plain"},
Schemes: []string{"http", "https"},
Params: params,
Reader: &RepoMergeUpstreamReader{formats: a.formats},
AuthInfo: authInfo,
Context: params.Context,
Client: params.HTTPClient,
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
success, ok := result.(*RepoMergeUpstreamOK)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for repoMergeUpstream: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
/*
RepoMigrate migrates a remote git repository
*/
@@ -6095,6 +6427,84 @@ func (a *Client) RepoUpdateAvatar(params *RepoUpdateAvatarParams, authInfo runti
panic(msg)
}
/*
RepoUpdateBranch updates a branch
*/
func (a *Client) RepoUpdateBranch(params *RepoUpdateBranchParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoUpdateBranchNoContent, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewRepoUpdateBranchParams()
}
op := &runtime.ClientOperation{
ID: "repoUpdateBranch",
Method: "PATCH",
PathPattern: "/repos/{owner}/{repo}/branches/{branch}",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{"application/json"},
Schemes: []string{"http", "https"},
Params: params,
Reader: &RepoUpdateBranchReader{formats: a.formats},
AuthInfo: authInfo,
Context: params.Context,
Client: params.HTTPClient,
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
success, ok := result.(*RepoUpdateBranchNoContent)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for repoUpdateBranch: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
/*
RepoUpdateBranchProtectionPriories updates the priorities of branch protections for a repository
*/
func (a *Client) RepoUpdateBranchProtectionPriories(params *RepoUpdateBranchProtectionPrioriesParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoUpdateBranchProtectionPrioriesNoContent, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewRepoUpdateBranchProtectionPrioriesParams()
}
op := &runtime.ClientOperation{
ID: "repoUpdateBranchProtectionPriories",
Method: "POST",
PathPattern: "/repos/{owner}/{repo}/branch_protections/priority",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{"application/json"},
Schemes: []string{"http", "https"},
Params: params,
Reader: &RepoUpdateBranchProtectionPrioriesReader{formats: a.formats},
AuthInfo: authInfo,
Context: params.Context,
Client: params.HTTPClient,
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
success, ok := result.(*RepoUpdateBranchProtectionPrioriesNoContent)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for repoUpdateBranchProtectionPriories: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
/*
RepoUpdateFile updates a file in a repository
*/

View File

@@ -0,0 +1,144 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// ActionTask ActionTask represents a ActionTask
//
// swagger:model ActionTask
type ActionTask struct {
// created at
// Format: date-time
CreatedAt strfmt.DateTime `json:"created_at,omitempty"`
// display title
DisplayTitle string `json:"display_title,omitempty"`
// event
Event string `json:"event,omitempty"`
// head branch
HeadBranch string `json:"head_branch,omitempty"`
// head s h a
HeadSHA string `json:"head_sha,omitempty"`
// ID
ID int64 `json:"id,omitempty"`
// name
Name string `json:"name,omitempty"`
// run number
RunNumber int64 `json:"run_number,omitempty"`
// run started at
// Format: date-time
RunStartedAt strfmt.DateTime `json:"run_started_at,omitempty"`
// status
Status string `json:"status,omitempty"`
// URL
URL string `json:"url,omitempty"`
// updated at
// Format: date-time
UpdatedAt strfmt.DateTime `json:"updated_at,omitempty"`
// workflow ID
WorkflowID string `json:"workflow_id,omitempty"`
}
// Validate validates this action task
func (m *ActionTask) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateCreatedAt(formats); err != nil {
res = append(res, err)
}
if err := m.validateRunStartedAt(formats); err != nil {
res = append(res, err)
}
if err := m.validateUpdatedAt(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *ActionTask) validateCreatedAt(formats strfmt.Registry) error {
if swag.IsZero(m.CreatedAt) { // not required
return nil
}
if err := validate.FormatOf("created_at", "body", "date-time", m.CreatedAt.String(), formats); err != nil {
return err
}
return nil
}
func (m *ActionTask) validateRunStartedAt(formats strfmt.Registry) error {
if swag.IsZero(m.RunStartedAt) { // not required
return nil
}
if err := validate.FormatOf("run_started_at", "body", "date-time", m.RunStartedAt.String(), formats); err != nil {
return err
}
return nil
}
func (m *ActionTask) validateUpdatedAt(formats strfmt.Registry) error {
if swag.IsZero(m.UpdatedAt) { // not required
return nil
}
if err := validate.FormatOf("updated_at", "body", "date-time", m.UpdatedAt.String(), formats); err != nil {
return err
}
return nil
}
// ContextValidate validates this action task based on context it is used
func (m *ActionTask) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *ActionTask) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *ActionTask) UnmarshalBinary(b []byte) error {
var res ActionTask
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,124 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"strconv"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// ActionTaskResponse ActionTaskResponse returns a ActionTask
//
// swagger:model ActionTaskResponse
type ActionTaskResponse struct {
// entries
Entries []*ActionTask `json:"workflow_runs"`
// total count
TotalCount int64 `json:"total_count,omitempty"`
}
// Validate validates this action task response
func (m *ActionTaskResponse) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateEntries(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *ActionTaskResponse) validateEntries(formats strfmt.Registry) error {
if swag.IsZero(m.Entries) { // not required
return nil
}
for i := 0; i < len(m.Entries); i++ {
if swag.IsZero(m.Entries[i]) { // not required
continue
}
if m.Entries[i] != nil {
if err := m.Entries[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("workflow_runs" + "." + strconv.Itoa(i))
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("workflow_runs" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// ContextValidate validate this action task response based on the context it is used
func (m *ActionTaskResponse) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
var res []error
if err := m.contextValidateEntries(ctx, formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *ActionTaskResponse) contextValidateEntries(ctx context.Context, formats strfmt.Registry) error {
for i := 0; i < len(m.Entries); i++ {
if m.Entries[i] != nil {
if swag.IsZero(m.Entries[i]) { // not required
return nil
}
if err := m.Entries[i].ContextValidate(ctx, formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("workflow_runs" + "." + strconv.Itoa(i))
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("workflow_runs" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// MarshalBinary interface implementation
func (m *ActionTaskResponse) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *ActionTaskResponse) UnmarshalBinary(b []byte) error {
var res ActionTaskResponse
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -7,6 +7,7 @@ package models
import (
"context"
"encoding/json"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
@@ -38,7 +39,8 @@ type Activity struct {
// is private
IsPrivate bool `json:"is_private,omitempty"`
// op type
// the type of action
// Enum: ["create_repo","rename_repo","star_repo","watch_repo","commit_repo","create_issue","create_pull_request","transfer_repo","push_tag","comment_issue","merge_pull_request","close_issue","reopen_issue","close_pull_request","reopen_pull_request","delete_tag","delete_branch","mirror_sync_push","mirror_sync_create","mirror_sync_delete","approve_pull_request","reject_pull_request","comment_pull","publish_release","pull_review_dismissed","pull_request_ready_for_review","auto_merge_pull_request"]
OpType string `json:"op_type,omitempty"`
// ref name
@@ -68,6 +70,10 @@ func (m *Activity) Validate(formats strfmt.Registry) error {
res = append(res, err)
}
if err := m.validateOpType(formats); err != nil {
res = append(res, err)
}
if err := m.validateActUser(formats); err != nil {
res = append(res, err)
}
@@ -98,6 +104,123 @@ func (m *Activity) validateCreated(formats strfmt.Registry) error {
return nil
}
var activityTypeOpTypePropEnum []interface{}
func init() {
var res []string
if err := json.Unmarshal([]byte(`["create_repo","rename_repo","star_repo","watch_repo","commit_repo","create_issue","create_pull_request","transfer_repo","push_tag","comment_issue","merge_pull_request","close_issue","reopen_issue","close_pull_request","reopen_pull_request","delete_tag","delete_branch","mirror_sync_push","mirror_sync_create","mirror_sync_delete","approve_pull_request","reject_pull_request","comment_pull","publish_release","pull_review_dismissed","pull_request_ready_for_review","auto_merge_pull_request"]`), &res); err != nil {
panic(err)
}
for _, v := range res {
activityTypeOpTypePropEnum = append(activityTypeOpTypePropEnum, v)
}
}
const (
// ActivityOpTypeCreateRepo captures enum value "create_repo"
ActivityOpTypeCreateRepo string = "create_repo"
// ActivityOpTypeRenameRepo captures enum value "rename_repo"
ActivityOpTypeRenameRepo string = "rename_repo"
// ActivityOpTypeStarRepo captures enum value "star_repo"
ActivityOpTypeStarRepo string = "star_repo"
// ActivityOpTypeWatchRepo captures enum value "watch_repo"
ActivityOpTypeWatchRepo string = "watch_repo"
// ActivityOpTypeCommitRepo captures enum value "commit_repo"
ActivityOpTypeCommitRepo string = "commit_repo"
// ActivityOpTypeCreateIssue captures enum value "create_issue"
ActivityOpTypeCreateIssue string = "create_issue"
// ActivityOpTypeCreatePullRequest captures enum value "create_pull_request"
ActivityOpTypeCreatePullRequest string = "create_pull_request"
// ActivityOpTypeTransferRepo captures enum value "transfer_repo"
ActivityOpTypeTransferRepo string = "transfer_repo"
// ActivityOpTypePushTag captures enum value "push_tag"
ActivityOpTypePushTag string = "push_tag"
// ActivityOpTypeCommentIssue captures enum value "comment_issue"
ActivityOpTypeCommentIssue string = "comment_issue"
// ActivityOpTypeMergePullRequest captures enum value "merge_pull_request"
ActivityOpTypeMergePullRequest string = "merge_pull_request"
// ActivityOpTypeCloseIssue captures enum value "close_issue"
ActivityOpTypeCloseIssue string = "close_issue"
// ActivityOpTypeReopenIssue captures enum value "reopen_issue"
ActivityOpTypeReopenIssue string = "reopen_issue"
// ActivityOpTypeClosePullRequest captures enum value "close_pull_request"
ActivityOpTypeClosePullRequest string = "close_pull_request"
// ActivityOpTypeReopenPullRequest captures enum value "reopen_pull_request"
ActivityOpTypeReopenPullRequest string = "reopen_pull_request"
// ActivityOpTypeDeleteTag captures enum value "delete_tag"
ActivityOpTypeDeleteTag string = "delete_tag"
// ActivityOpTypeDeleteBranch captures enum value "delete_branch"
ActivityOpTypeDeleteBranch string = "delete_branch"
// ActivityOpTypeMirrorSyncPush captures enum value "mirror_sync_push"
ActivityOpTypeMirrorSyncPush string = "mirror_sync_push"
// ActivityOpTypeMirrorSyncCreate captures enum value "mirror_sync_create"
ActivityOpTypeMirrorSyncCreate string = "mirror_sync_create"
// ActivityOpTypeMirrorSyncDelete captures enum value "mirror_sync_delete"
ActivityOpTypeMirrorSyncDelete string = "mirror_sync_delete"
// ActivityOpTypeApprovePullRequest captures enum value "approve_pull_request"
ActivityOpTypeApprovePullRequest string = "approve_pull_request"
// ActivityOpTypeRejectPullRequest captures enum value "reject_pull_request"
ActivityOpTypeRejectPullRequest string = "reject_pull_request"
// ActivityOpTypeCommentPull captures enum value "comment_pull"
ActivityOpTypeCommentPull string = "comment_pull"
// ActivityOpTypePublishRelease captures enum value "publish_release"
ActivityOpTypePublishRelease string = "publish_release"
// ActivityOpTypePullReviewDismissed captures enum value "pull_review_dismissed"
ActivityOpTypePullReviewDismissed string = "pull_review_dismissed"
// ActivityOpTypePullRequestReadyForReview captures enum value "pull_request_ready_for_review"
ActivityOpTypePullRequestReadyForReview string = "pull_request_ready_for_review"
// ActivityOpTypeAutoMergePullRequest captures enum value "auto_merge_pull_request"
ActivityOpTypeAutoMergePullRequest string = "auto_merge_pull_request"
)
// prop value enum
func (m *Activity) validateOpTypeEnum(path, location string, value string) error {
if err := validate.EnumCase(path, location, value, activityTypeOpTypePropEnum, true); err != nil {
return err
}
return nil
}
func (m *Activity) validateOpType(formats strfmt.Registry) error {
if swag.IsZero(m.OpType) { // not required
return nil
}
// value enum
if err := m.validateOpTypeEnum("op_type", "body", m.OpType); err != nil {
return err
}
return nil
}
func (m *Activity) validateActUser(formats strfmt.Registry) error {
if swag.IsZero(m.ActUser) { // not required
return nil

View File

@@ -7,9 +7,12 @@ package models
import (
"context"
"encoding/json"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// AddCollaboratorOption AddCollaboratorOption options when adding a user as a collaborator of a repository
@@ -18,11 +21,66 @@ import (
type AddCollaboratorOption struct {
// permission
// Enum: ["read","write","admin"]
Permission string `json:"permission,omitempty"`
}
// Validate validates this add collaborator option
func (m *AddCollaboratorOption) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validatePermission(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
var addCollaboratorOptionTypePermissionPropEnum []interface{}
func init() {
var res []string
if err := json.Unmarshal([]byte(`["read","write","admin"]`), &res); err != nil {
panic(err)
}
for _, v := range res {
addCollaboratorOptionTypePermissionPropEnum = append(addCollaboratorOptionTypePermissionPropEnum, v)
}
}
const (
// AddCollaboratorOptionPermissionRead captures enum value "read"
AddCollaboratorOptionPermissionRead string = "read"
// AddCollaboratorOptionPermissionWrite captures enum value "write"
AddCollaboratorOptionPermissionWrite string = "write"
// AddCollaboratorOptionPermissionAdmin captures enum value "admin"
AddCollaboratorOptionPermissionAdmin string = "admin"
)
// prop value enum
func (m *AddCollaboratorOption) validatePermissionEnum(path, location string, value string) error {
if err := validate.EnumCase(path, location, value, addCollaboratorOptionTypePermissionPropEnum, true); err != nil {
return err
}
return nil
}
func (m *AddCollaboratorOption) validatePermission(formats strfmt.Registry) error {
if swag.IsZero(m.Permission) { // not required
return nil
}
// value enum
if err := m.validatePermissionEnum("permission", "body", m.Permission); err != nil {
return err
}
return nil
}

View File

@@ -25,6 +25,9 @@ type BranchProtection struct {
// approvals whitelist usernames
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
// block admin merge override
BlockAdminMergeOverride bool `json:"block_admin_merge_override,omitempty"`
// block on official review requests
BlockOnOfficialReviewRequests bool `json:"block_on_official_review_requests,omitempty"`
@@ -47,6 +50,12 @@ type BranchProtection struct {
// enable approvals whitelist
EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist,omitempty"`
// enable force push
EnableForcePush bool `json:"enable_force_push,omitempty"`
// enable force push allowlist
EnableForcePushAllowlist bool `json:"enable_force_push_allowlist,omitempty"`
// enable merge whitelist
EnableMergeWhitelist bool `json:"enable_merge_whitelist,omitempty"`
@@ -59,6 +68,15 @@ type BranchProtection struct {
// enable status check
EnableStatusCheck bool `json:"enable_status_check,omitempty"`
// force push allowlist deploy keys
ForcePushAllowlistDeployKeys bool `json:"force_push_allowlist_deploy_keys,omitempty"`
// force push allowlist teams
ForcePushAllowlistTeams []string `json:"force_push_allowlist_teams"`
// force push allowlist usernames
ForcePushAllowlistUsernames []string `json:"force_push_allowlist_usernames"`
// ignore stale approvals
IgnoreStaleApprovals bool `json:"ignore_stale_approvals,omitempty"`
@@ -68,6 +86,9 @@ type BranchProtection struct {
// merge whitelist usernames
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
// priority
Priority int64 `json:"priority,omitempty"`
// protected file patterns
ProtectedFilePatterns string `json:"protected_file_patterns,omitempty"`

View File

@@ -24,6 +24,7 @@ type CreateAccessTokenOption struct {
Name *string `json:"name"`
// scopes
// Example: ["all","read:activitypub","read:issue","write:misc","read:notification","read:organization","read:package","read:repository","read:user"]
Scopes []string `json:"scopes"`
}

View File

@@ -23,6 +23,9 @@ type CreateBranchProtectionOption struct {
// approvals whitelist usernames
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
// block admin merge override
BlockAdminMergeOverride bool `json:"block_admin_merge_override,omitempty"`
// block on official review requests
BlockOnOfficialReviewRequests bool `json:"block_on_official_review_requests,omitempty"`
@@ -41,6 +44,12 @@ type CreateBranchProtectionOption struct {
// enable approvals whitelist
EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist,omitempty"`
// enable force push
EnableForcePush bool `json:"enable_force_push,omitempty"`
// enable force push allowlist
EnableForcePushAllowlist bool `json:"enable_force_push_allowlist,omitempty"`
// enable merge whitelist
EnableMergeWhitelist bool `json:"enable_merge_whitelist,omitempty"`
@@ -53,6 +62,15 @@ type CreateBranchProtectionOption struct {
// enable status check
EnableStatusCheck bool `json:"enable_status_check,omitempty"`
// force push allowlist deploy keys
ForcePushAllowlistDeployKeys bool `json:"force_push_allowlist_deploy_keys,omitempty"`
// force push allowlist teams
ForcePushAllowlistTeams []string `json:"force_push_allowlist_teams"`
// force push allowlist usernames
ForcePushAllowlistUsernames []string `json:"force_push_allowlist_usernames"`
// ignore stale approvals
IgnoreStaleApprovals bool `json:"ignore_stale_approvals,omitempty"`
@@ -62,6 +80,9 @@ type CreateBranchProtectionOption struct {
// merge whitelist usernames
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
// priority
Priority int64 `json:"priority,omitempty"`
// protected file patterns
ProtectedFilePatterns string `json:"protected_file_patterns,omitempty"`

View File

@@ -25,6 +25,9 @@ type CreateOAuth2ApplicationOptions struct {
// redirect u r is
RedirectURIs []string `json:"redirect_uris"`
// skip secondary authorization
SkipSecondaryAuthorization bool `json:"skip_secondary_authorization,omitempty"`
}
// Validate validates this create o auth2 application options

View File

@@ -44,6 +44,12 @@ type CreatePullRequestOption struct {
// milestone
Milestone int64 `json:"milestone,omitempty"`
// reviewers
Reviewers []string `json:"reviewers"`
// team reviewers
TeamReviewers []string `json:"team_reviewers"`
// title
Title string `json:"title,omitempty"`
}

View File

@@ -0,0 +1,56 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// CreateTagProtectionOption CreateTagProtectionOption options for creating a tag protection
//
// swagger:model CreateTagProtectionOption
type CreateTagProtectionOption struct {
// name pattern
NamePattern string `json:"name_pattern,omitempty"`
// whitelist teams
WhitelistTeams []string `json:"whitelist_teams"`
// whitelist usernames
WhitelistUsernames []string `json:"whitelist_usernames"`
}
// Validate validates this create tag protection option
func (m *CreateTagProtectionOption) Validate(formats strfmt.Registry) error {
return nil
}
// ContextValidate validates this create tag protection option based on context it is used
func (m *CreateTagProtectionOption) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *CreateTagProtectionOption) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *CreateTagProtectionOption) UnmarshalBinary(b []byte) error {
var res CreateTagProtectionOption
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -23,6 +23,9 @@ type EditBranchProtectionOption struct {
// approvals whitelist usernames
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
// block admin merge override
BlockAdminMergeOverride bool `json:"block_admin_merge_override,omitempty"`
// block on official review requests
BlockOnOfficialReviewRequests bool `json:"block_on_official_review_requests,omitempty"`
@@ -38,6 +41,12 @@ type EditBranchProtectionOption struct {
// enable approvals whitelist
EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist,omitempty"`
// enable force push
EnableForcePush bool `json:"enable_force_push,omitempty"`
// enable force push allowlist
EnableForcePushAllowlist bool `json:"enable_force_push_allowlist,omitempty"`
// enable merge whitelist
EnableMergeWhitelist bool `json:"enable_merge_whitelist,omitempty"`
@@ -50,6 +59,15 @@ type EditBranchProtectionOption struct {
// enable status check
EnableStatusCheck bool `json:"enable_status_check,omitempty"`
// force push allowlist deploy keys
ForcePushAllowlistDeployKeys bool `json:"force_push_allowlist_deploy_keys,omitempty"`
// force push allowlist teams
ForcePushAllowlistTeams []string `json:"force_push_allowlist_teams"`
// force push allowlist usernames
ForcePushAllowlistUsernames []string `json:"force_push_allowlist_usernames"`
// ignore stale approvals
IgnoreStaleApprovals bool `json:"ignore_stale_approvals,omitempty"`
@@ -59,6 +77,9 @@ type EditBranchProtectionOption struct {
// merge whitelist usernames
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
// priority
Priority int64 `json:"priority,omitempty"`
// protected file patterns
ProtectedFilePatterns string `json:"protected_file_patterns,omitempty"`

View File

@@ -0,0 +1,56 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// EditTagProtectionOption EditTagProtectionOption options for editing a tag protection
//
// swagger:model EditTagProtectionOption
type EditTagProtectionOption struct {
// name pattern
NamePattern string `json:"name_pattern,omitempty"`
// whitelist teams
WhitelistTeams []string `json:"whitelist_teams"`
// whitelist usernames
WhitelistUsernames []string `json:"whitelist_usernames"`
}
// Validate validates this edit tag protection option
func (m *EditTagProtectionOption) Validate(formats strfmt.Registry) error {
return nil
}
// ContextValidate validates this edit tag protection option based on context it is used
func (m *EditTagProtectionOption) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *EditTagProtectionOption) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *EditTagProtectionOption) UnmarshalBinary(b []byte) error {
var res EditTagProtectionOption
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -40,8 +40,11 @@ type IssueTemplate struct {
// title
Title string `json:"title,omitempty"`
// assignees
Assignees IssueTemplateStringSlice `json:"assignees,omitempty"`
// labels
Labels IssueTemplateLabels `json:"labels,omitempty"`
Labels IssueTemplateStringSlice `json:"labels,omitempty"`
}
// Validate validates this issue template
@@ -52,6 +55,10 @@ func (m *IssueTemplate) Validate(formats strfmt.Registry) error {
res = append(res, err)
}
if err := m.validateAssignees(formats); err != nil {
res = append(res, err)
}
if err := m.validateLabels(formats); err != nil {
res = append(res, err)
}
@@ -88,6 +95,23 @@ func (m *IssueTemplate) validateFields(formats strfmt.Registry) error {
return nil
}
func (m *IssueTemplate) validateAssignees(formats strfmt.Registry) error {
if swag.IsZero(m.Assignees) { // not required
return nil
}
if err := m.Assignees.Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("assignees")
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("assignees")
}
return err
}
return nil
}
func (m *IssueTemplate) validateLabels(formats strfmt.Registry) error {
if swag.IsZero(m.Labels) { // not required
return nil
@@ -113,6 +137,10 @@ func (m *IssueTemplate) ContextValidate(ctx context.Context, formats strfmt.Regi
res = append(res, err)
}
if err := m.contextValidateAssignees(ctx, formats); err != nil {
res = append(res, err)
}
if err := m.contextValidateLabels(ctx, formats); err != nil {
res = append(res, err)
}
@@ -148,6 +176,20 @@ func (m *IssueTemplate) contextValidateFields(ctx context.Context, formats strfm
return nil
}
func (m *IssueTemplate) contextValidateAssignees(ctx context.Context, formats strfmt.Registry) error {
if err := m.Assignees.ContextValidate(ctx, formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("assignees")
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("assignees")
}
return err
}
return nil
}
func (m *IssueTemplate) contextValidateLabels(ctx context.Context, formats strfmt.Registry) error {
if err := m.Labels.ContextValidate(ctx, formats); err != nil {

View File

@@ -0,0 +1,27 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/strfmt"
)
// IssueTemplateStringSlice issue template string slice
//
// swagger:model IssueTemplateStringSlice
type IssueTemplateStringSlice []string
// Validate validates this issue template string slice
func (m IssueTemplateStringSlice) Validate(formats strfmt.Registry) error {
return nil
}
// ContextValidate validates this issue template string slice based on context it is used
func (m IssueTemplateStringSlice) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}

View File

@@ -23,7 +23,7 @@ type MarkdownOption struct {
// in: body
Context string `json:"Context,omitempty"`
// Mode to render (comment, gfm, markdown)
// Mode to render (markdown, comment, wiki, file)
//
// in: body
Mode string `json:"Mode,omitempty"`
@@ -33,8 +33,9 @@ type MarkdownOption struct {
// in: body
Text string `json:"Text,omitempty"`
// Is it a wiki page ?
// Is it a wiki page? (use mode=wiki instead)
//
// Deprecated: true
// in: body
Wiki bool `json:"Wiki,omitempty"`
}

View File

@@ -28,7 +28,7 @@ type MarkupOption struct {
// in: body
FilePath string `json:"FilePath,omitempty"`
// Mode to render (comment, gfm, markdown, file)
// Mode to render (markdown, comment, wiki, file)
//
// in: body
Mode string `json:"Mode,omitempty"`
@@ -38,8 +38,9 @@ type MarkupOption struct {
// in: body
Text string `json:"Text,omitempty"`
// Is it a wiki page ?
// Is it a wiki page? (use mode=wiki instead)
//
// Deprecated: true
// in: body
Wiki bool `json:"Wiki,omitempty"`
}

View File

@@ -0,0 +1,50 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// MergeUpstreamRequest merge upstream request
//
// swagger:model MergeUpstreamRequest
type MergeUpstreamRequest struct {
// branch
Branch string `json:"branch,omitempty"`
}
// Validate validates this merge upstream request
func (m *MergeUpstreamRequest) Validate(formats strfmt.Registry) error {
return nil
}
// ContextValidate validates this merge upstream request based on context it is used
func (m *MergeUpstreamRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *MergeUpstreamRequest) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *MergeUpstreamRequest) UnmarshalBinary(b []byte) error {
var res MergeUpstreamRequest
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,50 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// MergeUpstreamResponse merge upstream response
//
// swagger:model MergeUpstreamResponse
type MergeUpstreamResponse struct {
// merge style
MergeStyle string `json:"merge_type,omitempty"`
}
// Validate validates this merge upstream response
func (m *MergeUpstreamResponse) Validate(formats strfmt.Registry) error {
return nil
}
// ContextValidate validates this merge upstream response based on context it is used
func (m *MergeUpstreamResponse) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *MergeUpstreamResponse) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *MergeUpstreamResponse) UnmarshalBinary(b []byte) error {
var res MergeUpstreamResponse
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -21,6 +21,12 @@ import (
// swagger:model MigrateRepoOptions
type MigrateRepoOptions struct {
// a w s access key ID
AWSAccessKeyID string `json:"aws_access_key_id,omitempty"`
// a w s secret access key
AWSSecretAccessKey string `json:"aws_secret_access_key,omitempty"`
// auth password
AuthPassword string `json:"auth_password,omitempty"`

View File

@@ -40,6 +40,9 @@ type OAuth2Application struct {
// redirect u r is
RedirectURIs []string `json:"redirect_uris"`
// skip secondary authorization
SkipSecondaryAuthorization bool `json:"skip_secondary_authorization,omitempty"`
}
// Validate validates this o auth2 application

View File

@@ -99,6 +99,9 @@ type PullRequest struct {
// requested reviewers
RequestedReviewers []*User `json:"requested_reviewers"`
// requested reviewers teams
RequestedReviewersTeams []*Team `json:"requested_reviewers_teams"`
// number of review comments made on the diff of a PR review (not including comments on commits or issues in a PR)
ReviewComments int64 `json:"review_comments,omitempty"`
@@ -166,6 +169,10 @@ func (m *PullRequest) Validate(formats strfmt.Registry) error {
res = append(res, err)
}
if err := m.validateRequestedReviewersTeams(formats); err != nil {
res = append(res, err)
}
if err := m.validateUpdated(formats); err != nil {
res = append(res, err)
}
@@ -330,6 +337,32 @@ func (m *PullRequest) validateRequestedReviewers(formats strfmt.Registry) error
return nil
}
func (m *PullRequest) validateRequestedReviewersTeams(formats strfmt.Registry) error {
if swag.IsZero(m.RequestedReviewersTeams) { // not required
return nil
}
for i := 0; i < len(m.RequestedReviewersTeams); i++ {
if swag.IsZero(m.RequestedReviewersTeams[i]) { // not required
continue
}
if m.RequestedReviewersTeams[i] != nil {
if err := m.RequestedReviewersTeams[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("requested_reviewers_teams" + "." + strconv.Itoa(i))
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("requested_reviewers_teams" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
func (m *PullRequest) validateUpdated(formats strfmt.Registry) error {
if swag.IsZero(m.Updated) { // not required
return nil
@@ -489,6 +522,10 @@ func (m *PullRequest) ContextValidate(ctx context.Context, formats strfmt.Regist
res = append(res, err)
}
if err := m.contextValidateRequestedReviewersTeams(ctx, formats); err != nil {
res = append(res, err)
}
if err := m.contextValidateAssignee(ctx, formats); err != nil {
res = append(res, err)
}
@@ -598,6 +635,31 @@ func (m *PullRequest) contextValidateRequestedReviewers(ctx context.Context, for
return nil
}
func (m *PullRequest) contextValidateRequestedReviewersTeams(ctx context.Context, formats strfmt.Registry) error {
for i := 0; i < len(m.RequestedReviewersTeams); i++ {
if m.RequestedReviewersTeams[i] != nil {
if swag.IsZero(m.RequestedReviewersTeams[i]) { // not required
return nil
}
if err := m.RequestedReviewersTeams[i].ContextValidate(ctx, formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("requested_reviewers_teams" + "." + strconv.Itoa(i))
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("requested_reviewers_teams" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
func (m *PullRequest) contextValidateAssignee(ctx context.Context, formats strfmt.Registry) error {
if m.Assignee != nil {

View File

@@ -23,6 +23,9 @@ type Repository struct {
// allow fast forward only
AllowFastForwardOnly bool `json:"allow_fast_forward_only_merge,omitempty"`
// allow manual merge
AllowManualMerge bool `json:"allow_manual_merge,omitempty"`
// allow merge
AllowMerge bool `json:"allow_merge_commits,omitempty"`
@@ -45,6 +48,9 @@ type Repository struct {
// Format: date-time
ArchivedAt strfmt.DateTime `json:"archived_at,omitempty"`
// autodetect manual merge
AutodetectManualMerge bool `json:"autodetect_manual_merge,omitempty"`
// avatar URL
AvatarURL string `json:"avatar_url,omitempty"`
@@ -121,6 +127,9 @@ type Repository struct {
// languages URL
LanguagesURL string `json:"languages_url,omitempty"`
// licenses
Licenses []string `json:"licenses"`
// link
Link string `json:"link,omitempty"`
@@ -171,6 +180,9 @@ type Repository struct {
// template
Template bool `json:"template,omitempty"`
// topics
Topics []string `json:"topics"`
// URL
URL string `json:"url,omitempty"`

View File

@@ -0,0 +1,106 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// TagProtection TagProtection represents a tag protection
//
// swagger:model TagProtection
type TagProtection struct {
// created
// Format: date-time
Created strfmt.DateTime `json:"created_at,omitempty"`
// ID
ID int64 `json:"id,omitempty"`
// name pattern
NamePattern string `json:"name_pattern,omitempty"`
// updated
// Format: date-time
Updated strfmt.DateTime `json:"updated_at,omitempty"`
// whitelist teams
WhitelistTeams []string `json:"whitelist_teams"`
// whitelist usernames
WhitelistUsernames []string `json:"whitelist_usernames"`
}
// Validate validates this tag protection
func (m *TagProtection) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateCreated(formats); err != nil {
res = append(res, err)
}
if err := m.validateUpdated(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *TagProtection) validateCreated(formats strfmt.Registry) error {
if swag.IsZero(m.Created) { // not required
return nil
}
if err := validate.FormatOf("created_at", "body", "date-time", m.Created.String(), formats); err != nil {
return err
}
return nil
}
func (m *TagProtection) validateUpdated(formats strfmt.Registry) error {
if swag.IsZero(m.Updated) { // not required
return nil
}
if err := validate.FormatOf("updated_at", "body", "date-time", m.Updated.String(), formats); err != nil {
return err
}
return nil
}
// ContextValidate validates this tag protection based on context it is used
func (m *TagProtection) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *TagProtection) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *TagProtection) UnmarshalBinary(b []byte) error {
var res TagProtection
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,50 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// UpdateBranchProtectionPriories UpdateBranchProtectionPriories a list to update the branch protection rule priorities
//
// swagger:model UpdateBranchProtectionPriories
type UpdateBranchProtectionPriories struct {
// i ds
IDs []int64 `json:"ids"`
}
// Validate validates this update branch protection priories
func (m *UpdateBranchProtectionPriories) Validate(formats strfmt.Registry) error {
return nil
}
// ContextValidate validates this update branch protection priories based on context it is used
func (m *UpdateBranchProtectionPriories) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *UpdateBranchProtectionPriories) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *UpdateBranchProtectionPriories) UnmarshalBinary(b []byte) error {
var res UpdateBranchProtectionPriories
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,71 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// UpdateBranchRepoOption UpdateBranchRepoOption options when updating a branch in a repository
//
// swagger:model UpdateBranchRepoOption
type UpdateBranchRepoOption struct {
// New branch name
// Required: true
Name *string `json:"name"`
}
// Validate validates this update branch repo option
func (m *UpdateBranchRepoOption) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateName(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *UpdateBranchRepoOption) validateName(formats strfmt.Registry) error {
if err := validate.Required("name", "body", m.Name); err != nil {
return err
}
return nil
}
// ContextValidate validates this update branch repo option based on context it is used
func (m *UpdateBranchRepoOption) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *UpdateBranchRepoOption) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *UpdateBranchRepoOption) UnmarshalBinary(b []byte) error {
var res UpdateBranchRepoOption
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -29,7 +29,7 @@ import (
"path"
"path/filepath"
"slices"
"strings"
"sync"
"time"
transport "github.com/go-openapi/runtime/client"
@@ -67,10 +67,31 @@ const (
ReviewStateUnknown models.ReviewStateType = ""
)
type GiteaLabelGetter interface {
GetLabels(org, repo string, idx int64) ([]*models.Label, error)
}
type GiteaLabelSettter interface {
SetLabels(org, repo string, idx int64, labels []string) ([]*models.Label, error)
}
type GiteaIssueFetcher interface {
GetIssue(org, repo string, idx int64) (*models.Issue, error)
}
type GiteaTimelineFetcher interface {
ResetTimelineCache(org, repo string, idx int64)
GetTimeline(org, repo string, idx int64) ([]*models.TimelineComment, error)
}
type GiteaComment interface {
AddComment(pr *models.PullRequest, comment string) error
}
type GiteaSetRepoOptions interface {
SetRepoOptions(owner, repo string, manual_merge bool) (*models.Repository, error)
}
type GiteaMaintainershipReader interface {
FetchMaintainershipFile(org, prjGit, branch string) ([]byte, string, error)
FetchMaintainershipDirFile(org, prjGit, branch, pkg string) ([]byte, string, error)
@@ -78,7 +99,20 @@ type GiteaMaintainershipReader interface {
type GiteaPRFetcher interface {
GetPullRequest(org, project string, num int64) (*models.PullRequest, error)
GetAssociatedPrjGitPR(prjGitOrg, prjGitRepo, refOrg, refRepo string, Index int64) (*models.PullRequest, error)
}
type GiteaPRUpdater interface {
UpdatePullRequest(org, repo string, num int64, options *models.EditPullRequestOption) (*models.PullRequest, error)
}
type GiteaPRTimelineReviewFetcher interface {
GiteaPRFetcher
GiteaTimelineFetcher
GiteaReviewFetcher
}
type GiteaCommitFetcher interface {
GetCommit(org, repo, sha string) (*models.Commit, error)
}
type GiteaReviewFetcher interface {
@@ -89,22 +123,38 @@ type GiteaCommentFetcher interface {
GetIssueComments(org, project string, issueNo int64) ([]*models.Comment, error)
}
type GiteaPRChecker interface {
type GiteaReviewTimelineFetcher interface {
GiteaReviewFetcher
GiteaTimelineFetcher
}
type GiteaPRChecker interface {
GiteaReviewTimelineFetcher
GiteaCommentFetcher
GiteaMaintainershipReader
}
type GiteaReviewFetcherAndRequester interface {
GiteaReviewFetcher
type GiteaReviewFetcherAndRequesterAndUnrequester interface {
GiteaReviewTimelineFetcher
GiteaCommentFetcher
GiteaReviewRequester
GiteaReviewUnrequester
}
type GiteaUnreviewTimelineFetcher interface {
GiteaTimelineFetcher
GiteaReviewUnrequester
}
type GiteaReviewRequester interface {
RequestReviews(pr *models.PullRequest, reviewer ...string) ([]*models.PullReview, error)
}
type GiteaReviewUnrequester interface {
UnrequestReview(org, repo string, id int64, reviwers ...string) error
UpdateIssue(org, repo string, idx int64, options *models.EditIssueOption) (*models.Issue, error)
}
type GiteaReviewer interface {
AddReviewComment(pr *models.PullRequest, state models.ReviewStateType, comment string) (*models.PullReview, error)
}
@@ -124,41 +174,51 @@ const (
CommitStatus_Error = "error"
)
type CommitStatus struct {
Context string
Description string
CommitStatus string
}
type GiteaCommitStatusSetter interface {
SetCommitStatus(org, repo, hash string, status *CommitStatus) error
SetCommitStatus(org, repo, hash string, status *models.CommitStatus) (*models.CommitStatus, error)
}
type GiteaCommitStatusGetter interface {
GetCommitStatus(org, repo, hash string) ([]*CommitStatus, error)
GetCommitStatus(org, repo, hash string) ([]*models.CommitStatus, error)
}
type GiteaMerger interface {
ManualMergePR(org, repo string, id int64, commitid string, delBranch bool) error
}
type Gitea interface {
GiteaComment
GiteaRepoFetcher
GiteaReviewRequester
GiteaReviewUnrequester
GiteaReviewer
GiteaPRFetcher
GiteaPRUpdater
GiteaMerger
GiteaCommitFetcher
GiteaReviewFetcher
GiteaCommentFetcher
GiteaTimelineFetcher
GiteaMaintainershipReader
GiteaFileContentReader
GiteaCommitStatusGetter
GiteaCommitStatusSetter
GiteaSetRepoOptions
GiteaLabelGetter
GiteaLabelSettter
GiteaIssueFetcher
GetPullNotifications(since *time.Time) ([]*models.NotificationThread, error)
GetNotifications(Type string, since *time.Time) ([]*models.NotificationThread, error)
GetDoneNotifications(Type string, page int64) ([]*models.NotificationThread, error)
SetNotificationRead(notificationId int64) error
GetOrganization(orgName string) (*models.Organization, error)
GetOrganizationRepositories(orgName string) ([]*models.Repository, error)
CreateRepositoryIfNotExist(git Git, org, repoName string) (*models.Repository, error)
CreatePullRequestIfNotExist(repo *models.Repository, srcId, targetId, title, body string) (*models.PullRequest, error)
GetAssociatedPrjGitPR(prjGitOrg, prjGitRepo, refOrg, refRepo string, Index int64) (*models.PullRequest, error)
CreatePullRequestIfNotExist(repo *models.Repository, srcId, targetId, title, body string) (*models.PullRequest, error, bool)
GetPullRequestFileContent(pr *models.PullRequest, path string) ([]byte, string, error)
GetRecentPullRequests(org, repo, branch string) ([]*models.PullRequest, error)
GetRecentCommits(org, repo, branch string, commitNo int64) ([]*models.Commit, error)
GetPullRequests(org, project string) ([]*models.PullRequest, error)
GetCurrentUser() (*models.User, error)
}
@@ -202,9 +262,134 @@ func (gitea *GiteaTransport) GetPullRequest(org, project string, num int64) (*mo
gitea.transport.DefaultAuthentication,
)
if err != nil {
LogError(err)
return nil, err
}
return pr.Payload, err
}
func (gitea *GiteaTransport) UpdatePullRequest(org, repo string, num int64, options *models.EditPullRequestOption) (*models.PullRequest, error) {
pr, err := gitea.client.Repository.RepoEditPullRequest(
repository.NewRepoEditPullRequestParams().
WithOwner(org).
WithRepo(repo).
WithIndex(num).
WithBody(options),
gitea.transport.DefaultAuthentication,
)
if err != nil {
LogError(err)
return nil, err
}
return pr.Payload, err
}
func (gitea *GiteaTransport) ManualMergePR(org, repo string, num int64, commitid string, delBranch bool) error {
manual_merge := "manually-merged"
_, err := gitea.client.Repository.RepoMergePullRequest(
repository.NewRepoMergePullRequestParams().
WithOwner(org).
WithRepo(repo).
WithIndex(num).
WithBody(&models.MergePullRequestForm{
Do: &manual_merge,
DeleteBranchAfterMerge: delBranch,
HeadCommitID: commitid,
}), gitea.transport.DefaultAuthentication,
)
if err != nil {
LogError(err)
return err
}
return nil
}
func (gitea *GiteaTransport) GetPullRequests(org, repo string) ([]*models.PullRequest, error) {
var page, limit int64
prs := make([]*models.PullRequest, 0)
limit = 20
state := "open"
for {
page++
req, err := gitea.client.Repository.RepoListPullRequests(
repository.
NewRepoListPullRequestsParams().
WithDefaults().
WithOwner(org).
WithRepo(repo).
WithState(&state).
WithPage(&page).
WithLimit(&limit),
gitea.transport.DefaultAuthentication)
if err != nil {
return nil, fmt.Errorf("cannot fetch PR list for %s / %s : %w", org, repo, err)
}
if len(req.Payload) == 0 {
break
}
prs = slices.Concat(prs, req.Payload)
if len(req.Payload) < int(limit) {
break
}
}
return prs, nil
}
func (gitea *GiteaTransport) GetCommitStatus(org, repo, hash string) ([]*models.CommitStatus, error) {
page := int64(1)
limit := int64(10)
var res []*models.CommitStatus
for {
r, err := gitea.client.Repository.RepoListStatuses(
repository.NewRepoListStatusesParams().WithDefaults().WithOwner(org).WithRepo(repo).WithSha(hash).WithPage(&page).WithLimit(&limit),
gitea.transport.DefaultAuthentication)
if err != nil {
return res, err
}
if len(r.Payload) == 0 {
break
}
res = append(res, r.Payload...)
page++
}
return res, nil
}
func (gitea *GiteaTransport) SetCommitStatus(org, repo, hash string, status *models.CommitStatus) (*models.CommitStatus, error) {
res, err := gitea.client.Repository.RepoCreateStatus(
repository.NewRepoCreateStatusParams().
WithDefaults().
WithOwner(org).
WithRepo(repo).
WithSha(hash).
WithBody(&models.CreateStatusOption{
TargetURL: status.TargetURL,
Description: status.Description,
Context: status.Context,
State: models.CommitStatusState(status.Status),
}),
gitea.transport.DefaultAuthentication,
)
if err != nil {
return nil, err
}
return res.Payload, err
}
func (gitea *GiteaTransport) GetRepository(org, pkg string) (*models.Repository, error) {
repo, err := gitea.client.Repository.RepoGet(repository.NewRepoGetParams().WithDefaults().WithOwner(org).WithRepo(pkg), gitea.transport.DefaultAuthentication)
if err != nil {
@@ -239,16 +424,35 @@ func (gitea *GiteaTransport) GetPullRequestReviews(org, project string, PRnum in
return nil, err
}
allReviews = slices.Concat(allReviews, reviews.Payload)
if len(reviews.Payload) < int(limit) {
if len(reviews.Payload) == 0 {
break
}
allReviews = slices.Concat(allReviews, reviews.Payload)
page++
}
return allReviews, nil
}
func (gitea *GiteaTransport) GetCommit(org, repo, sha string) (*models.Commit, error) {
f := false
r, err := gitea.client.Repository.RepoGetSingleCommit(
repository.NewRepoGetSingleCommitParams().
WithOwner(org).
WithRepo(repo).
WithSha(sha).
WithStat(&f).
WithFiles(&f).
WithVerification(&f),
gitea.transport.DefaultAuthentication)
if err != nil {
return nil, err
}
return r.Payload, nil
}
func (gitea *GiteaTransport) GetIssueComments(org, project string, issueNo int64) ([]*models.Comment, error) {
// limit := int64(20)
// var page int64
@@ -273,25 +477,120 @@ func (gitea *GiteaTransport) GetIssueComments(org, project string, issueNo int64
}
func (gitea *GiteaTransport) GetPullNotifications(since *time.Time) ([]*models.NotificationThread, error) {
bigLimit := int64(100000)
func (gitea *GiteaTransport) SetRepoOptions(owner, repo string, manual_merge bool) (*models.Repository, error) {
ok, err := gitea.client.Repository.RepoEdit(repository.NewRepoEditParams().WithOwner(owner).WithRepo(repo).WithBody(
&models.EditRepoOption{
AllowManualMerge: manual_merge,
AutodetectManualMerge: manual_merge,
}), gitea.transport.DefaultAuthentication)
params := notification.NewNotifyGetListParams().
WithDefaults().
WithSubjectType([]string{"Pull"}).
WithStatusTypes([]string{"unread"}).
WithLimit(&bigLimit)
if since != nil {
s := strfmt.DateTime(*since)
params.SetSince(&s)
}
list, err := gitea.client.Notification.NotifyGetList(params, gitea.transport.DefaultAuthentication)
if err != nil {
return nil, err
}
return ok.Payload, err
}
func (gitea *GiteaTransport) GetLabels(owner, repo string, idx int64) ([]*models.Label, error) {
ret, err := gitea.client.Issue.IssueGetLabels(issue.NewIssueGetLabelsParams().WithOwner(owner).WithRepo(repo).WithIndex(idx), gitea.transport.DefaultAuthentication)
if err != nil {
return nil, err
}
return ret.Payload, err
}
func (gitea *GiteaTransport) SetLabels(owner, repo string, idx int64, labels []string) ([]*models.Label, error) {
interfaceLabels := make([]interface{}, len(labels))
for i, l := range labels {
interfaceLabels[i] = l
}
ret, err := gitea.client.Issue.IssueAddLabel(issue.NewIssueAddLabelParams().WithOwner(owner).WithRepo(repo).WithIndex(idx).WithBody(&models.IssueLabelsOption{Labels: interfaceLabels}),
gitea.transport.DefaultAuthentication)
if err != nil {
return nil, err
}
return ret.Payload, nil
}
func (gitea *GiteaTransport) GetIssue(owner, repo string, idx int64) (*models.Issue, error) {
ret, err := gitea.client.Issue.IssueGetIssue(
issue.NewIssueGetIssueParams().WithOwner(owner).WithRepo(repo).WithIndex(idx),
gitea.transport.DefaultAuthentication)
if err != nil {
return nil, err
}
return ret.Payload, nil
}
func (gitea *GiteaTransport) UpdateIssue(owner, repo string, idx int64, options *models.EditIssueOption) (*models.Issue, error) {
ret, err := gitea.client.Issue.IssueEditIssue(
issue.NewIssueEditIssueParams().WithOwner(owner).WithRepo(repo).WithIndex(idx).WithBody(options),
gitea.transport.DefaultAuthentication)
if err != nil {
return nil, err
}
return ret.Payload, nil
}
const (
GiteaNotificationType_Pull = "Pull"
)
func (gitea *GiteaTransport) GetNotifications(Type string, since *time.Time) ([]*models.NotificationThread, error) {
bigLimit := int64(20)
ret := make([]*models.NotificationThread, 0, 100)
for page := int64(1); ; page++ {
params := notification.NewNotifyGetListParams().
WithDefaults().
WithSubjectType([]string{Type}).
WithStatusTypes([]string{"unread"}).
WithLimit(&bigLimit).
WithPage(&page)
if since != nil {
s := strfmt.DateTime(*since)
params.SetSince(&s)
}
list, err := gitea.client.Notification.NotifyGetList(params, gitea.transport.DefaultAuthentication)
if err != nil {
return nil, err
}
if len(list.Payload) == 0 {
break
}
ret = slices.Concat(ret, list.Payload)
if len(list.Payload) < int(bigLimit) {
break
}
}
return ret, nil
}
func (gitea *GiteaTransport) GetDoneNotifications(Type string, page int64) ([]*models.NotificationThread, error) {
limit := int64(20)
t := true
if page <= 0 {
return nil, fmt.Errorf("Page is 1-base positive int...")
}
list, err := gitea.client.Notification.NotifyGetList(
notification.NewNotifyGetListParams().
WithAll(&t).
WithSubjectType([]string{Type}).
WithStatusTypes([]string{"read"}).
WithLimit(&limit).
WithPage(&page),
gitea.transport.DefaultAuthentication)
if err != nil {
return nil, err
}
return list.Payload, nil
}
@@ -413,19 +712,23 @@ func (gitea *GiteaTransport) CreateRepositoryIfNotExist(git Git, org, repoName s
return repo.Payload, nil
}
func (gitea *GiteaTransport) CreatePullRequestIfNotExist(repo *models.Repository, srcId, targetId, title, body string) (*models.PullRequest, error) {
func (gitea *GiteaTransport) CreatePullRequestIfNotExist(repo *models.Repository, srcId, targetId, title, body string) (*models.PullRequest, error, bool) {
prOptions := models.CreatePullRequestOption{
Base: repo.DefaultBranch,
Base: targetId,
Head: srcId,
Title: title,
Body: body,
}
if pr, err := gitea.client.Repository.RepoGetPullRequestByBaseHead(
repository.NewRepoGetPullRequestByBaseHeadParams().WithOwner(repo.Owner.UserName).WithRepo(repo.Name).WithBase(repo.DefaultBranch).WithHead(srcId),
repository.NewRepoGetPullRequestByBaseHeadParams().
WithOwner(repo.Owner.UserName).
WithRepo(repo.Name).
WithBase(targetId).
WithHead(srcId),
gitea.transport.DefaultAuthentication,
); err == nil {
return pr.Payload, nil
); err == nil && pr.Payload.State == "open" {
return pr.Payload, nil, false
}
pr, err := gitea.client.Repository.RepoCreatePullRequest(
@@ -439,50 +742,11 @@ func (gitea *GiteaTransport) CreatePullRequestIfNotExist(repo *models.Repository
)
if err != nil {
return nil, fmt.Errorf("Cannot create pull request. %w", err)
LogError("owner:", repo.Owner.UserName, " repo:", repo.Name, " body:", prOptions)
return nil, fmt.Errorf("Cannot create pull request. %w", err), true
}
return pr.GetPayload(), nil
}
func (gitea *GiteaTransport) GetAssociatedPrjGitPR(prjGitOrg, prjGitRepo, refOrg, refRepo string, Index int64) (*models.PullRequest, error) {
var page int64
state := "open"
for {
page++
prs, err := gitea.client.Repository.RepoListPullRequests(
repository.
NewRepoListPullRequestsParams().
WithDefaults().
WithOwner(prjGitOrg).
WithRepo(prjGitRepo).
WithState(&state).
WithPage(&page),
gitea.transport.DefaultAuthentication)
if err != nil {
return nil, fmt.Errorf("cannot fetch PR list for %s / %s : %w", prjGitOrg, prjGitRepo, err)
}
prLine := fmt.Sprintf(PrPattern, refOrg, refRepo, Index)
// payload_processing:
for _, pr := range prs.Payload {
lines := strings.Split(pr.Body, "\n")
for _, line := range lines {
if strings.TrimSpace(line) == prLine {
return pr, nil
}
}
}
if len(prs.Payload) < 10 {
break
}
}
return nil, nil
return pr.GetPayload(), nil, true
}
func (gitea *GiteaTransport) RequestReviews(pr *models.PullRequest, reviewers ...string) ([]*models.PullReview, error) {
@@ -507,6 +771,14 @@ func (gitea *GiteaTransport) RequestReviews(pr *models.PullRequest, reviewers ..
return review.GetPayload(), nil
}
func (gitea *GiteaTransport) UnrequestReview(org, repo string, id int64, reviwers ...string) error {
_, err := gitea.client.Repository.RepoDeletePullReviewRequests(
repository.NewRepoDeletePullReviewRequestsParams().WithOwner(org).WithRepo(repo).WithIndex(id).WithBody(&models.PullReviewRequestOptions{
Reviewers: reviwers,
}), gitea.transport.DefaultAuthentication)
return err
}
func (gitea *GiteaTransport) AddReviewComment(pr *models.PullRequest, state models.ReviewStateType, comment string) (*models.PullReview, error) {
c, err := gitea.client.Repository.RepoCreatePullReview(
repository.NewRepoCreatePullReviewParams().
@@ -561,6 +833,92 @@ func (gitea *GiteaTransport) AddComment(pr *models.PullRequest, comment string)
return nil
}
type TimelineCacheData struct {
data []*models.TimelineComment
lastCheck time.Time
}
var giteaTimelineCache map[string]TimelineCacheData = make(map[string]TimelineCacheData)
var giteaTimelineCacheMutex sync.RWMutex
func (gitea *GiteaTransport) ResetTimelineCache(org, repo string, idx int64) {
giteaTimelineCacheMutex.Lock()
defer giteaTimelineCacheMutex.Unlock()
prID := fmt.Sprintf("%s/%s!%d", org, repo, idx)
Cache, IsCached := giteaTimelineCache[prID]
if IsCached {
Cache.lastCheck = Cache.lastCheck.Add(-time.Hour)
}
}
// returns timeline in reverse chronological create order
func (gitea *GiteaTransport) GetTimeline(org, repo string, idx int64) ([]*models.TimelineComment, error) {
page := int64(1)
resCount := 1
prID := fmt.Sprintf("%s/%s!%d", org, repo, idx)
giteaTimelineCacheMutex.RLock()
TimelineCache, IsCached := giteaTimelineCache[prID]
var LastCachedTime strfmt.DateTime
if IsCached {
l := len(TimelineCache.data)
if l > 0 {
LastCachedTime = TimelineCache.data[0].Updated
}
// cache data for 5 seconds
if TimelineCache.lastCheck.Add(time.Second*5).Compare(time.Now()) > 0 {
giteaTimelineCacheMutex.RUnlock()
return TimelineCache.data, nil
}
}
giteaTimelineCacheMutex.RUnlock()
giteaTimelineCacheMutex.Lock()
defer giteaTimelineCacheMutex.Unlock()
for resCount > 0 {
opts := issue.NewIssueGetCommentsAndTimelineParams().WithOwner(org).WithRepo(repo).WithIndex(idx).WithPage(&page)
if !LastCachedTime.IsZero() {
opts = opts.WithSince(&LastCachedTime)
}
res, err := gitea.client.Issue.IssueGetCommentsAndTimeline(opts, gitea.transport.DefaultAuthentication)
if err != nil {
return nil, err
}
if resCount = len(res.Payload); resCount == 0 {
break
}
for _, d := range res.Payload {
if d != nil {
if time.Time(d.Created).Compare(time.Time(LastCachedTime)) > 0 {
// created after last check, so we append here
TimelineCache.data = append(TimelineCache.data, d)
} else {
// we need something updated in the timeline, maybe
}
}
}
if resCount < 10 {
break
}
page++
}
LogDebug("timeline", prID, "# timeline:", len(TimelineCache.data))
slices.SortFunc(TimelineCache.data, func(a, b *models.TimelineComment) int {
return time.Time(b.Created).Compare(time.Time(a.Created))
})
TimelineCache.lastCheck = time.Now()
giteaTimelineCache[prID] = TimelineCache
return TimelineCache.data, nil
}
func (gitea *GiteaTransport) GetRepositoryFileContent(org, repo, hash, path string) ([]byte, string, error) {
params := repository.NewRepoGetContentsParams().WithOwner(org).WithRepo(repo).WithFilepath(path)
if len(hash) > 0 {
@@ -632,7 +990,7 @@ endPrs:
}
// if pr is closed for more than a week, assume that we are done too
if time.Since(time.Time(pr.Updated)) > 7*24*time.Hour {
if pr.State == "closed" && time.Since(time.Time(pr.Updated)) > 7*24*time.Hour {
break endPrs
}

View File

@@ -1,317 +0,0 @@
package common
/*
* This file is part of Autogits.
*
* Copyright © 2024 SUSE LLC
*
* Autogits is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 2 of the License, or (at your option) any later
* version.
*
* Autogits is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Foobar. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"crypto/tls"
"fmt"
"net/url"
"runtime/debug"
"slices"
"strings"
"time"
rabbitmq "github.com/rabbitmq/amqp091-go"
)
const RequestType_CreateBrachTag = "create"
const RequestType_DeleteBranchTag = "delete"
const RequestType_Fork = "fork"
const RequestType_Issue = "issues"
const RequestType_IssueAssign = "issue_assign"
const RequestType_IssueComment = "issue_comment"
const RequestType_IssueLabel = "issue_label"
const RequestType_IssueMilestone = "issue_milestone"
const RequestType_Push = "push"
const RequestType_Repository = "repository"
const RequestType_Release = "release"
const RequestType_PR = "pull_request"
const RequestType_PRAssign = "pull_request_assign"
const RequestType_PRLabel = "pull_request_label"
const RequestType_PRComment = "pull_request_comment"
const RequestType_PRMilestone = "pull_request_milestone"
const RequestType_PRSync = "pull_request_sync"
const RequestType_PRReviewAccepted = "pull_request_review_approved"
const RequestType_PRReviewRejected = "pull_request_review_rejected"
const RequestType_PRReviewRequest = "pull_request_review_request"
const RequestType_PRReviewComment = "pull_request_review_comment"
const RequestType_Wiki = "wiki"
type RequestProcessor interface {
ProcessFunc(*Request) error
}
type ListenDefinitions struct {
RabbitURL *url.URL // amqps://user:password@host/queue
GitAuthor string
Handlers map[string]RequestProcessor
Orgs []string
topics []string
topicSubChanges chan string // +topic = subscribe, -topic = unsubscribe
}
type RabbitMessage rabbitmq.Delivery
func (l *ListenDefinitions) processTopicChanges(ch *rabbitmq.Channel, queueName string) {
for {
topic, ok := <-l.topicSubChanges
if !ok {
return
}
LogDebug(" topic change:", topic)
switch topic[0] {
case '+':
if err := ch.QueueBind(queueName, topic[1:], "pubsub", false, nil); err != nil {
LogError(err)
}
case '-':
if err := ch.QueueUnbind(queueName, topic[1:], "pubsub", nil); err != nil {
LogError(err)
}
default:
LogInfo("Ignoring unknown topic change:", topic)
}
}
}
func (l *ListenDefinitions) processRabbitMQ(msgCh chan<- RabbitMessage) error {
queueName := l.RabbitURL.Path
l.RabbitURL.Path = ""
if len(queueName) > 0 && queueName[0] == '/' {
queueName = queueName[1:]
}
connection, err := rabbitmq.DialTLS(l.RabbitURL.String(), &tls.Config{
ServerName: l.RabbitURL.Hostname(),
})
if err != nil {
return fmt.Errorf("Cannot connect to %s . Err: %w", l.RabbitURL.Hostname(), err)
}
defer connection.Close()
ch, err := connection.Channel()
if err != nil {
return fmt.Errorf("Cannot create a channel. Err: %w", err)
}
defer ch.Close()
if err = ch.ExchangeDeclarePassive("pubsub", "topic", true, false, false, false, nil); err != nil {
return fmt.Errorf("Cannot find pubsub exchange? Err: %w", err)
}
var q rabbitmq.Queue
if len(queueName) == 0 {
q, err = ch.QueueDeclare("", false, true, true, false, nil)
} else {
q, err = ch.QueueDeclarePassive(queueName, true, false, true, false, nil)
if err != nil {
LogInfo("queue not found .. trying to create it:", err)
if ch.IsClosed() {
ch, err = connection.Channel()
if err != nil {
return fmt.Errorf("Channel cannot be re-opened. Err: %w", err)
}
}
q, err = ch.QueueDeclare(queueName, true, false, true, false, nil)
if err != nil {
LogInfo("can't create persistent queue ... falling back to temporaty queue:", err)
if ch.IsClosed() {
ch, err = connection.Channel()
return fmt.Errorf("Channel cannot be re-opened. Err: %w", err)
}
q, err = ch.QueueDeclare("", false, true, true, false, nil)
}
}
}
if err != nil {
return fmt.Errorf("Cannot declare queue. Err: %w", err)
}
// log.Printf("queue: %s:%d", q.Name, q.Consumers)
LogInfo(" -- listening to topics:")
l.topicSubChanges = make(chan string)
defer close(l.topicSubChanges)
go l.processTopicChanges(ch, q.Name)
for _, topic := range l.topics {
l.topicSubChanges <- "+" + topic
}
msgs, err := ch.Consume(q.Name, "", true, true, false, false, nil)
if err != nil {
return fmt.Errorf("Cannot start consumer. Err: %w", err)
}
// log.Printf("queue: %s:%d", q.Name, q.Consumers)
for {
msg, ok := <-msgs
if !ok {
return fmt.Errorf("channel/connection closed?\n")
}
msgCh <- RabbitMessage(msg)
}
}
func (l *ListenDefinitions) connectAndProcessRabbitMQ(ch chan<- RabbitMessage) {
defer func() {
if r := recover(); r != nil {
LogError(r)
LogError("'crash' RabbitMQ worker. Recovering... reconnecting...")
time.Sleep(5 * time.Second)
go l.connectAndProcessRabbitMQ(ch)
}
}()
for {
err := l.processRabbitMQ(ch)
if err != nil {
LogError("Error in RabbitMQ connection. %#v", err)
LogInfo("Reconnecting in 2 seconds...")
time.Sleep(2 * time.Second)
}
}
}
func (l *ListenDefinitions) connectToRabbitMQ() chan RabbitMessage {
ch := make(chan RabbitMessage, 100)
go l.connectAndProcessRabbitMQ(ch)
return ch
}
func ProcessEvent(f RequestProcessor, request *Request) {
defer func() {
if r := recover(); r != nil {
LogError("panic caught")
if err, ok := r.(error); !ok {
LogError(err)
}
LogError(string(debug.Stack()))
}
}()
if err := f.ProcessFunc(request); err != nil {
LogError(err)
}
}
func (l *ListenDefinitions) generateTopics() []string {
topics := make([]string, 0, len(l.Handlers)*len(l.Orgs))
scope := "suse"
if l.RabbitURL.Hostname() == "rabbit.opensuse.org" {
scope = "opensuse"
}
for _, org := range l.Orgs {
for requestType, _ := range l.Handlers {
topics = append(topics, fmt.Sprintf("%s.src.%s.%s.#", scope, org, requestType))
}
}
slices.Sort(topics)
return slices.Compact(topics)
}
func (l *ListenDefinitions) UpdateTopics() {
newTopics := l.generateTopics()
j := 0
next_new_topic:
for i := 0; i < len(newTopics); i++ {
topic := newTopics[i]
for j < len(l.topics) {
cmp := strings.Compare(topic, l.topics[j])
if cmp == 0 {
j++
continue next_new_topic
}
if cmp < 0 {
l.topicSubChanges <- "+" + topic
break
}
l.topicSubChanges <- "-" + l.topics[j]
j++
}
if j == len(l.topics) {
l.topicSubChanges <- "+" + topic
}
}
}
func (l *ListenDefinitions) ProcessRabbitMQEvents() error {
LogInfo("RabbitMQ connection:", l.RabbitURL.String())
LogDebug("# Handlers:", len(l.Handlers))
LogDebug("# Orgs:", len(l.Orgs))
l.RabbitURL.User = url.UserPassword(rabbitUser, rabbitPassword)
l.topics = l.generateTopics()
ch := l.connectToRabbitMQ()
for {
msg, ok := <-ch
if !ok {
return nil
}
LogDebug("event:", msg.RoutingKey)
route := strings.Split(msg.RoutingKey, ".")
if len(route) > 3 {
reqType := route[3]
org := route[2]
if !slices.Contains(l.Orgs, org) {
LogInfo("Got event for unhandeled org:", org)
continue
}
LogDebug("org:", org, "type:", reqType)
if handler, found := l.Handlers[reqType]; found {
/* h, err := CreateRequestHandler()
if err != nil {
log.Println("Cannot create request handler", err)
continue
}
*/
req, err := ParseRequestJSON(reqType, msg.Body)
if err != nil {
LogError("Error parsing request JSON:", err)
continue
} else {
LogDebug("processing req", req.Type)
// h.Request = req
ProcessEvent(handler, req)
}
}
}
}
}

View File

@@ -1,48 +0,0 @@
package common
import (
"net/url"
"testing"
)
func TestListenDefinitionsTopicUpdate(t *testing.T) {
tests := []struct {
name string
handlers []string
orgs1, orgs2 []string
topicDelta []string
}{
{
name: "no handlers, no orgs",
},
{
name: "adding one org",
handlers: []string{"foo"},
orgs2: []string{"newOrg"},
topicDelta: []string{"+suse"},
},
}
u, _ := url.Parse("amqps://rabbit.example.com")
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
l := ListenDefinitions{
Orgs: test.orgs1,
Handlers: make(map[string]RequestProcessor),
topicSubChanges: make(chan string, len(test.topicDelta)*10),
RabbitURL: u,
}
for _, r := range test.handlers {
l.Handlers[r] = nil
}
l.UpdateTopics()
if len(l.topicSubChanges) != len(test.topicDelta) {
t.Fatal("topicSubChanges", len(l.topicSubChanges), " != topicDelta", len(test.topicDelta))
}
})
}
}

View File

@@ -36,13 +36,14 @@ func CreateStdoutLogger(stdout, stderr io.Writer) (*log.Logger, *log.Logger) {
func PanicOnError(err error) {
if err != nil {
LogError(err)
panic(err)
}
}
func PanicOnErrorWithMsg(err error, msg string) {
func PanicOnErrorWithMsg(err error, msg ...any) {
if err != nil {
LogError(msg)
LogError(msg...)
panic(err)
}
}
@@ -51,28 +52,70 @@ type LogLevel int
const (
LogLevelNone = 0
LogLevelError = 2
LogLevelInfo = 5
LogLevelDebug = 10
)
var logLevel LogLevel
var logLevel LogLevel = LogLevelInfo
func SetLoggingLevel(ll LogLevel) {
logLevel = ll
}
func GetLoggingLevel() LogLevel {
return logLevel
}
type Logger interface {
Log(args ...any)
}
var testLogger Logger
func SetTestLogger(l Logger) {
testLogger = l
}
func SetLoggingLevelFromString(ll string) error {
switch ll {
case "info":
SetLoggingLevel(LogLevelInfo)
case "debug":
SetLoggingLevel(LogLevelDebug)
case "error":
SetLoggingLevel(LogLevelError)
case "none":
SetLoggingLevel(LogLevelNone)
default:
return fmt.Errorf("Unknown logging level: %s", ll)
}
return nil
}
func LogError(params ...any) {
log.Println(append([]any{"[E]"}, params...)...)
if logLevel >= LogLevelError {
logit("[E]", params...)
}
}
func LogDebug(params ...any) {
if logLevel >= LogLevelDebug {
log.Println(append([]any{"[D]"}, params...)...)
logit("[D]", params...)
}
}
func LogInfo(params ...any) {
if logLevel >= LogLevelInfo {
log.Println(append([]any{"[I]"}, params...)...)
logit("[I]", params...)
}
}
func logit(prefix string, params ...any) {
if testLogger != nil {
testLogger.Log(append([]any{prefix}, params...)...)
} else {
log.Println(append([]any{prefix}, params...)...)
}
}

View File

@@ -13,10 +13,10 @@ import (
//go:generate mockgen -source=maintainership.go -destination=mock/maintainership.go -typed
type MaintainershipData interface {
ListProjectMaintainers() []string
ListPackageMaintainers(pkg string) []string
ListProjectMaintainers(OptionalGroupExpansion []*ReviewGroup) []string
ListPackageMaintainers(Pkg string, OptionalGroupExpasion []*ReviewGroup) []string
IsApproved(pkg string, reviews []*models.PullReview) bool
IsApproved(Pkg string, Reviews []*models.PullReview, Submitter string, ReviewGroups []*ReviewGroup) bool
}
const ProjectKey = ""
@@ -25,6 +25,7 @@ const ProjectFileKey = "_project"
type MaintainershipMap struct {
Data map[string][]string
IsDir bool
Config *AutogitConfig
FetchPackage func(string) ([]byte, error)
}
@@ -39,17 +40,20 @@ func parseMaintainershipData(data []byte) (*MaintainershipMap, error) {
return maintainers, nil
}
func FetchProjectMaintainershipData(gitea GiteaMaintainershipReader, org, prjGit, branch string) (*MaintainershipMap, error) {
func FetchProjectMaintainershipData(gitea GiteaMaintainershipReader, config *AutogitConfig) (*MaintainershipMap, error) {
org, prjGit, branch := config.GetPrjGit()
data, _, err := gitea.FetchMaintainershipDirFile(org, prjGit, branch, ProjectFileKey)
dir := true
if err != nil || data == nil {
dir = false
if _, notFound := err.(*repository.RepoGetRawFileNotFound); !notFound {
if _, notFound := err.(*repository.RepoGetContentsNotFound); !notFound {
return nil, err
}
LogDebug("Falling back to maintainership file")
data, _, err = gitea.FetchMaintainershipFile(org, prjGit, branch)
if err != nil || data == nil {
if _, notFound := err.(*repository.RepoGetRawFileNotFound); !notFound {
if _, notFound := err.(*repository.RepoGetContentsNotFound); !notFound {
return nil, err
}
@@ -60,16 +64,17 @@ func FetchProjectMaintainershipData(gitea GiteaMaintainershipReader, org, prjGit
m, err := parseMaintainershipData(data)
if m != nil {
m.Config = config
m.IsDir = dir
m.FetchPackage = func(pkg string) ([]byte, error) {
data , _, err := gitea.FetchMaintainershipDirFile(org, prjGit, branch, pkg)
data, _, err := gitea.FetchMaintainershipDirFile(org, prjGit, branch, pkg)
return data, err
}
}
return m, err
}
func (data *MaintainershipMap) ListProjectMaintainers() []string {
func (data *MaintainershipMap) ListProjectMaintainers(groups []*ReviewGroup) []string {
if data == nil {
return nil
}
@@ -79,6 +84,11 @@ func (data *MaintainershipMap) ListProjectMaintainers() []string {
return nil
}
// expands groups
for _, g := range groups {
m = g.ExpandMaintainers(m)
}
return m
}
@@ -95,7 +105,7 @@ func parsePkgDirData(pkg string, data []byte) []string {
return pkgMaintainers
}
func (data *MaintainershipMap) ListPackageMaintainers(pkg string) []string {
func (data *MaintainershipMap) ListPackageMaintainers(pkg string, groups []*ReviewGroup) []string {
if data == nil {
return nil
}
@@ -110,7 +120,7 @@ func (data *MaintainershipMap) ListPackageMaintainers(pkg string) []string {
}
}
}
prjMaintainers := data.ListProjectMaintainers()
prjMaintainers := data.ListProjectMaintainers(nil)
prjMaintainer:
for _, prjm := range prjMaintainers {
@@ -122,30 +132,38 @@ prjMaintainer:
pkgMaintainers = append(pkgMaintainers, prjm)
}
// expands groups
for _, g := range groups {
pkgMaintainers = g.ExpandMaintainers(pkgMaintainers)
}
return pkgMaintainers
}
func (data *MaintainershipMap) IsApproved(pkg string, reviews []*models.PullReview) bool {
reviewers, found := data.Data[pkg]
if !found {
if pkg != ProjectKey && data.IsDir {
r, err := data.FetchPackage(pkg)
if err != nil {
return false
}
reviewers = parsePkgDirData(pkg, r)
data.Data[pkg] = reviewers
} else {
return true
}
func (data *MaintainershipMap) IsApproved(pkg string, reviews []*models.PullReview, submitter string, groups []*ReviewGroup) bool {
var reviewers []string
if pkg != ProjectKey {
reviewers = data.ListPackageMaintainers(pkg, groups)
} else {
reviewers = data.ListProjectMaintainers(groups)
}
if len(reviewers) == 0 {
return true
}
LogDebug("Looking for review by:", reviewers)
slices.Sort(reviewers)
reviewers = slices.Compact(reviewers)
SubmitterIdxInReviewers := slices.Index(reviewers, submitter)
if SubmitterIdxInReviewers > -1 && (!data.Config.ReviewRequired || len(reviewers) == 1) {
LogDebug("Submitter is maintainer. Approving.")
return true
}
for _, review := range reviews {
if !review.Stale && review.State == ReviewStateApproved && slices.Contains(reviewers, review.User.UserName) {
LogDebug("Reviewed by", review.User.UserName)
return true
}
@@ -183,7 +201,7 @@ func (data *MaintainershipMap) WriteMaintainershipFile(writer io.StringWriter) e
keys = slices.Delete(keys, i, len(keys))
}
slices.Sort(keys)
for i, pkg := range(keys) {
for i, pkg := range keys {
eol := ","
if i == len(keys)-1 {
eol = ""

View File

@@ -13,10 +13,10 @@ import (
)
func TestMaintainership(t *testing.T) {
config := common.AutogitConfig{
config := &common.AutogitConfig{
Branch: "bar",
Organization: "foo",
GitProjectName: common.DefaultGitPrj,
GitProjectName: common.DefaultGitPrj + "#bar",
}
packageTests := []struct {
@@ -28,6 +28,8 @@ func TestMaintainership(t *testing.T) {
maintainersFile []byte
maintainersFileErr error
groups []*common.ReviewGroup
maintainersDir map[string][]byte
}{
/* PACKAGE MAINTAINERS */
@@ -51,6 +53,22 @@ func TestMaintainership(t *testing.T) {
maintainers: []string{"user1", "user2", "user3"},
packageName: "pkg",
},
{
name: "Multiple package maintainers and groups",
maintainersFile: []byte(`{"pkg": ["user1", "user2", "g2"], "": ["g2", "user1", "user3"]}`),
maintainersDir: map[string][]byte{
"_project": []byte(`{"": ["user1", "user3", "g2"]}`),
"pkg": []byte(`{"pkg": ["user1", "g2", "user2"]}`),
},
maintainers: []string{"user1", "user2", "user3", "user5"},
packageName: "pkg",
groups: []*common.ReviewGroup{
{
Name: "g2",
Reviewers: []string{"user1", "user5"},
},
},
},
{
name: "No package maintainers and only project maintainer",
maintainersFile: []byte(`{"pkg2": ["user1", "user2"], "": ["user1", "user3"]}`),
@@ -120,10 +138,10 @@ func TestMaintainership(t *testing.T) {
},
}
notFoundError := repository.NewRepoGetRawFileNotFound()
notFoundError := repository.NewRepoGetContentsNotFound()
for _, test := range packageTests {
runTests := func(t *testing.T, mi common.GiteaMaintainershipReader) {
maintainers, err := common.FetchProjectMaintainershipData(mi, config.Organization, config.GitProjectName, config.Branch)
maintainers, err := common.FetchProjectMaintainershipData(mi, config)
if err != nil && !test.otherError {
if test.maintainersFileErr == nil {
t.Fatal("Unexpected error recieved", err)
@@ -138,9 +156,9 @@ func TestMaintainership(t *testing.T) {
var m []string
if len(test.packageName) > 0 {
m = maintainers.ListPackageMaintainers(test.packageName)
m = maintainers.ListPackageMaintainers(test.packageName, test.groups)
} else {
m = maintainers.ListProjectMaintainers()
m = maintainers.ListProjectMaintainers(test.groups)
}
if len(m) != len(test.maintainers) {
@@ -154,7 +172,7 @@ func TestMaintainership(t *testing.T) {
}
t.Run(test.name+"_File", func(t *testing.T) {
ctl := gomock.NewController(t)
ctl := NewController(t)
mi := mock_common.NewMockGiteaMaintainershipReader(ctl)
// tests with maintainership file
@@ -167,7 +185,7 @@ func TestMaintainership(t *testing.T) {
})
t.Run(test.name+"_Dir", func(t *testing.T) {
ctl := gomock.NewController(t)
ctl := NewController(t)
mi := mock_common.NewMockGiteaMaintainershipReader(ctl)
// run same tests with directory maintainership data
@@ -207,7 +225,7 @@ func TestMaintainershipFileWrite(t *testing.T) {
{
name: "2 project maintainers and 2 single package maintainers",
maintainers: map[string][]string{
"": {"two", "one"},
"": {"two", "one"},
"pkg1": {},
"foo": {"four", "byte"},
},
@@ -235,3 +253,43 @@ func TestMaintainershipFileWrite(t *testing.T) {
})
}
}
func TestReviewRequired(t *testing.T) {
tests := []struct {
name string
maintainers []string
config *common.AutogitConfig
is_approved bool
}{
{
name: "ReviewRequired=false",
maintainers: []string{"maintainer1", "maintainer2"},
config: &common.AutogitConfig{ReviewRequired: false},
is_approved: true,
},
{
name: "ReviewRequired=true",
maintainers: []string{"maintainer1", "maintainer2"},
config: &common.AutogitConfig{ReviewRequired: true},
is_approved: false,
},
{
name: "ReviewRequired=true",
maintainers: []string{"maintainer1"},
config: &common.AutogitConfig{ReviewRequired: true},
is_approved: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
m := &common.MaintainershipMap{
Data: map[string][]string{"": test.maintainers},
}
m.Config = test.config
if approved := m.IsApproved("", nil, "maintainer1", nil); approved != test.is_approved {
t.Error("Expected m.IsApproved()->", test.is_approved, "but didn't get it")
}
})
}
}

56
common/manifest.go Normal file
View File

@@ -0,0 +1,56 @@
package common
import (
"os"
"path"
"strings"
"gopkg.in/yaml.v3"
)
type Manifest struct {
Subdirectories []string
}
func (m *Manifest) SubdirForPackage(pkg string) string {
if m == nil {
return pkg
}
idx := -1
matchLen := 0
basePkg := path.Base(pkg)
lowercasePkg := strings.ToLower(basePkg)
for i, sub := range m.Subdirectories {
basename := strings.ToLower(path.Base(sub))
if strings.HasPrefix(lowercasePkg, basename) && matchLen < len(basename) {
idx = i
matchLen = len(basename)
}
}
if idx > -1 {
return path.Join(m.Subdirectories[idx], basePkg)
}
return pkg
}
func ReadManifestFile(filename string) (*Manifest, error) {
data, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
return ParseManifestFile(data)
}
func ParseManifestFile(data []byte) (*Manifest, error) {
ret := &Manifest{}
err := yaml.Unmarshal(data, ret)
if err != nil {
return nil, err
}
return ret, nil
}

57
common/manifest_test.go Normal file
View File

@@ -0,0 +1,57 @@
package common_test
import (
"testing"
"src.opensuse.org/autogits/common"
)
func TestManifestSubdirAssignments(t *testing.T) {
common.SetTestLogger(t)
tests := []struct {
Name string
ManifestContent string
Packages []string
ManifestLocations []string
}{
{
Name: "empty manifest",
Packages: []string{"atom", "blarg", "Foobar", "X-Ray", "boost", "NodeJS"},
ManifestLocations: []string{"atom", "blarg", "Foobar", "X-Ray", "boost", "NodeJS"},
},
{
Name: "only few subdirs manifest",
ManifestContent: "subdirectories:\n - a\n - b",
Packages: []string{"atom", "blarg", "Foobar", "X-Ray", "Boost", "NodeJS"},
ManifestLocations: []string{"a/atom", "b/blarg", "Foobar", "X-Ray", "b/Boost", "NodeJS"},
},
{
Name: "multilayer subdirs manifest",
ManifestContent: "subdirectories:\n - a\n - b\n - libs/boo",
Packages: []string{"atom", "blarg", "Foobar", "X-Ray", "Boost", "NodeJS"},
ManifestLocations: []string{"a/atom", "b/blarg", "Foobar", "X-Ray", "libs/boo/Boost", "NodeJS"},
},
{
Name: "multilayer subdirs manifest with trailing /",
ManifestContent: "subdirectories:\n - a\n - b\n - libs/boo/\n - somedir/Node/",
Packages: []string{"atom", "blarg", "Foobar", "X-Ray", "Boost", "NodeJS", "foobar/node2"},
ManifestLocations: []string{"a/atom", "b/blarg", "Foobar", "X-Ray", "libs/boo/Boost", "somedir/Node/NodeJS", "somedir/Node/node2"},
},
}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
m, err := common.ParseManifestFile([]byte(test.ManifestContent))
if err != nil {
t.Fatal(err)
}
for i, pkg := range test.Packages {
expected := test.ManifestLocations[i]
if l := m.SubdirForPackage(pkg); l != expected {
t.Error("Expected:", expected, "but got:", l)
}
}
})
}
}

120
common/mock/config.go Normal file
View File

@@ -0,0 +1,120 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: config.go
//
// Generated by this command:
//
// mockgen -source=config.go -destination=mock/config.go -typed
//
// Package mock_common is a generated GoMock package.
package mock_common
import (
reflect "reflect"
gomock "go.uber.org/mock/gomock"
models "src.opensuse.org/autogits/common/gitea-generated/models"
)
// MockGiteaFileContentAndRepoFetcher is a mock of GiteaFileContentAndRepoFetcher interface.
type MockGiteaFileContentAndRepoFetcher struct {
ctrl *gomock.Controller
recorder *MockGiteaFileContentAndRepoFetcherMockRecorder
isgomock struct{}
}
// MockGiteaFileContentAndRepoFetcherMockRecorder is the mock recorder for MockGiteaFileContentAndRepoFetcher.
type MockGiteaFileContentAndRepoFetcherMockRecorder struct {
mock *MockGiteaFileContentAndRepoFetcher
}
// NewMockGiteaFileContentAndRepoFetcher creates a new mock instance.
func NewMockGiteaFileContentAndRepoFetcher(ctrl *gomock.Controller) *MockGiteaFileContentAndRepoFetcher {
mock := &MockGiteaFileContentAndRepoFetcher{ctrl: ctrl}
mock.recorder = &MockGiteaFileContentAndRepoFetcherMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockGiteaFileContentAndRepoFetcher) EXPECT() *MockGiteaFileContentAndRepoFetcherMockRecorder {
return m.recorder
}
// GetRepository mocks base method.
func (m *MockGiteaFileContentAndRepoFetcher) GetRepository(org, repo string) (*models.Repository, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetRepository", org, repo)
ret0, _ := ret[0].(*models.Repository)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetRepository indicates an expected call of GetRepository.
func (mr *MockGiteaFileContentAndRepoFetcherMockRecorder) GetRepository(org, repo any) *MockGiteaFileContentAndRepoFetcherGetRepositoryCall {
mr.mock.ctrl.T.Helper()
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRepository", reflect.TypeOf((*MockGiteaFileContentAndRepoFetcher)(nil).GetRepository), org, repo)
return &MockGiteaFileContentAndRepoFetcherGetRepositoryCall{Call: call}
}
// MockGiteaFileContentAndRepoFetcherGetRepositoryCall wrap *gomock.Call
type MockGiteaFileContentAndRepoFetcherGetRepositoryCall struct {
*gomock.Call
}
// Return rewrite *gomock.Call.Return
func (c *MockGiteaFileContentAndRepoFetcherGetRepositoryCall) Return(arg0 *models.Repository, arg1 error) *MockGiteaFileContentAndRepoFetcherGetRepositoryCall {
c.Call = c.Call.Return(arg0, arg1)
return c
}
// Do rewrite *gomock.Call.Do
func (c *MockGiteaFileContentAndRepoFetcherGetRepositoryCall) Do(f func(string, string) (*models.Repository, error)) *MockGiteaFileContentAndRepoFetcherGetRepositoryCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
func (c *MockGiteaFileContentAndRepoFetcherGetRepositoryCall) DoAndReturn(f func(string, string) (*models.Repository, error)) *MockGiteaFileContentAndRepoFetcherGetRepositoryCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// GetRepositoryFileContent mocks base method.
func (m *MockGiteaFileContentAndRepoFetcher) GetRepositoryFileContent(org, repo, hash, path string) ([]byte, string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetRepositoryFileContent", org, repo, hash, path)
ret0, _ := ret[0].([]byte)
ret1, _ := ret[1].(string)
ret2, _ := ret[2].(error)
return ret0, ret1, ret2
}
// GetRepositoryFileContent indicates an expected call of GetRepositoryFileContent.
func (mr *MockGiteaFileContentAndRepoFetcherMockRecorder) GetRepositoryFileContent(org, repo, hash, path any) *MockGiteaFileContentAndRepoFetcherGetRepositoryFileContentCall {
mr.mock.ctrl.T.Helper()
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRepositoryFileContent", reflect.TypeOf((*MockGiteaFileContentAndRepoFetcher)(nil).GetRepositoryFileContent), org, repo, hash, path)
return &MockGiteaFileContentAndRepoFetcherGetRepositoryFileContentCall{Call: call}
}
// MockGiteaFileContentAndRepoFetcherGetRepositoryFileContentCall wrap *gomock.Call
type MockGiteaFileContentAndRepoFetcherGetRepositoryFileContentCall struct {
*gomock.Call
}
// Return rewrite *gomock.Call.Return
func (c *MockGiteaFileContentAndRepoFetcherGetRepositoryFileContentCall) Return(arg0 []byte, arg1 string, arg2 error) *MockGiteaFileContentAndRepoFetcherGetRepositoryFileContentCall {
c.Call = c.Call.Return(arg0, arg1, arg2)
return c
}
// Do rewrite *gomock.Call.Do
func (c *MockGiteaFileContentAndRepoFetcherGetRepositoryFileContentCall) Do(f func(string, string, string, string) ([]byte, string, error)) *MockGiteaFileContentAndRepoFetcherGetRepositoryFileContentCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
func (c *MockGiteaFileContentAndRepoFetcherGetRepositoryFileContentCall) DoAndReturn(f func(string, string, string, string) ([]byte, string, error)) *MockGiteaFileContentAndRepoFetcherGetRepositoryFileContentCall {
c.Call = c.Call.DoAndReturn(f)
return c
}

1226
common/mock/git_utils.go Normal file

File diff suppressed because it is too large Load Diff

3856
common/mock/gitea_utils.go Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,156 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: maintainership.go
//
// Generated by this command:
//
// mockgen -source=maintainership.go -destination=mock/maintainership.go -typed
//
// Package mock_common is a generated GoMock package.
package mock_common
import (
reflect "reflect"
gomock "go.uber.org/mock/gomock"
common "src.opensuse.org/autogits/common"
models "src.opensuse.org/autogits/common/gitea-generated/models"
)
// MockMaintainershipData is a mock of MaintainershipData interface.
type MockMaintainershipData struct {
ctrl *gomock.Controller
recorder *MockMaintainershipDataMockRecorder
isgomock struct{}
}
// MockMaintainershipDataMockRecorder is the mock recorder for MockMaintainershipData.
type MockMaintainershipDataMockRecorder struct {
mock *MockMaintainershipData
}
// NewMockMaintainershipData creates a new mock instance.
func NewMockMaintainershipData(ctrl *gomock.Controller) *MockMaintainershipData {
mock := &MockMaintainershipData{ctrl: ctrl}
mock.recorder = &MockMaintainershipDataMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockMaintainershipData) EXPECT() *MockMaintainershipDataMockRecorder {
return m.recorder
}
// IsApproved mocks base method.
func (m *MockMaintainershipData) IsApproved(Pkg string, Reviews []*models.PullReview, Submitter string, ReviewGroups []*common.ReviewGroup) bool {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "IsApproved", Pkg, Reviews, Submitter, ReviewGroups)
ret0, _ := ret[0].(bool)
return ret0
}
// IsApproved indicates an expected call of IsApproved.
func (mr *MockMaintainershipDataMockRecorder) IsApproved(Pkg, Reviews, Submitter, ReviewGroups any) *MockMaintainershipDataIsApprovedCall {
mr.mock.ctrl.T.Helper()
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsApproved", reflect.TypeOf((*MockMaintainershipData)(nil).IsApproved), Pkg, Reviews, Submitter, ReviewGroups)
return &MockMaintainershipDataIsApprovedCall{Call: call}
}
// MockMaintainershipDataIsApprovedCall wrap *gomock.Call
type MockMaintainershipDataIsApprovedCall struct {
*gomock.Call
}
// Return rewrite *gomock.Call.Return
func (c *MockMaintainershipDataIsApprovedCall) Return(arg0 bool) *MockMaintainershipDataIsApprovedCall {
c.Call = c.Call.Return(arg0)
return c
}
// Do rewrite *gomock.Call.Do
func (c *MockMaintainershipDataIsApprovedCall) Do(f func(string, []*models.PullReview, string, []*common.ReviewGroup) bool) *MockMaintainershipDataIsApprovedCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
func (c *MockMaintainershipDataIsApprovedCall) DoAndReturn(f func(string, []*models.PullReview, string, []*common.ReviewGroup) bool) *MockMaintainershipDataIsApprovedCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// ListPackageMaintainers mocks base method.
func (m *MockMaintainershipData) ListPackageMaintainers(Pkg string, OptionalGroupExpasion []*common.ReviewGroup) []string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ListPackageMaintainers", Pkg, OptionalGroupExpasion)
ret0, _ := ret[0].([]string)
return ret0
}
// ListPackageMaintainers indicates an expected call of ListPackageMaintainers.
func (mr *MockMaintainershipDataMockRecorder) ListPackageMaintainers(Pkg, OptionalGroupExpasion any) *MockMaintainershipDataListPackageMaintainersCall {
mr.mock.ctrl.T.Helper()
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListPackageMaintainers", reflect.TypeOf((*MockMaintainershipData)(nil).ListPackageMaintainers), Pkg, OptionalGroupExpasion)
return &MockMaintainershipDataListPackageMaintainersCall{Call: call}
}
// MockMaintainershipDataListPackageMaintainersCall wrap *gomock.Call
type MockMaintainershipDataListPackageMaintainersCall struct {
*gomock.Call
}
// Return rewrite *gomock.Call.Return
func (c *MockMaintainershipDataListPackageMaintainersCall) Return(arg0 []string) *MockMaintainershipDataListPackageMaintainersCall {
c.Call = c.Call.Return(arg0)
return c
}
// Do rewrite *gomock.Call.Do
func (c *MockMaintainershipDataListPackageMaintainersCall) Do(f func(string, []*common.ReviewGroup) []string) *MockMaintainershipDataListPackageMaintainersCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
func (c *MockMaintainershipDataListPackageMaintainersCall) DoAndReturn(f func(string, []*common.ReviewGroup) []string) *MockMaintainershipDataListPackageMaintainersCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// ListProjectMaintainers mocks base method.
func (m *MockMaintainershipData) ListProjectMaintainers(OptionalGroupExpansion []*common.ReviewGroup) []string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ListProjectMaintainers", OptionalGroupExpansion)
ret0, _ := ret[0].([]string)
return ret0
}
// ListProjectMaintainers indicates an expected call of ListProjectMaintainers.
func (mr *MockMaintainershipDataMockRecorder) ListProjectMaintainers(OptionalGroupExpansion any) *MockMaintainershipDataListProjectMaintainersCall {
mr.mock.ctrl.T.Helper()
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListProjectMaintainers", reflect.TypeOf((*MockMaintainershipData)(nil).ListProjectMaintainers), OptionalGroupExpansion)
return &MockMaintainershipDataListProjectMaintainersCall{Call: call}
}
// MockMaintainershipDataListProjectMaintainersCall wrap *gomock.Call
type MockMaintainershipDataListProjectMaintainersCall struct {
*gomock.Call
}
// Return rewrite *gomock.Call.Return
func (c *MockMaintainershipDataListProjectMaintainersCall) Return(arg0 []string) *MockMaintainershipDataListProjectMaintainersCall {
c.Call = c.Call.Return(arg0)
return c
}
// Do rewrite *gomock.Call.Do
func (c *MockMaintainershipDataListProjectMaintainersCall) Do(f func([]*common.ReviewGroup) []string) *MockMaintainershipDataListProjectMaintainersCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
func (c *MockMaintainershipDataListProjectMaintainersCall) DoAndReturn(f func([]*common.ReviewGroup) []string) *MockMaintainershipDataListProjectMaintainersCall {
c.Call = c.Call.DoAndReturn(f)
return c
}

85
common/mock/obs_utils.go Normal file
View File

@@ -0,0 +1,85 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: obs_utils.go
//
// Generated by this command:
//
// mockgen -source=obs_utils.go -destination=mock/obs_utils.go -typed
//
// Package mock_common is a generated GoMock package.
package mock_common
import (
reflect "reflect"
gomock "go.uber.org/mock/gomock"
common "src.opensuse.org/autogits/common"
)
// MockObsStatusFetcherWithState is a mock of ObsStatusFetcherWithState interface.
type MockObsStatusFetcherWithState struct {
ctrl *gomock.Controller
recorder *MockObsStatusFetcherWithStateMockRecorder
isgomock struct{}
}
// MockObsStatusFetcherWithStateMockRecorder is the mock recorder for MockObsStatusFetcherWithState.
type MockObsStatusFetcherWithStateMockRecorder struct {
mock *MockObsStatusFetcherWithState
}
// NewMockObsStatusFetcherWithState creates a new mock instance.
func NewMockObsStatusFetcherWithState(ctrl *gomock.Controller) *MockObsStatusFetcherWithState {
mock := &MockObsStatusFetcherWithState{ctrl: ctrl}
mock.recorder = &MockObsStatusFetcherWithStateMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockObsStatusFetcherWithState) EXPECT() *MockObsStatusFetcherWithStateMockRecorder {
return m.recorder
}
// BuildStatusWithState mocks base method.
func (m *MockObsStatusFetcherWithState) BuildStatusWithState(project string, opts *common.BuildResultOptions, packages ...string) (*common.BuildResultList, error) {
m.ctrl.T.Helper()
varargs := []any{project, opts}
for _, a := range packages {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "BuildStatusWithState", varargs...)
ret0, _ := ret[0].(*common.BuildResultList)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// BuildStatusWithState indicates an expected call of BuildStatusWithState.
func (mr *MockObsStatusFetcherWithStateMockRecorder) BuildStatusWithState(project, opts any, packages ...any) *MockObsStatusFetcherWithStateBuildStatusWithStateCall {
mr.mock.ctrl.T.Helper()
varargs := append([]any{project, opts}, packages...)
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BuildStatusWithState", reflect.TypeOf((*MockObsStatusFetcherWithState)(nil).BuildStatusWithState), varargs...)
return &MockObsStatusFetcherWithStateBuildStatusWithStateCall{Call: call}
}
// MockObsStatusFetcherWithStateBuildStatusWithStateCall wrap *gomock.Call
type MockObsStatusFetcherWithStateBuildStatusWithStateCall struct {
*gomock.Call
}
// Return rewrite *gomock.Call.Return
func (c *MockObsStatusFetcherWithStateBuildStatusWithStateCall) Return(arg0 *common.BuildResultList, arg1 error) *MockObsStatusFetcherWithStateBuildStatusWithStateCall {
c.Call = c.Call.Return(arg0, arg1)
return c
}
// Do rewrite *gomock.Call.Do
func (c *MockObsStatusFetcherWithStateBuildStatusWithStateCall) Do(f func(string, *common.BuildResultOptions, ...string) (*common.BuildResultList, error)) *MockObsStatusFetcherWithStateBuildStatusWithStateCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
func (c *MockObsStatusFetcherWithStateBuildStatusWithStateCall) DoAndReturn(f func(string, *common.BuildResultOptions, ...string) (*common.BuildResultList, error)) *MockObsStatusFetcherWithStateBuildStatusWithStateCall {
c.Call = c.Call.DoAndReturn(f)
return c
}

View File

@@ -25,7 +25,6 @@ import (
"errors"
"fmt"
"io"
"log"
"net/http"
"net/url"
"os/exec"
@@ -59,7 +58,7 @@ type ObsClient struct {
}
func NewObsClient(host string) (*ObsClient, error) {
baseUrl, err := url.Parse("https://" + host)
baseUrl, err := url.Parse(host)
if err != nil {
return nil, err
}
@@ -128,10 +127,12 @@ type ProjectMeta struct {
Groups []GroupRepoMeta `xml:"group"`
Repositories []RepositoryMeta `xml:"repository"`
BuildFlags Flags `xml:"build"`
PublicFlags Flags `xml:"publish"`
DebugFlags Flags `xml:"debuginfo"`
UseForBuild Flags `xml:"useforbuild"`
BuildFlags Flags `xml:"build"`
PublicFlags Flags `xml:"publish"`
DebugFlags Flags `xml:"debuginfo"`
UseForBuild Flags `xml:"useforbuild"`
Access Flags `xml:"access"`
SourceAccess Flags `xml:"sourceaccess"`
}
type PackageMeta struct {
@@ -141,6 +142,12 @@ type PackageMeta struct {
ScmSync string `xml:"scmsync"`
Persons []PersonRepoMeta `xml:"person"`
Groups []GroupRepoMeta `xml:"group"`
BuildFlags Flags `xml:"build"`
PublicFlags Flags `xml:"publish"`
DebugFlags Flags `xml:"debuginfo"`
UseForBuild Flags `xml:"useforbuild"`
SourceAccess Flags `xml:"sourceaccess"`
}
type UserMeta struct {
@@ -157,6 +164,34 @@ type GroupMeta struct {
Persons PersonGroup `xml:"person"`
}
type RequestStateMeta struct {
XMLName xml.Name `xml:"state"`
State string `xml:"name,attr"`
}
type RequestActionTarget struct {
XMLName xml.Name
Project string `xml:"project,attr"`
Package string `xml:"package,attr"`
Revision *string `xml:"rev,attr,optional"`
}
type RequestActionMeta struct {
XMLName xml.Name `xml:"action"`
Type string `xml:"type,attr"`
Source *RequestActionTarget `xml:"source,optional"`
Target *RequestActionTarget `xml:"target,optional"`
}
type RequestMeta struct {
XMLName xml.Name `xml:"request"`
Id int `xml:"id,attr"`
Creator string `xml:"creator,attr"`
Action *RequestActionMeta `xml:"action"`
State RequestStateMeta `xml:"state"`
}
func parseProjectMeta(data []byte) (*ProjectMeta, error) {
var meta ProjectMeta
err := xml.Unmarshal(data, &meta)
@@ -167,8 +202,83 @@ func parseProjectMeta(data []byte) (*ProjectMeta, error) {
return &meta, nil
}
const (
RequestStatus_Unknown = "unknown"
RequestStatus_Accepted = "accepted"
RequestStatus_Superseded = "superseded"
RequestStatus_Declined = "declined"
RequestStatus_Revoked = "revoked"
RequestStatus_New = "new"
RequestStatus_Review = "review"
)
func (status *RequestStateMeta) IsFinal() bool {
switch status.State {
case RequestStatus_Declined, RequestStatus_Revoked, RequestStatus_Accepted, RequestStatus_Superseded:
return true
}
return false
}
func parseRequestXml(data []byte) (*RequestMeta, error) {
ret := RequestMeta{}
LogDebug("parsing: ", string(data))
if err := xml.Unmarshal(data, &ret); err != nil {
return nil, err
}
return &ret, nil
}
func (c *ObsClient) CreateSubmitRequest(sourcePrj, sourcePkg, targetPrj string) (*RequestMeta, error) {
url := c.baseUrl.JoinPath("request")
query := url.Query()
query.Add("cmd", "create")
url.RawQuery = query.Encode()
request := `<request>
<action type="submit">
<source project="` + sourcePrj + `" package="` + sourcePkg + `">
</source>
<target project="` + targetPrj + `" package="` + sourcePkg + `">
</target>
</action>
</request>`
res, err := c.ObsRequestRaw("POST", url.String(), strings.NewReader(request))
if err != nil {
return nil, err
} else if res.StatusCode != 200 {
return nil, fmt.Errorf("Unexpected return code: %d", res.StatusCode)
}
data, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
return parseRequestXml(data)
}
func (c *ObsClient) RequestStatus(requestID int) (*RequestMeta, error) {
res, err := c.ObsRequest("GET", []string{"request", fmt.Sprint(requestID)}, nil)
if err != nil {
return nil, err
}
if res.StatusCode != 200 {
return nil, fmt.Errorf("Unexpected return code: %d", res.StatusCode)
}
data, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
return parseRequestXml(data)
}
func (c *ObsClient) GetGroupMeta(gid string) (*GroupMeta, error) {
res, err := c.ObsRequest("GET", c.baseUrl.JoinPath("group", gid).String(), nil)
res, err := c.ObsRequest("GET", []string{"group", gid}, nil)
if err != nil {
return nil, err
}
@@ -186,6 +296,7 @@ func (c *ObsClient) GetGroupMeta(gid string) (*GroupMeta, error) {
if err != nil {
return nil, err
}
defer res.Body.Close()
var meta GroupMeta
err = xml.Unmarshal(data, &meta)
@@ -197,7 +308,7 @@ func (c *ObsClient) GetGroupMeta(gid string) (*GroupMeta, error) {
}
func (c *ObsClient) GetUserMeta(uid string) (*UserMeta, error) {
res, err := c.ObsRequest("GET", c.baseUrl.JoinPath("person", uid).String(), nil)
res, err := c.ObsRequest("GET", []string{"person", uid}, nil)
if err != nil {
return nil, err
}
@@ -215,6 +326,7 @@ func (c *ObsClient) GetUserMeta(uid string) (*UserMeta, error) {
if err != nil {
return nil, err
}
defer res.Body.Close()
var meta UserMeta
err = xml.Unmarshal(data, &meta)
@@ -225,7 +337,11 @@ func (c *ObsClient) GetUserMeta(uid string) (*UserMeta, error) {
return &meta, nil
}
func (c *ObsClient) ObsRequest(method string, url string, body io.Reader) (*http.Response, error) {
func (c *ObsClient) ObsRequest(method string, url_path []string, body io.Reader) (*http.Response, error) {
return c.ObsRequestRaw(method, c.baseUrl.JoinPath(url_path...).String(), body)
}
func (c *ObsClient) ObsRequestRaw(method string, url string, body io.Reader) (*http.Response, error) {
req, err := http.NewRequest(method, url, body)
if err != nil {
@@ -238,6 +354,12 @@ func (c *ObsClient) ObsRequest(method string, url string, body io.Reader) (*http
req.Header.Add("cookie", c.cookie)
}
res, err := c.client.Do(req)
if err != nil && res == nil {
LogDebug("No res headers:", err)
return res, err
}
if err == nil && res.StatusCode == 200 {
auth_cookie := res.Header.Get("set-cookie")
if auth_cookie != "" {
@@ -248,6 +370,7 @@ func (c *ObsClient) ObsRequest(method string, url string, body io.Reader) (*http
if res.StatusCode == 401 {
if c.sshkey == "" {
LogDebug("setting basic auth")
req.SetBasicAuth(c.user, c.password)
} else {
www := res.Header.Get("www-authenticate")
@@ -290,28 +413,32 @@ func (c *ObsClient) ObsRequest(method string, url string, body io.Reader) (*http
// log.Printf("Add Authorization Signature ", authorization)
req.Header.Add("Authorization", "Signature "+authorization)
}
// Another time with authentification header
LogDebug("Trying again with authorization for", req.URL.String())
res, err = c.client.Do(req)
if err != nil {
if res != nil {
LogError("Authentification failed:", res.StatusCode)
}
return nil, err
}
}
// Another time with authentification header
// log.Printf("Trying again with authorization: %s", req.Header.Get("Authorization"))
res, err = c.client.Do(req)
if err != nil {
log.Println("Authentification failed:", res.StatusCode)
return nil, err
}
// Store the cookie for next call
auth_cookie := res.Header.Get("set-cookie")
if auth_cookie != "" {
c.cookie = auth_cookie
if err == nil {
// Store the cookie for next call
auth_cookie := res.Header.Get("set-cookie")
if auth_cookie != "" {
c.cookie = auth_cookie
}
}
return res, err
}
func (c *ObsClient) GetProjectMeta(project string) (*ProjectMeta, error) {
res, err := c.ObsRequest("GET", c.baseUrl.JoinPath("source", project, "_meta").String(), nil)
req := []string{"source", project, "_meta"}
res, err := c.ObsRequest("GET", req, nil)
if err != nil {
return nil, err
@@ -323,7 +450,7 @@ func (c *ObsClient) GetProjectMeta(project string) (*ProjectMeta, error) {
case 404:
return nil, nil
default:
return nil, fmt.Errorf("Unexpected return code: %d", res.StatusCode)
return nil, fmt.Errorf("Unexpected return code: %d %s %w", res.StatusCode, req, err)
}
data, err := io.ReadAll(res.Body)
@@ -331,11 +458,12 @@ func (c *ObsClient) GetProjectMeta(project string) (*ProjectMeta, error) {
return nil, err
}
defer res.Body.Close()
return parseProjectMeta(data)
}
func (c *ObsClient) GetPackageMeta(project, pkg string) (*PackageMeta, error) {
res, err := c.ObsRequest("GET", c.baseUrl.JoinPath("source", project, pkg, "_meta").String(), nil)
res, err := c.ObsRequest("GET", []string{"source", project, pkg, "_meta"}, nil)
if err != nil {
return nil, err
@@ -354,6 +482,7 @@ func (c *ObsClient) GetPackageMeta(project, pkg string) (*PackageMeta, error) {
if err != nil {
return nil, err
}
defer res.Body.Close()
var meta PackageMeta
err = xml.Unmarshal(data, &meta)
@@ -408,10 +537,11 @@ func (c *ObsClient) SetProjectMeta(meta *ProjectMeta) error {
return err
}
res, err := c.ObsRequest("PUT", c.baseUrl.JoinPath("source", meta.Name, "_meta").String(), io.NopCloser(bytes.NewReader(xml)))
res, err := c.ObsRequest("PUT", []string{"source", meta.Name, "_meta"}, io.NopCloser(bytes.NewReader(xml)))
if err != nil {
return err
}
defer res.Body.Close()
switch res.StatusCode {
case 200:
@@ -424,35 +554,74 @@ func (c *ObsClient) SetProjectMeta(meta *ProjectMeta) error {
}
func (c *ObsClient) DeleteProject(project string) error {
res, err := c.ObsRequest("DELETE", c.baseUrl.JoinPath("source", project).String(), nil)
url := c.baseUrl.JoinPath("source", project)
query := url.Query()
query.Add("force", "1")
url.RawQuery = query.Encode()
res, err := c.ObsRequestRaw("DELETE", url.String(), nil)
if err != nil {
return err
}
defer res.Body.Close()
if res.StatusCode != 200 {
return fmt.Errorf("Unexpected return code: %d", res.StatusCode)
}
return nil
}
func (c *ObsClient) BuildLog(prj, pkg, repo, arch string) (io.ReadCloser, error) {
url := c.baseUrl.JoinPath("build", prj, repo, arch, pkg, "_log")
query := url.Query()
query.Add("nostream", "1")
query.Add("start", "0")
url.RawQuery = query.Encode()
res, err := c.ObsRequestRaw("GET", url.String(), nil)
if err != nil {
return nil, err
}
return res.Body, nil
}
type PackageBuildStatus struct {
Package string `xml:"package,attr"`
Code string `xml:"code,attr"`
Details string `xml:"details"`
LastUpdate time.Time
}
func PackageBuildStatusComp(A, B *PackageBuildStatus) int {
return strings.Compare(A.Package, B.Package)
}
type BuildResult struct {
Project string `xml:"project,attr"`
Repository string `xml:"repository,attr"`
Arch string `xml:"arch,attr"`
Code string `xml:"code,attr"`
Dirty bool `xml:"dirty,attr"`
ScmSync string `xml:"scmsync"`
ScmInfo string `xml:"scminfo"`
Status []PackageBuildStatus `xml:"status"`
Binaries []BinaryList `xml:"binarylist"`
XMLName xml.Name `xml:"result" json:"xml,omitempty"`
Project string `xml:"project,attr"`
Repository string `xml:"repository,attr"`
Arch string `xml:"arch,attr"`
Code string `xml:"code,attr"`
Dirty bool `xml:"dirty,attr,omitempty"`
ScmSync string `xml:"scmsync,omitempty"`
ScmInfo string `xml:"scminfo,omitempty"`
Status []*PackageBuildStatus `xml:"status"`
Binaries []BinaryList `xml:"binarylist,omitempty"`
LastUpdate time.Time
}
func BuildResultComp(A, B *BuildResult) int {
if cmp := strings.Compare(A.Project, B.Project); cmp != 0 {
return cmp
}
if cmp := strings.Compare(A.Repository, B.Repository); cmp != 0 {
return cmp
}
return strings.Compare(A.Arch, B.Arch)
}
type Binary struct {
@@ -467,9 +636,11 @@ type BinaryList struct {
}
type BuildResultList struct {
XMLName xml.Name `xml:"resultlist"`
State string `xml:"state,attr"`
Result []BuildResult `xml:"result"`
XMLName xml.Name `xml:"resultlist"`
State string `xml:"state,attr"`
Result []*BuildResult `xml:"result"`
isLastBuild bool
}
func (r *BuildResultList) GetPackageList() []string {
@@ -494,7 +665,7 @@ func (r *BuildResultList) GetPackageList() []string {
func (r *BuildResultList) BuildResultSummary() (success, finished bool) {
if r == nil {
return true, true
return false, false
}
finished = len(r.Result) > 0 && len(r.Result[0].Status) > 0
@@ -507,7 +678,7 @@ func (r *BuildResultList) BuildResultSummary() (success, finished bool) {
panic("Unknown repo result code: " + resultSet.Code)
}
finished = repoDetail.Finished
finished = r.isLastBuild || repoDetail.Finished
if !finished || resultSet.Dirty {
return
}
@@ -518,6 +689,11 @@ func (r *BuildResultList) BuildResultSummary() (success, finished bool) {
if !ok {
panic("Unknown result code: " + result.Code)
}
if r.isLastBuild && result.Code == "unknown" {
// it means the package has never build yet,
// but we don't know the reason
detail.Finished = true
}
finished = finished && detail.Finished
success = success && detail.Success
@@ -613,7 +789,7 @@ var ObsBuildStatusDetails map[string]ObsBuildStatusDetail = map[string]ObsBuildS
},
"unknown": ObsBuildStatusDetail{
Code: "unknown",
Description: "The scheduler has not yet evaluated this package. Should be a short intermediate state for new packages.",
Description: "The scheduler has not yet evaluated this package. Should be a short intermediate state for new packages. When used for lastbuild state it means it was never possible to attempt a build",
Finished: false,
},
@@ -690,14 +866,13 @@ func (obs ObsProjectNotFound) Error() string {
}
func (c *ObsClient) ProjectConfig(project string) (string, error) {
u := c.baseUrl.JoinPath("source", project, "_config")
res, err := c.ObsRequest("GET", u.String(), nil)
res, err := c.ObsRequest("GET", []string{"source", project, "_config"}, nil)
if err != nil {
return "", err
}
if data, err := io.ReadAll(res.Body); err == nil {
defer res.Body.Close()
return string(data), nil
} else {
return "", err
@@ -732,7 +907,7 @@ func (c *ObsClient) BuildStatusWithState(project string, opts *BuildResultOption
}
}
u.RawQuery = query.Encode()
res, err := c.ObsRequest("GET", u.String(), nil)
res, err := c.ObsRequestRaw("GET", u.String(), nil)
if err != nil {
return nil, err
}
@@ -750,5 +925,10 @@ func (c *ObsClient) BuildStatusWithState(project string, opts *BuildResultOption
if err != nil {
return nil, err
}
return parseBuildResults(data)
defer res.Body.Close()
ret, err := parseBuildResults(data)
if ret != nil {
ret.isLastBuild = opts.LastBuild
}
return ret, err
}

View File

@@ -55,6 +55,52 @@ func TestParsingOfBuildResults(t *testing.T) {
}
}
func TestParsingRequestResults(t *testing.T) {
res, err := parseRequestXml([]byte(metaRequestData))
if err != nil {
t.Fatal(err)
}
if res.Id != 42 ||
res.Action.Source.Project != "home:foo-user" ||
res.Action.Source.Package != "obs-server" ||
*res.Action.Source.Revision != "521e" ||
res.Action.Target.Project != "OBS:Unstable" ||
res.Action.Target.Revision != nil {
t.Fatal(res)
}
}
const metaRequestData = `<?xml version="1.0" encoding="UTF-8"?>
<request id="42" creator="foo-user">
<action type="submit">
<source project="home:foo-user" package="obs-server" rev="521e">
</source>
<target project="OBS:Unstable" package="obs-server">
</target>
<options>
<sourceupdate>cleanup</sourceupdate>
</options>
</action>
<state name="accepted" who="bar-user" when="2021-01-15T13:39:43">
<comment>allright</comment>
</state>
<review state="accepted" when="2021-01-15T15:49:32" who="obs-maintainer" by_user="obs-maintainer">
</review>
<review state="accepted" when="2021-01-15T15:49:32" who="obs-maintainer" by_group="obs-group">
</review>
<review state="accepted" when="2021-01-15T15:49:32" who="obs-maintainer" by_project="OBS:Unstable">
</review>
<review state="accepted" when="2021-01-15T15:49:32" who="obs-maintainer" by_package="obs-server">
</review>
<history who="foo" when="2021-01-15T13:39:43">
<description>Request created</description>
<comment>Please review sources</comment>
</history>
<description>A little version update</description>
</request>`
const metaPrjData = `
<project name="home:adamm">
<title>Adam's Home Projects</title>

View File

@@ -6,32 +6,82 @@ import (
"fmt"
"os"
"path"
"regexp"
"slices"
"strconv"
"strings"
"src.opensuse.org/autogits/common/gitea-generated/client/repository"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
type PRInfo struct {
PR *models.PullRequest
Reviews *PRReviews
PR *models.PullRequest
Reviews *PRReviews
RemoteName string
}
type PRSet struct {
PRs []PRInfo
PRs []*PRInfo
Config *AutogitConfig
BotUser string
HasAutoStaging bool
}
func readPRData(gitea GiteaPRFetcher, pr *models.PullRequest, currentSet []PRInfo, config *AutogitConfig) ([]PRInfo, error) {
func (prinfo *PRInfo) PRComponents() (org string, repo string, idx int64) {
org = prinfo.PR.Base.Repo.Owner.UserName
repo = prinfo.PR.Base.Repo.Name
idx = prinfo.PR.Index
return
}
func (prinfo *PRInfo) RemoveReviewers(gitea GiteaUnreviewTimelineFetcher, Reviewers []string, BotUser string) {
org, repo, idx := prinfo.PRComponents()
tl, err := gitea.GetTimeline(org, repo, idx)
if err != nil {
LogError("Failed to fetch timeline for", PRtoString(prinfo.PR), err)
}
// find review request for each reviewer
ReviewersToUnrequest := Reviewers
ReviewersAlreadyChecked := []string{}
for _, tlc := range tl {
if tlc.Type == TimelineCommentType_ReviewRequested && tlc.Assignee != nil {
user := tlc.Assignee.UserName
if idx := slices.Index(ReviewersToUnrequest, user); idx >= 0 && !slices.Contains(ReviewersAlreadyChecked, user) {
if tlc.User != nil && tlc.User.UserName == BotUser {
ReviewersAlreadyChecked = append(ReviewersAlreadyChecked, user)
continue
}
ReviewersToUnrequest = slices.Delete(ReviewersToUnrequest, idx, idx+1)
if len(Reviewers) == 0 {
break
}
}
}
}
LogDebug("Unrequesting reviewes for", PRtoString(prinfo.PR), ReviewersToUnrequest)
err = gitea.UnrequestReview(org, repo, idx, ReviewersToUnrequest...)
if err != nil {
LogError("Failed to unrequest reviewers for", PRtoString(prinfo.PR), err)
}
}
func readPRData(gitea GiteaPRFetcher, pr *models.PullRequest, currentSet []*PRInfo, config *AutogitConfig) ([]*PRInfo, error) {
for _, p := range currentSet {
if pr.Index == p.PR.Index && pr.Base.Repo.Name == p.PR.Base.Repo.Name && pr.Base.Repo.Owner.UserName == p.PR.Base.Repo.Owner.UserName {
return nil, nil
}
}
retSet := []PRInfo{PRInfo{PR: pr}}
retSet := []*PRInfo{&PRInfo{PR: pr}}
// only need to extact there on PrjGit PR
if pr.Base.Repo.Name == config.GitProjectName && pr.Base.Repo.Owner.UserName == config.Organization {
org, repo, _ := config.GetPrjGit()
if pr.Base.Repo.Name == repo && pr.Base.Repo.Owner.UserName == org {
_, refPRs := ExtractDescriptionAndPRs(bufio.NewScanner(strings.NewReader(pr.Body)))
for _, prdata := range refPRs {
pr, err := gitea.GetPullRequest(prdata.Org, prdata.Repo, prdata.Num)
@@ -49,13 +99,78 @@ func readPRData(gitea GiteaPRFetcher, pr *models.PullRequest, currentSet []PRInf
return retSet, nil
}
func FetchPRSet(gitea GiteaPRFetcher, org, repo string, num int64, config *AutogitConfig) (*PRSet, error) {
var Timeline_RefIssueNotFound error = errors.New("RefIssue not found on the timeline")
func LastPrjGitRefOnTimeline(botUser string, gitea GiteaPRTimelineReviewFetcher, org, repo string, num int64, config *AutogitConfig) (*models.PullRequest, error) {
timeline, err := gitea.GetTimeline(org, repo, num)
if err != nil {
LogError("Failed to fetch timeline for", org, repo, "#", num, err)
return nil, err
}
prjGitOrg, prjGitRepo, prjGitBranch := config.GetPrjGit()
for idx := len(timeline) - 1; idx >= 0; idx-- {
item := timeline[idx]
issue := item.RefIssue
if item.Type == TimelineCommentType_PullRequestRef &&
issue != nil &&
issue.Repository != nil &&
issue.Repository.Owner == prjGitOrg &&
issue.Repository.Name == prjGitRepo {
if !config.NoProjectGitPR {
if issue.User.UserName != botUser {
continue
}
}
pr, err := gitea.GetPullRequest(prjGitOrg, prjGitRepo, issue.Index)
if err != nil {
switch err.(type) {
case *repository.RepoGetPullRequestNotFound: // deleted?
continue
default:
LogDebug("PrjGit RefIssue fetch error from timeline", issue.Index, err)
continue
}
}
LogDebug("found ref PR on timeline:", PRtoString(pr))
if pr.Base.Name != prjGitBranch {
LogDebug(" -> not matching:", pr.Base.Name, prjGitBranch)
continue
}
_, prs := ExtractDescriptionAndPRs(bufio.NewScanner(strings.NewReader(item.RefIssue.Body)))
for _, pr := range prs {
if pr.Org == org && pr.Repo == repo && pr.Num == num {
LogDebug("Found PrjGit PR in Timeline:", issue.Index)
// found prjgit PR in timeline. Return it
return gitea.GetPullRequest(prjGitOrg, prjGitRepo, issue.Index)
}
}
}
}
LogDebug("PrjGit RefIssue not found on timeline in", org, repo, num)
return nil, Timeline_RefIssueNotFound
}
func FetchPRSet(user string, gitea GiteaPRTimelineReviewFetcher, org, repo string, num int64, config *AutogitConfig) (*PRSet, error) {
var pr *models.PullRequest
var err error
gitea.ResetTimelineCache(org, repo, num)
prjGitOrg, prjGitRepo, _ := config.GetPrjGit()
if prjGitOrg != org || prjGitRepo != config.GitProjectName {
if pr, err = gitea.GetAssociatedPrjGitPR(prjGitOrg, prjGitRepo, org, repo, num); err != nil {
if prjGitOrg == org && prjGitRepo == repo {
if pr, err = gitea.GetPullRequest(org, repo, num); err != nil {
return nil, err
}
} else {
if pr, err = LastPrjGitRefOnTimeline(user, gitea, org, repo, num, config); err != nil && err != Timeline_RefIssueNotFound {
return nil, err
}
@@ -64,10 +179,6 @@ func FetchPRSet(gitea GiteaPRFetcher, org, repo string, num int64, config *Autog
return nil, err
}
}
} else {
if pr, err = gitea.GetPullRequest(org, repo, num); err != nil {
return nil, err
}
}
prs, err := readPRData(gitea, pr, nil, config)
@@ -75,22 +186,70 @@ func FetchPRSet(gitea GiteaPRFetcher, org, repo string, num int64, config *Autog
return nil, err
}
return &PRSet{PRs: prs, Config: config}, nil
for _, pr := range prs {
org, repo, idx := pr.PRComponents()
gitea.ResetTimelineCache(org, repo, idx)
reviews, err := FetchGiteaReviews(gitea, org, repo, idx)
if err != nil {
LogError("Error fetching reviews for", PRtoString(pr.PR), ":", err)
}
pr.Reviews = reviews
}
return &PRSet{
PRs: prs,
Config: config,
BotUser: user,
}, nil
}
func (prset *PRSet) RemoveReviewers(gitea GiteaUnreviewTimelineFetcher, reviewers []string) {
for _, prinfo := range prset.PRs {
prinfo.RemoveReviewers(gitea, reviewers, prset.BotUser)
}
}
func (rs *PRSet) Find(pr *models.PullRequest) (*PRInfo, bool) {
for _, p := range rs.PRs {
if p.PR.Base.RepoID == pr.Base.RepoID &&
p.PR.Head.Sha == pr.Head.Sha &&
p.PR.Base.Name == pr.Base.Name {
return p, true
}
}
return nil, false
}
func (rs *PRSet) AddPR(pr *models.PullRequest) *PRInfo {
if pr, found := rs.Find(pr); found {
return pr
}
prinfo := &PRInfo{
PR: pr,
}
rs.PRs = append(rs.PRs, prinfo)
return prinfo
}
func (rs *PRSet) IsPrjGitPR(pr *models.PullRequest) bool {
return pr.Base.Repo.Name == rs.Config.GitProjectName && pr.Base.Repo.Owner.UserName == rs.Config.Organization
org, repo, branch := rs.Config.GetPrjGit()
return pr.Base.Name == branch && pr.Base.Repo.Name == repo && pr.Base.Repo.Owner.UserName == org
}
func (rs *PRSet) GetPrjGitPR() (*models.PullRequest, error) {
var ret *models.PullRequest
var PRSet_PrjGitMissing error = errors.New("No PrjGit PR found")
var PRSet_MultiplePrjGit error = errors.New("Multiple PrjGit PRs in one review set")
func (rs *PRSet) GetPrjGitPR() (*PRInfo, error) {
var ret *PRInfo
for _, prinfo := range rs.PRs {
if rs.IsPrjGitPR(prinfo.PR) {
if ret == nil {
ret = prinfo.PR
ret = prinfo
} else {
return nil, errors.New("Multiple PrjGit PRs in one review set")
return nil, PRSet_MultiplePrjGit
}
}
}
@@ -99,137 +258,328 @@ func (rs *PRSet) GetPrjGitPR() (*models.PullRequest, error) {
return ret, nil
}
return nil, errors.New("No PrjGit PR found")
return nil, PRSet_PrjGitMissing
}
func (rs *PRSet) NeedRecreatingPrjGit(currentBranchHash string) bool {
pr, err := rs.GetPrjGitPR()
if err != nil {
return true
}
return pr.PR.Base.Sha == currentBranchHash
}
func (rs *PRSet) IsConsistent() bool {
prjpr, err := rs.GetPrjGitPR()
prjpr_info, err := rs.GetPrjGitPR()
if err != nil {
return false
}
prjpr := prjpr_info.PR
_, prjpr_set := ExtractDescriptionAndPRs(bufio.NewScanner(strings.NewReader(prjpr.Body)))
if len(prjpr_set) != len(rs.PRs)-1 { // 1 to many mapping
LogDebug("Number of PR from links:", len(prjpr_set), "is not what's expected", len(rs.PRs)-1)
return false
}
next_rs:
for _, prinfo := range rs.PRs {
if prinfo.PR.State != "open" {
return false
}
if prjpr == prinfo.PR {
continue
}
for _, pr := range prjpr_set {
if prinfo.PR.Base.Repo.Owner.UserName == pr.Org && prinfo.PR.Base.Repo.Name == pr.Repo && prinfo.PR.Index == pr.Num {
if strings.EqualFold(prinfo.PR.Base.Repo.Owner.UserName, pr.Org) && strings.EqualFold(prinfo.PR.Base.Repo.Name, pr.Repo) && prinfo.PR.Index == pr.Num {
continue next_rs
}
}
LogDebug(" PR: ", PRtoString(prinfo.PR), "not found in project git PRSet")
return false
}
return true
}
func (rs *PRSet) AssignReviewers(gitea GiteaReviewFetcherAndRequester, maintainers MaintainershipData) error {
func (rs *PRSet) FindMissingAndExtraReviewers(maintainers MaintainershipData, idx int) (missing, extra []string) {
configReviewers := ParseReviewers(rs.Config.Reviewers)
for _, pr := range rs.PRs {
reviewers := []string{}
if rs.IsPrjGitPR(pr.PR) {
reviewers = configReviewers.Prj
if len(rs.PRs) == 1 {
reviewers = slices.Concat(reviewers, maintainers.ListProjectMaintainers())
}
// remove reviewers that were already requested and are not stale
prjMaintainers := maintainers.ListProjectMaintainers(nil)
LogDebug("project maintainers:", prjMaintainers)
pr := rs.PRs[idx]
if rs.IsPrjGitPR(pr.PR) {
missing = slices.Concat(configReviewers.Prj, configReviewers.PrjOptional)
if rs.HasAutoStaging {
missing = append(missing, Bot_BuildReview)
}
LogDebug("PrjGit submitter:", pr.PR.User.UserName)
// only need project maintainer reviews if:
// * not created by a bot and has other PRs, or
// * not created by maintainer
noReviewPRCreators := []string{}
if !rs.Config.ReviewRequired {
noReviewPRCreators = prjMaintainers
}
if len(rs.PRs) > 1 {
noReviewPRCreators = append(noReviewPRCreators, rs.BotUser)
}
if slices.Contains(noReviewPRCreators, pr.PR.User.UserName) || pr.Reviews.IsReviewedByOneOf(prjMaintainers...) {
LogDebug("Project already reviewed by a project maintainer, remove rest")
// do not remove reviewers if they are also maintainers
prjMaintainers = slices.DeleteFunc(prjMaintainers, func(m string) bool { return slices.Contains(missing, m) })
extra = slices.Concat(prjMaintainers, []string{rs.BotUser})
} else {
pkg := pr.PR.Base.Repo.Name
reviewers = slices.Concat(configReviewers.Pkg, maintainers.ListProjectMaintainers(), maintainers.ListPackageMaintainers(pkg))
}
// submitters do not need to review their own work
if idx := slices.Index(reviewers, pr.PR.User.UserName); idx != -1 {
reviewers = slices.Delete(reviewers, idx, idx+1)
}
// remove reviewers that were already requested and are not stale
reviews, err := FetchGiteaReviews(gitea, reviewers, pr.PR.Base.Repo.Owner.UserName, pr.PR.Base.Repo.Name, pr.PR.Index)
if err != nil {
return err
}
for idx := 0; idx < len(reviewers); {
user := reviewers[idx]
if reviews.HasPendingReviewBy(user) || reviews.IsReviewedBy(user) {
reviewers = slices.Delete(reviewers, idx, idx+1)
// if bot not created PrjGit or prj maintainer, we need to add project reviewers here
if slices.Contains(noReviewPRCreators, pr.PR.User.UserName) {
LogDebug("No need for project maintainers")
extra = slices.Concat(prjMaintainers, []string{rs.BotUser})
} else {
idx++
LogDebug("Adding prjMaintainers to PrjGit")
missing = append(missing, prjMaintainers...)
}
}
} else {
pkg := pr.PR.Base.Repo.Name
pkgMaintainers := maintainers.ListPackageMaintainers(pkg, nil)
Maintainers := slices.Concat(prjMaintainers, pkgMaintainers)
noReviewPkgPRCreators := []string{}
if !rs.Config.ReviewRequired {
noReviewPkgPRCreators = pkgMaintainers
}
// get maintainers associated with the PR too
if len(reviewers) > 0 {
if _, err := gitea.RequestReviews(pr.PR, reviewers...); err != nil {
return fmt.Errorf("Cannot create reviews on %s/%s#%d for [%s]: %w", pr.PR.Base.Repo.Owner.UserName, pr.PR.Base.Repo.Name, pr.PR.Index, strings.Join(reviewers, ", "), err)
LogDebug("packakge maintainers:", Maintainers)
missing = slices.Concat(configReviewers.Pkg, configReviewers.PkgOptional)
if slices.Contains(noReviewPkgPRCreators, pr.PR.User.UserName) || pr.Reviews.IsReviewedByOneOf(Maintainers...) {
// submitter is maintainer or already reviewed
LogDebug("Package reviewed by maintainer (or subitter is maintainer), remove the rest of them")
// do not remove reviewers if they are also maintainers
Maintainers = slices.DeleteFunc(Maintainers, func(m string) bool { return slices.Contains(missing, m) })
extra = slices.Concat(Maintainers, []string{rs.BotUser})
} else {
// maintainer review is missing
LogDebug("Adding package maintainers to package git")
missing = append(missing, pkgMaintainers...)
}
}
slices.Sort(missing)
missing = slices.Compact(missing)
slices.Sort(extra)
extra = slices.Compact(extra)
// submitters cannot review their own work
if idx := slices.Index(missing, pr.PR.User.UserName); idx != -1 {
missing = slices.Delete(missing, idx, idx+1)
}
LogDebug("PR: ", PRtoString(pr.PR))
LogDebug(" preliminary add reviewers for PR:", missing)
LogDebug(" preliminary rm reviewers for PR:", extra)
// remove missing reviewers that are already done or already pending
for idx := 0; idx < len(missing); {
user := missing[idx]
if pr.Reviews.HasPendingReviewBy(user) || pr.Reviews.IsReviewedBy(user) {
missing = slices.Delete(missing, idx, idx+1)
LogDebug(" removing done/pending reviewer:", user)
} else {
idx++
}
}
// remove extra reviews that are actually only pending, and only pending by us
for idx := 0; idx < len(extra); {
user := extra[idx]
rr := pr.Reviews.FindReviewRequester(user)
if rr != nil && rr.User.UserName == rs.BotUser && pr.Reviews.HasPendingReviewBy(user) {
// good to remove this review
idx++
} else {
// this review should not be considered as extra by us
LogDebug(" - cannot find? to remove", user)
if rr != nil {
LogDebug(" ", rr.User.UserName, "vs.", rs.BotUser, pr.Reviews.HasPendingReviewBy(user))
}
extra = slices.Delete(extra, idx, idx+1)
}
}
LogDebug(" add reviewers for PR:", missing)
LogDebug(" rm reviewers for PR:", extra)
return missing, extra
}
func (rs *PRSet) AssignReviewers(gitea GiteaReviewFetcherAndRequesterAndUnrequester, maintainers MaintainershipData) error {
for idx, pr := range rs.PRs {
missingReviewers, extraReviewers := rs.FindMissingAndExtraReviewers(maintainers, idx)
if len(missingReviewers) > 0 {
LogDebug(" Requesting reviews from:", missingReviewers)
if !IsDryRun {
for _, r := range missingReviewers {
if _, err := gitea.RequestReviews(pr.PR, r); err != nil {
LogError("Cannot create reviews on", PRtoString(pr.PR), "for user:", r, err)
}
}
}
}
if len(extraReviewers) > 0 {
LogDebug(" UnRequesting reviews from:", extraReviewers)
if !IsDryRun {
for _, r := range extraReviewers {
org, repo, idx := pr.PRComponents()
if err := gitea.UnrequestReview(org, repo, idx, r); err != nil {
LogError("Cannot unrequest reviews on", PRtoString(pr.PR), "for user:", r, err)
}
}
}
}
}
return nil
}
func (rs *PRSet) RemoveClosedPRs() {
rs.PRs = slices.DeleteFunc(rs.PRs, func(pr *PRInfo) bool {
return pr.PR.State != "open"
})
}
func (rs *PRSet) IsApproved(gitea GiteaPRChecker, maintainers MaintainershipData) bool {
configReviewers := ParseReviewers(rs.Config.Reviewers)
is_manually_reviewed_ok := false
if need_manual_review := rs.Config.ManualMergeOnly || rs.Config.ManualMergeProject; need_manual_review {
// Groups are expanded here because any group member can issue "merge ok" to the BotUser
groups := rs.Config.ReviewGroups
prjgit, err := rs.GetPrjGitPR()
if err == nil && prjgit != nil {
reviewers := slices.Concat(configReviewers.Prj, maintainers.ListProjectMaintainers(groups))
LogDebug("Fetching reviews for", prjgit.PR.Base.Repo.Owner.UserName, prjgit.PR.Base.Repo.Name, prjgit.PR.Index)
r, err := FetchGiteaReviews(gitea, prjgit.PR.Base.Repo.Owner.UserName, prjgit.PR.Base.Repo.Name, prjgit.PR.Index)
if err != nil {
LogError("Cannot fetch gita reaviews for PR:", err)
return false
}
r.RequestedReviewers = reviewers
prjgit.Reviews = r
if prjgit.Reviews.IsManualMergeOK() {
is_manually_reviewed_ok = true
}
}
if !is_manually_reviewed_ok && !rs.Config.ManualMergeProject {
for _, pr := range rs.PRs {
if rs.IsPrjGitPR(pr.PR) {
continue
}
pkg := pr.PR.Base.Repo.Name
reviewers := slices.Concat(configReviewers.Pkg, maintainers.ListPackageMaintainers(pkg, groups))
LogDebug("Fetching reviews for", pr.PR.Base.Repo.Owner.UserName, pr.PR.Base.Repo.Name, pr.PR.Index)
r, err := FetchGiteaReviews(gitea, pr.PR.Base.Repo.Owner.UserName, pr.PR.Base.Repo.Name, pr.PR.Index)
if err != nil {
LogError("Cannot fetch gita reaviews for PR:", err)
return false
}
r.RequestedReviewers = reviewers
pr.Reviews = r
if !pr.Reviews.IsManualMergeOK() {
LogInfo("Not approved manual merge. PR:", pr.PR.URL)
return false
}
}
is_manually_reviewed_ok = true
}
if !is_manually_reviewed_ok {
LogInfo("manual merge not ok")
return false
}
}
is_reviewed := false
for _, pr := range rs.PRs {
var reviewers []string
var pkg string
if rs.IsPrjGitPR(pr.PR) {
reviewers = configReviewers.Prj
if rs.HasAutoStaging {
reviewers = append(reviewers, Bot_BuildReview)
}
pkg = ""
} else {
reviewers = configReviewers.Pkg
pkg = pr.PR.Base.Repo.Name
}
r, err := FetchGiteaReviews(gitea, reviewers, pr.PR.Base.Repo.Owner.UserName, pr.PR.Base.Repo.Name, pr.PR.Index)
if err != nil {
return false
}
is_reviewed = r.IsApproved()
if !is_reviewed {
if strings.HasPrefix(pr.PR.Title, "WIP:") {
LogInfo("WIP PR. Ignoring")
return false
}
if is_reviewed = maintainers.IsApproved(pkg, r.reviews); !is_reviewed {
r, err := FetchGiteaReviews(gitea, pr.PR.Base.Repo.Owner.UserName, pr.PR.Base.Repo.Name, pr.PR.Index)
if err != nil {
LogError("Cannot fetch gitea reaviews for PR:", err)
return false
}
r.RequestedReviewers = reviewers
is_manually_reviewed_ok = r.IsApproved()
LogDebug("PR to", pr.PR.Base.Repo.Name, "reviewed?", is_manually_reviewed_ok)
if !is_manually_reviewed_ok {
if GetLoggingLevel() > LogLevelInfo {
LogDebug("missing reviewers:", r.MissingReviews())
}
return false
}
if need_maintainer_review := !rs.IsPrjGitPR(pr.PR) || pr.PR.User.UserName != rs.BotUser; need_maintainer_review {
// Do not expand groups here, as the group-review-bot will ACK if group has reviewed.
if is_manually_reviewed_ok = maintainers.IsApproved(pkg, r.Reviews, pr.PR.User.UserName, nil); !is_manually_reviewed_ok {
LogDebug(" not approved?", pkg)
return false
}
} else {
LogDebug("PrjGit PR -- bot created, no need for review")
}
}
return is_reviewed
return is_manually_reviewed_ok
}
func (rs *PRSet) Merge(gh GitHandlerGenerator) error {
prjgit, err := rs.GetPrjGitPR()
func (rs *PRSet) Merge(gitea GiteaReviewUnrequester, git Git) error {
prjgit_info, err := rs.GetPrjGitPR()
if err != nil {
return err
}
prjgit := prjgit_info.PR
git, err := gh.CreateGitHandler(rs.Config.Organization)
defer git.Close()
if err != nil {
return err
}
git.GitExecOrPanic("", "clone", "--depth", "1", prjgit.Base.Repo.SSHURL, DefaultGitPrj)
git.GitExecOrPanic(DefaultGitPrj, "fetch", "origin", prjgit.Base.Sha, prjgit.Head.Sha)
_, _, prjgitBranch := rs.Config.GetPrjGit()
remote, err := git.GitClone(DefaultGitPrj, prjgitBranch, prjgit.Base.Repo.SSHURL)
PanicOnError(err)
git.GitExecOrPanic(DefaultGitPrj, "fetch", remote, prjgit.Head.Sha)
// if other changes merged, check if we have conflicts
rev := strings.TrimSpace(git.GitExecWithOutputOrPanic(DefaultGitPrj, "merge-base", "HEAD", prjgit.Base.Sha, prjgit.Head.Sha))
if rev != prjgit.Base.Sha {
return fmt.Errorf("Base.Sha (%s) not yet merged into project-git. Aborting merge.", prjgit.Base.Sha)
}
/*
rev := strings.TrimSpace(git.GitExecWithOutputOrPanic(DefaultGitPrj, "merge-base", "HEAD", prjgit.Base.Sha, prjgit.Head.Sha))
if rev != prjgit.Base.Sha {
return fmt.Errorf("Base.Sha (%s) not yet merged into project-git. Aborting merge.", prjgit.Base.Sha)
}
*/
/*
rev := git.GitExecWithOutputOrPanic(common.DefaultGitPrj, "rev-list", "-1", "HEAD")
if rev != prjgit.Base.Sha {
panic("FIXME")
}
*/
msg := "merging"
msg := fmt.Sprintf("Merging\n\nPR: %s/%s!%d", prjgit.Base.Repo.Owner.UserName, prjgit.Base.Repo.Name, prjgit.Index)
err = git.GitExec(DefaultGitPrj, "merge", "--no-ff", "-m", msg, prjgit.Head.Sha)
if err != nil {
@@ -241,6 +591,7 @@ func (rs *PRSet) Merge(gh GitHandlerGenerator) error {
// we can only resolve conflicts with .gitmodules
for _, s := range status {
if s.Status == GitStatus_Unmerged {
panic("Can't handle conflicts yet")
if s.Path != ".gitmodules" {
return err
}
@@ -303,31 +654,121 @@ func (rs *PRSet) Merge(gh GitHandlerGenerator) error {
return fmt.Errorf("Can't close .gitmodules: %w", err)
}
os.CopyFS("/tmp/test", os.DirFS(git.GetPath()))
git.GitExecOrPanic(DefaultGitPrj, "add", ".gitmodules")
git.GitExecOrPanic(DefaultGitPrj, "-c", "core.editor=true", "merge", "--continue")
}
}
}
// FF all non-prj git
// FF all non-prj git and unrequest reviews.
newRepoIssues := make(map[int64]string) // issue index -> org/repo
for _, prinfo := range rs.PRs {
// remove pending review requests
repo := prinfo.PR.Base.Repo
head := prinfo.PR.Head
id := prinfo.PR.Index
reviewers := make([]string, len(prinfo.PR.RequestedReviewers))
for idx := range prinfo.PR.RequestedReviewers {
r := prinfo.PR.RequestedReviewers[idx]
if r != nil {
reviewers[idx] = r.UserName
}
}
if err := gitea.UnrequestReview(repo.Owner.UserName, repo.Name, id, reviewers...); err != nil {
LogError("Cannot unrequest reviews in PR:", repo.Owner.UserName, repo.Name, id, reviewers, ": ", err)
}
// PrjGit already merged above, so skip here.
if rs.IsPrjGitPR(prinfo.PR) {
continue
}
git.GitExecOrPanic("", "clone", prinfo.PR.Base.Repo.SSHURL, prinfo.PR.Base.Name)
git.GitExecOrPanic(prinfo.PR.Base.Name, "fetch", "origin", prinfo.PR.Head.Sha)
git.GitExecOrPanic(prinfo.PR.Base.Name, "merge", "--ff", prinfo.PR.Head.Sha)
isNewRepo := false
for _, l := range prinfo.PR.Labels {
if l.Name == Label_NewRepository {
isNewRepo = true
break
}
}
br := rs.Config.Branch
if len(br) == 0 {
// if branch is unspecified, take it from the PR as it
// matches default branch already
br = prinfo.PR.Base.Name
} else if br != prinfo.PR.Base.Name {
panic(prinfo.PR.Base.Name + " is expected to match " + br)
}
if isNewRepo {
// Extract issue reference from body: "See issue #XYZ"
rx := regexp.MustCompile(`See issue #(\d+)`)
if matches := rx.FindStringSubmatch(prinfo.PR.Body); len(matches) > 1 {
if issueIdx, err := strconv.ParseInt(matches[1], 10, 64); err == nil {
// We need to know which project git this issue belongs to.
// Since the PR set is linked to a ProjectGit, we can use its org/repo.
prjGitOrg, prjGitRepo, _ := rs.Config.GetPrjGit()
newRepoIssues[issueIdx] = prjGitOrg + "/" + prjGitRepo
}
}
}
prinfo.RemoteName, err = git.GitClone(repo.Name, br, repo.SSHURL)
PanicOnError(err)
git.GitExecOrPanic(repo.Name, "fetch", prinfo.RemoteName, head.Sha)
if isNewRepo {
LogInfo("Force-pushing new repository branch", br, "to", head.Sha)
// we don't merge, we just set the branch to this commit
} else {
git.GitExecOrPanic(repo.Name, "merge", "--ff", head.Sha)
}
}
// push changes
git.GitExecOrPanic(DefaultGitPrj, "push", "origin")
if !IsDryRun {
git.GitExecOrPanic(DefaultGitPrj, "push", remote)
} else {
LogInfo("*** WOULD push", DefaultGitPrj, "changes to", remote)
}
for _, prinfo := range rs.PRs {
if rs.IsPrjGitPR(prinfo.PR) {
continue
}
git.GitExecOrPanic(prinfo.PR.Base.Name, "push", "origin")
repo := prinfo.PR.Base.Repo
isNewRepo := false
for _, l := range prinfo.PR.Labels {
if l.Name == Label_NewRepository {
isNewRepo = true
break
}
}
if !IsDryRun {
if isNewRepo {
git.GitExecOrPanic(repo.Name, "push", "-f", prinfo.RemoteName, prinfo.PR.Head.Sha+":"+prinfo.PR.Base.Name)
} else {
git.GitExecOrPanic(repo.Name, "push", prinfo.RemoteName)
}
} else {
LogInfo("*** WOULD push", repo.Name, "to", prinfo.RemoteName)
}
}
// Close referencing issues
if !IsDryRun {
for issueIdx, prjPath := range newRepoIssues {
parts := strings.Split(prjPath, "/")
if len(parts) == 2 {
LogInfo("Closing issue", prjPath+"#"+strconv.FormatInt(issueIdx, 10))
gitea.UpdateIssue(parts[0], parts[1], issueIdx, &models.EditIssueOption{
State: "closed",
})
}
}
}
return nil

123
common/pr_linkage_test.go Normal file
View File

@@ -0,0 +1,123 @@
package common_test
import (
"testing"
"go.uber.org/mock/gomock"
"src.opensuse.org/autogits/common"
"src.opensuse.org/autogits/common/gitea-generated/models"
mock_common "src.opensuse.org/autogits/common/mock"
)
func TestFetchPRSet_Linkage(t *testing.T) {
config := &common.AutogitConfig{
Organization: "target-org",
GitProjectName: "test-org/prjgit#main",
}
// 1. Mock a package PR
pkgPR := &models.PullRequest{
Index: 101,
State: "open",
Base: &models.PRBranchInfo{
Ref: "main",
Repo: &models.Repository{
Name: "pkg1",
Owner: &models.User{UserName: "target-org"},
},
},
Head: &models.PRBranchInfo{Sha: "pkg-sha"},
}
// 2. Mock a ProjectGit PR that references the package PR
prjGitPR := &models.PullRequest{
Index: 500,
State: "open",
Base: &models.PRBranchInfo{
Ref: "main",
Name: "main",
Repo: &models.Repository{
Name: "prjgit",
Owner: &models.User{UserName: "test-org"},
},
},
Body: "Forwarded PRs: pkg1\n\nPR: target-org/pkg1!101",
}
t.Run("Fetch from ProjectGit PR", func(t *testing.T) {
ctl := NewController(t)
defer ctl.Finish()
mockGitea := mock_common.NewMockGiteaPRTimelineReviewFetcher(ctl)
mockGitea.EXPECT().ResetTimelineCache(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
// Expect fetch of prjGitPR
mockGitea.EXPECT().GetPullRequest("test-org", "prjgit", int64(500)).Return(prjGitPR, nil)
// Expect fetch of pkgPR because it's linked in body
mockGitea.EXPECT().GetPullRequest("target-org", "pkg1", int64(101)).Return(pkgPR, nil)
// Expect review fetching (part of FetchPRSet)
mockGitea.EXPECT().GetPullRequestReviews(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*models.PullReview{}, nil).AnyTimes()
mockGitea.EXPECT().GetTimeline(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*models.TimelineComment{}, nil).AnyTimes()
prset, err := common.FetchPRSet("bot", mockGitea, "test-org", "prjgit", 500, config)
if err != nil {
t.Fatalf("FetchPRSet failed: %v", err)
}
if len(prset.PRs) != 2 {
t.Errorf("Expected 2 PRs in set, got %d", len(prset.PRs))
}
if !prset.IsConsistent() {
t.Error("PR set should be consistent")
}
})
t.Run("Fetch from Package PR via Timeline", func(t *testing.T) {
ctl := NewController(t)
defer ctl.Finish()
mockGitea := mock_common.NewMockGiteaPRTimelineReviewFetcher(ctl)
mockGitea.EXPECT().ResetTimelineCache(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
// 1. FetchPRSet for pkgPR will call LastPrjGitRefOnTimeline
mockGitea.EXPECT().GetTimeline("target-org", "pkg1", int64(101)).Return([]*models.TimelineComment{
{
Type: common.TimelineCommentType_PullRequestRef,
RefIssue: &models.Issue{
Index: 500,
Body: "PR: target-org/pkg1!101",
Repository: &models.RepositoryMeta{
Owner: "test-org",
Name: "prjgit",
},
User: &models.User{UserName: "bot"},
},
},
}, nil)
// 2. It will then fetch the prjGitPR found in timeline (twice in LastPrjGitRefOnTimeline)
mockGitea.EXPECT().GetPullRequest("test-org", "prjgit", int64(500)).Return(prjGitPR, nil).Times(2)
// 3. Then it will recursively fetch linked PRs from prjGitPR body in readPRData
mockGitea.EXPECT().GetPullRequest("target-org", "pkg1", int64(101)).Return(pkgPR, nil)
// Review fetching for all PRs in the set
mockGitea.EXPECT().GetPullRequestReviews(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*models.PullReview{}, nil).AnyTimes()
mockGitea.EXPECT().GetTimeline("test-org", "prjgit", int64(500)).Return([]*models.TimelineComment{}, nil).AnyTimes()
mockGitea.EXPECT().GetTimeline("target-org", "pkg1", int64(101)).Return([]*models.TimelineComment{}, nil).AnyTimes()
prset, err := common.FetchPRSet("bot", mockGitea, "target-org", "pkg1", 101, config)
if err != nil {
t.Fatalf("FetchPRSet failed: %v", err)
}
if len(prset.PRs) != 2 {
t.Errorf("Expected 2 PRs in set, got %d", len(prset.PRs))
}
prjPRInfo, err := prset.GetPrjGitPR()
if err != nil || prjPRInfo.PR.Index != 500 {
t.Errorf("Expected ProjectGit PR 500 to be found, got %v", prjPRInfo)
}
})
}

View File

@@ -0,0 +1,94 @@
package common_test
import (
"testing"
"go.uber.org/mock/gomock"
"src.opensuse.org/autogits/common"
"src.opensuse.org/autogits/common/gitea-generated/models"
mock_common "src.opensuse.org/autogits/common/mock"
)
func TestPRSet_Merge_Special(t *testing.T) {
ctl := NewController(t)
defer ctl.Finish()
mockGitea := mock_common.NewMockGiteaReviewUnrequester(ctl)
mockGit := mock_common.NewMockGit(ctl)
config := &common.AutogitConfig{
Organization: "target-org",
GitProjectName: "test-org/prjgit#main",
Branch: "main",
}
// 1. Regular ProjectGit PR
prjGitPR := &models.PullRequest{
Index: 500,
Base: &models.PRBranchInfo{
Ref: "main",
Name: "main",
Repo: &models.Repository{Name: "prjgit", Owner: &models.User{UserName: "test-org"}, SSHURL: "prj-ssh-url"},
Sha: "base-sha",
},
Head: &models.PRBranchInfo{Sha: "prj-head-sha"},
}
// 2. "new/New Repository" Package PR
newPkgPR := &models.PullRequest{
Index: 101,
Base: &models.PRBranchInfo{
Ref: "main",
Name: "main",
Repo: &models.Repository{Name: "new-pkg", Owner: &models.User{UserName: "target-org"}, SSHURL: "pkg-ssh-url"},
},
Head: &models.PRBranchInfo{Sha: "pkg-head-sha"},
Labels: []*models.Label{
{Name: "new/New Repository"},
},
Body: "See issue #123",
}
prset := &common.PRSet{
Config: config,
PRs: []*common.PRInfo{
{PR: prjGitPR},
{PR: newPkgPR},
},
}
common.IsDryRun = false
// Mock expectations for Merge
// Clone and fetch for PrjGit
mockGit.EXPECT().GitClone("_ObsPrj", "main", "prj-ssh-url").Return("origin", nil)
mockGit.EXPECT().GitExecOrPanic("_ObsPrj", "fetch", "origin", "prj-head-sha")
// mockGit.EXPECT().GitExecWithOutputOrPanic("_ObsPrj", "merge-base", "HEAD", "base-sha", "prj-head-sha").Return("base-sha")
mockGit.EXPECT().GitExec("_ObsPrj", "merge", "--no-ff", "-m", gomock.Any(), "prj-head-sha").Return(nil)
// Unrequest reviews
mockGitea.EXPECT().UnrequestReview("test-org", "prjgit", int64(500), gomock.Any()).Return(nil)
mockGitea.EXPECT().UnrequestReview("target-org", "new-pkg", int64(101), gomock.Any()).Return(nil)
// Clone and fetch for new-pkg
mockGit.EXPECT().GitClone("new-pkg", "main", "pkg-ssh-url").Return("origin", nil)
mockGit.EXPECT().GitExecOrPanic("new-pkg", "fetch", "origin", "pkg-head-sha")
// Pushing changes
mockGit.EXPECT().GitExecOrPanic("_ObsPrj", "push", "origin")
// Special push for new repo: git push -f origin pkg-head-sha:main
mockGit.EXPECT().GitExecOrPanic("new-pkg", "push", "-f", "origin", "pkg-head-sha:main")
// Closing issue
mockGitea.EXPECT().UpdateIssue("test-org", "prjgit", int64(123), gomock.Any()).DoAndReturn(func(org, repo string, idx int64, opt *models.EditIssueOption) (*models.Issue, error) {
if opt.State != "closed" {
t.Errorf("Expected issue state to be closed, got %s", opt.State)
}
return nil, nil
})
err := prset.Merge(mockGitea, mockGit)
if err != nil {
t.Fatalf("Merge failed: %v", err)
}
}

File diff suppressed because it is too large Load Diff

238
common/rabbitmq.go Normal file
View File

@@ -0,0 +1,238 @@
package common
/*
* This file is part of Autogits.
*
* Copyright © 2024 SUSE LLC
*
* Autogits is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 2 of the License, or (at your option) any later
* version.
*
* Autogits is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Foobar. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"crypto/tls"
"fmt"
"net/url"
"strings"
"time"
rabbitmq "github.com/rabbitmq/amqp091-go"
)
type RabbitConnection struct {
RabbitURL *url.URL // amqps://user:password@host/queue
queueName string
ch *rabbitmq.Channel
topics []string
topicSubChanges chan string // +topic = subscribe, -topic = unsubscribe
}
type RabbitProcessor interface {
GenerateTopics() []string
Connection() *RabbitConnection
ProcessRabbitMessage(msg RabbitMessage) error
}
type RabbitMessage rabbitmq.Delivery
func (l *RabbitConnection) ProcessTopicChanges() {
for {
topic, ok := <-l.topicSubChanges
if !ok {
return
}
LogDebug(" topic change:", topic)
switch topic[0] {
case '+':
if err := l.ch.QueueBind(l.queueName, topic[1:], "pubsub", false, nil); err != nil {
LogError(err)
}
case '-':
if err := l.ch.QueueUnbind(l.queueName, topic[1:], "pubsub", nil); err != nil {
LogError(err)
}
default:
LogInfo("Ignoring unknown topic change:", topic)
}
}
}
func (l *RabbitConnection) ProcessRabbitMQ(msgCh chan<- RabbitMessage) error {
queueName := l.RabbitURL.Path
l.RabbitURL.Path = ""
if len(queueName) > 0 && queueName[0] == '/' {
queueName = queueName[1:]
}
connection, err := rabbitmq.DialTLS(l.RabbitURL.String(), &tls.Config{
ServerName: l.RabbitURL.Hostname(),
})
if err != nil {
return fmt.Errorf("Cannot connect to %s . Err: %w", l.RabbitURL.Hostname(), err)
}
defer connection.Close()
l.ch, err = connection.Channel()
if err != nil {
return fmt.Errorf("Cannot create a channel. Err: %w", err)
}
defer l.ch.Close()
if err = l.ch.ExchangeDeclarePassive("pubsub", "topic", true, false, false, false, nil); err != nil {
return fmt.Errorf("Cannot find pubsub exchange? Err: %w", err)
}
var q rabbitmq.Queue
if len(queueName) == 0 {
q, err = l.ch.QueueDeclare("", false, true, true, false, nil)
} else {
q, err = l.ch.QueueDeclarePassive(queueName, true, false, true, false, nil)
if err != nil {
LogInfo("queue not found .. trying to create it:", err)
if l.ch.IsClosed() {
l.ch, err = connection.Channel()
if err != nil {
return fmt.Errorf("Channel cannot be re-opened. Err: %w", err)
}
}
q, err = l.ch.QueueDeclare(queueName, true, false, true, false, nil)
if err != nil {
LogInfo("can't create persistent queue ... falling back to temporaty queue:", err)
if l.ch.IsClosed() {
l.ch, err = connection.Channel()
return fmt.Errorf("Channel cannot be re-opened. Err: %w", err)
}
q, err = l.ch.QueueDeclare("", false, true, true, false, nil)
}
}
}
if err != nil {
return fmt.Errorf("Cannot declare queue. Err: %w", err)
}
// log.Printf("queue: %s:%d", q.Name, q.Consumers)
LogDebug(" -- listening to topics:")
l.topicSubChanges = make(chan string)
defer close(l.topicSubChanges)
go l.ProcessTopicChanges()
for _, topic := range l.topics {
l.topicSubChanges <- "+" + topic
}
msgs, err := l.ch.Consume(q.Name, "", true, true, false, false, nil)
if err != nil {
return fmt.Errorf("Cannot start consumer. Err: %w", err)
}
// log.Printf("queue: %s:%d", q.Name, q.Consumers)
for {
msg, ok := <-msgs
if !ok {
return fmt.Errorf("channel/connection closed?\n")
}
msgCh <- RabbitMessage(msg)
}
}
func (l *RabbitConnection) ConnectAndProcessRabbitMQ(ch chan<- RabbitMessage) {
defer func() {
if r := recover(); r != nil {
LogError(r)
LogError("'crash' RabbitMQ worker. Recovering... reconnecting...")
time.Sleep(5 * time.Second)
go l.ConnectAndProcessRabbitMQ(ch)
}
}()
for {
err := l.ProcessRabbitMQ(ch)
if err != nil {
LogError("Error in RabbitMQ connection:", err)
LogInfo("Reconnecting in 2 seconds...")
time.Sleep(2 * time.Second)
}
}
}
func (l *RabbitConnection) ConnectToRabbitMQ(processor RabbitProcessor) <-chan RabbitMessage {
LogInfo("RabbitMQ connection:", l.RabbitURL.String())
l.RabbitURL.User = url.UserPassword(rabbitUser, rabbitPassword)
l.topics = processor.GenerateTopics()
ch := make(chan RabbitMessage, 100)
go l.ConnectAndProcessRabbitMQ(ch)
return ch
}
func (l *RabbitConnection) UpdateTopics(processor RabbitProcessor) {
newTopics := processor.GenerateTopics()
j := 0
next_new_topic:
for i := 0; i < len(newTopics); i++ {
topic := newTopics[i]
for j < len(l.topics) {
cmp := strings.Compare(topic, l.topics[j])
if cmp == 0 {
j++
continue next_new_topic
}
if cmp < 0 {
l.topicSubChanges <- "+" + topic
break
}
l.topicSubChanges <- "-" + l.topics[j]
j++
}
if j == len(l.topics) {
l.topicSubChanges <- "+" + topic
}
}
for j < len(l.topics) {
l.topicSubChanges <- "-" + l.topics[j]
j++
}
l.topics = newTopics
}
func ProcessRabbitMQEvents(processor RabbitProcessor) error {
ch := processor.Connection().ConnectToRabbitMQ(processor)
for {
msg, ok := <-ch
if !ok {
return nil
}
LogDebug("event:", msg.RoutingKey)
if err := processor.ProcessRabbitMessage(msg); err != nil {
LogError("Error processing", msg.RoutingKey, err)
}
}
}

129
common/rabbitmq_gitea.go Normal file
View File

@@ -0,0 +1,129 @@
package common
/*
* This file is part of Autogits.
*
* Copyright © 2024 SUSE LLC
*
* Autogits is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 2 of the License, or (at your option) any later
* version.
*
* Autogits is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Foobar. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"fmt"
"runtime/debug"
"slices"
"strings"
)
const RequestType_CreateBrachTag = "create"
const RequestType_DeleteBranchTag = "delete"
const RequestType_Fork = "fork"
const RequestType_Issue = "issues"
const RequestType_IssueAssign = "issue_assign"
const RequestType_IssueComment = "issue_comment"
const RequestType_IssueLabel = "issue_label"
const RequestType_IssueMilestone = "issue_milestone"
const RequestType_Push = "push"
const RequestType_Repository = "repository"
const RequestType_Release = "release"
const RequestType_PR = "pull_request"
const RequestType_PRAssign = "pull_request_assign"
const RequestType_PRLabel = "pull_request_label"
const RequestType_PRComment = "pull_request_comment"
const RequestType_PRMilestone = "pull_request_milestone"
const RequestType_PRSync = "pull_request_sync"
const RequestType_PRReviewAccepted = "pull_request_review_approved"
const RequestType_PRReviewRejected = "pull_request_review_rejected"
const RequestType_PRReviewRequest = "pull_request_review_request"
const RequestType_PRReviewComment = "pull_request_review_comment"
const RequestType_Status = "status"
const RequestType_Wiki = "wiki"
type RequestProcessor interface {
ProcessFunc(*Request) error
}
type RabbitMQGiteaEventsProcessor struct {
Handlers map[string]RequestProcessor
Orgs []string
c *RabbitConnection
}
func (gitea *RabbitMQGiteaEventsProcessor) Connection() *RabbitConnection {
if gitea.c == nil {
gitea.c = &RabbitConnection{}
}
return gitea.c
}
func (gitea *RabbitMQGiteaEventsProcessor) GenerateTopics() []string {
topics := make([]string, 0, len(gitea.Handlers)*len(gitea.Orgs))
scope := "suse"
if gitea.c.RabbitURL.Hostname() == "rabbit.opensuse.org" {
scope = "opensuse"
}
for _, org := range gitea.Orgs {
for requestType, _ := range gitea.Handlers {
topics = append(topics, fmt.Sprintf("%s.src.%s.%s.#", scope, org, requestType))
}
}
slices.Sort(topics)
return slices.Compact(topics)
}
func (gitea *RabbitMQGiteaEventsProcessor) ProcessRabbitMessage(msg RabbitMessage) error {
route := strings.Split(msg.RoutingKey, ".")
if len(route) > 3 {
reqType := route[3]
org := route[2]
if !slices.Contains(gitea.Orgs, org) {
LogInfo("Got event for unhandeled org:", org)
return nil
}
LogDebug("org:", org, "type:", reqType)
if handler, found := gitea.Handlers[reqType]; found {
req, err := ParseRequestJSON(reqType, msg.Body)
if err != nil {
LogError("Error parsing request JSON:", err)
} else {
LogDebug("processing req", req.Type)
// h.Request = req
ProcessEvent(handler, req)
}
return nil
}
}
return fmt.Errorf("Invalid routing key: %s", route)
}
func ProcessEvent(f RequestProcessor, request *Request) {
defer func() {
if r := recover(); r != nil {
LogError("panic caught")
if err, ok := r.(error); !ok {
LogError(err)
}
LogError(string(debug.Stack()))
}
}()
if err := f.ProcessFunc(request); err != nil {
LogError(err)
}
}

22
common/rabbitmq_obs.go Normal file
View File

@@ -0,0 +1,22 @@
package common
type RabbitMQObsBuildStatusProcessor struct {
c *RabbitConnection
}
func (o *RabbitMQObsBuildStatusProcessor) GenerateTopics() []string {
return []string{}
}
func (o *RabbitMQObsBuildStatusProcessor) Connection() *RabbitConnection {
if o.c == nil {
o.c = &RabbitConnection{}
}
return o.c
}
func (o *RabbitMQObsBuildStatusProcessor) ProcessRabbitMessage(msg RabbitMessage) error {
return nil
}

101
common/rabbitmq_test.go Normal file
View File

@@ -0,0 +1,101 @@
package common
import (
"net/url"
"slices"
"testing"
)
func TestListenDefinitionsTopicUpdate(t *testing.T) {
tests := []struct {
name string
handlers []string
orgs1, orgs2 []string
topicDelta []string
}{
{
name: "no handlers, no orgs",
},
{
name: "adding one org",
handlers: []string{"foo"},
orgs2: []string{"NewOrg"},
topicDelta: []string{"+suse.src.NewOrg.foo.#"},
},
{
name: "adding two orgs",
handlers: []string{"foo", "bar"},
orgs1: []string{"old"},
orgs2: []string{"old", "NewOrg", "NewOrg2"},
topicDelta: []string{"+suse.src.NewOrg.foo.#", "+suse.src.NewOrg2.foo.#", "+suse.src.NewOrg.bar.#", "+suse.src.NewOrg2.bar.#"},
},
{
name: "adding one org and removing old one",
handlers: []string{"foo", "bar"},
orgs1: []string{"old"},
orgs2: []string{"NewOrg"},
topicDelta: []string{"+suse.src.NewOrg.foo.#", "+suse.src.NewOrg.bar.#", "-suse.src.old.foo.#", "-suse.src.old.bar.#"},
},
{
name: "adding one org and removing old one",
handlers: []string{"foo", "bar"},
orgs1: []string{"NewOrg"},
orgs2: []string{"old"},
topicDelta: []string{"-suse.src.NewOrg.foo.#", "-suse.src.NewOrg.bar.#", "+suse.src.old.foo.#", "+suse.src.old.bar.#"},
},
}
u, _ := url.Parse("amqps://rabbit.example.com")
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
l := &RabbitMQGiteaEventsProcessor{
Orgs: test.orgs1,
Handlers: make(map[string]RequestProcessor),
c: &RabbitConnection{
RabbitURL: u,
topicSubChanges: make(chan string, len(test.topicDelta)*10),
},
}
slices.Sort(test.topicDelta)
for _, r := range test.handlers {
l.Handlers[r] = nil
}
changes := []string{}
l.c.UpdateTopics(l)
a:
for {
select {
case c := <-l.c.topicSubChanges:
changes = append(changes, c)
default:
changes = []string{}
break a
}
}
l.Orgs = test.orgs2
l.c.UpdateTopics(l)
changes = []string{}
b:
for {
select {
case c := <-l.c.topicSubChanges:
changes = append(changes, c)
default:
slices.Sort(changes)
break b
}
}
if !slices.Equal(changes, test.topicDelta) {
t.Error("got:", changes, " expected:", test.topicDelta)
}
})
}
}

View File

@@ -21,8 +21,6 @@ package common
import (
"encoding/json"
"fmt"
"log"
"os"
)
type RequestType interface {
@@ -87,24 +85,14 @@ func ParseRequestJSON(reqType string, data []byte) (req *Request, err error) {
}
type RequestHandler struct {
StdLogger, ErrLogger *log.Logger
Request *Request
}
func (r *RequestHandler) WriteError() {
r.ErrLogger.Println("internal error sent")
LogError("internal error sent")
}
func CreateRequestHandler() (*RequestHandler, error) {
var h *RequestHandler = new(RequestHandler)
h.StdLogger, h.ErrLogger = CreateStdoutLogger(os.Stdout, os.Stderr)
/* var err error
h.Git, err = CreateGitHandler(git_author, name)
if err != nil {
return nil, err
}
*/
return h, nil
}

View File

@@ -19,7 +19,6 @@ package common
*/
import (
"os"
"strings"
"testing"
)
@@ -27,8 +26,6 @@ import (
func TestPrParsing(t *testing.T) {
t.Run("Test parsing", func(t *testing.T) {
var h RequestHandler
h.StdLogger, h.ErrLogger = CreateStdoutLogger(os.Stdout, os.Stdout)
pr, err := h.parsePullRequest(strings.NewReader(samplePR_JSON))
if err != nil {
t.Fatalf("error parsing PR: %v\n", err)

Some files were not shown because too many files have changed in this diff Show More