#8 delete cobra, add micro-config-flag (#11)

Убрана кобра, доработаны методы создания, закрытия пулл реквестов.

Co-authored-by: Gorbunov Kirill Andreevich <kgorbunov@mtsbank.ru>
Reviewed-on: #11
Co-authored-by: Кирилл Горбунов <kirya_gorbunov_2015@mail.ru>
Co-committed-by: Кирилл Горбунов <kirya_gorbunov_2015@mail.ru>
This commit is contained in:
Кирилл Горбунов 2024-04-02 22:54:15 +03:00 committed by Василий Толстов
parent f913c01fca
commit eb2a21a1b1
24 changed files with 1337 additions and 1749 deletions

11
.gitea/pkgdashcli.yaml Normal file
View File

@ -0,0 +1,11 @@
branches: [master]
source:
type: gitea
apiurl: git.unistack.org
repository: pkgdash
owner: kgorbunov
update_opt:
pre: false
major: false
up_major: false
cached: true

5
.gitignore vendored
View File

@ -29,7 +29,4 @@ tmp/
cmd/pkgdash/pkgdash cmd/pkgdash/pkgdash
cmd/pkgdashcli/pkgdashcli cmd/pkgdashcli/pkgdashcli
*.sqlite *.sqlite
*.db *.db
.gitea
.github
.gitlab

View File

@ -3,6 +3,14 @@ build:
GOWORK=off CGO_ENABLED=0 go build -o bin/pkgdash -mod=readonly git.unistack.org/unistack-org/pkgdash/cmd/pkgdash GOWORK=off CGO_ENABLED=0 go build -o bin/pkgdash -mod=readonly git.unistack.org/unistack-org/pkgdash/cmd/pkgdash
GOWORK=off CGO_ENABLED=0 go build -o bin/pkgdashcli -mod=readonly git.unistack.org/unistack-org/pkgdash/cmd/pkgdashcli GOWORK=off CGO_ENABLED=0 go build -o bin/pkgdashcli -mod=readonly git.unistack.org/unistack-org/pkgdash/cmd/pkgdashcli
.PHONY: buildcli
buildcli:
CGO_ENABLED=0 go build -o bin/app -mod=readonly git.unistack.org/unistack-org/pkgdash/cmd/pkgdashcli
.PHONY: cli
cli:
go install git.unistack.org/unistack-org/pkgdash/cmd/pkgdashcli
.PHONY: test .PHONY: test
test: test:
go test -v ./... -race -cover go test -v ./... -race -cover

View File

@ -1507,10 +1507,10 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isFunction */ 2971); /* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isFunction */ 2971);
function throwError(errorOrErroractory, scheduler) { function throwError(errorOrErrorFactory, scheduler) {
const Erroractory = (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(errorOrErroractory) ? errorOrErroractory : () => errorOrErroractory; const errorFactory = (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(errorOrErrorFactory) ? errorOrErrorFactory : () => errorOrErrorFactory;
const init = subscriber => subscriber.error(Erroractory()); const init = subscriber => subscriber.error(errorFactory());
return new _Observable__WEBPACK_IMPORTED_MODULE_1__.Observable(scheduler ? subscriber => scheduler.schedule(init, 0, subscriber) : init); return new _Observable__WEBPACK_IMPORTED_MODULE_1__.Observable(scheduler ? subscriber => scheduler.schedule(init, 0, subscriber) : init);
} }
@ -2963,17 +2963,17 @@ __webpack_require__.r(__webpack_exports__);
function throwIfEmpty(Erroractory = defaultErroractory) { function throwIfEmpty(errorFactory = defaultErrorFactory) {
return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => { return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => {
let hasValue = false; let hasValue = false;
source.subscribe(new _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.OperatorSubscriber(subscriber, value => { source.subscribe(new _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.OperatorSubscriber(subscriber, value => {
hasValue = true; hasValue = true;
subscriber.next(value); subscriber.next(value);
}, () => hasValue ? subscriber.complete() : subscriber.error(Erroractory()))); }, () => hasValue ? subscriber.complete() : subscriber.error(errorFactory())));
}); });
} }
function defaultErroractory() { function defaultErrorFactory() {
return new _util_EmptyError__WEBPACK_IMPORTED_MODULE_2__.EmptyError(); return new _util_EmptyError__WEBPACK_IMPORTED_MODULE_2__.EmptyError();
} }
@ -51956,7 +51956,7 @@ function ɵɵresolveBody(element) {
*/ */
const INTERPOLATION_DELIMITER = `<EFBFBD>`; const INTERPOLATION_DELIMITER = `<60>`;
/** /**
* Unwrap a value which might be behind a closure (for forward declaration reasons). * Unwrap a value which might be behind a closure (for forward declaration reasons).
*/ */
@ -52069,7 +52069,7 @@ function getExpressionChangedErrorDetails(lView, bindingIndex, oldValue, newValu
} // metadata is not available for this expression, check if this expression is a part of the } // metadata is not available for this expression, check if this expression is a part of the
// property interpolation by going from the current binding index left and look for a string that // property interpolation by going from the current binding index left and look for a string that
// contains INTERPOLATION_DELIMITER, the layout in tView.data for this case will look like this: // contains INTERPOLATION_DELIMITER, the layout in tView.data for this case will look like this:
// [..., 'id<EFBFBD>Prefix <20> and <20> suffix', null, null, null, ...] // [..., 'id<69>Prefix <20> and <20> suffix', null, null, null, ...]
if (metadata === null) { if (metadata === null) {
@ -56810,7 +56810,7 @@ function executeViewQueryFn(flags, viewQueryFn, component) {
* `LView`). Metadata are represented as `INTERPOLATION_DELIMITER`-delimited string with the * `LView`). Metadata are represented as `INTERPOLATION_DELIMITER`-delimited string with the
* following format: * following format:
* - `propertyName` for bound properties; * - `propertyName` for bound properties;
* - `propertyName<EFBFBD>prefix<EFBFBD>interpolation_static_part1<EFBFBD>..interpolation_static_partN<74>suffix` for * - `propertyName<6D>prefix<69>interpolation_static_part1<74>..interpolation_static_partN<74>suffix` for
* interpolated properties. * interpolated properties.
* *
* @param tData `TData` where meta-data will be saved; * @param tData `TData` where meta-data will be saved;
@ -64853,13 +64853,13 @@ class OpCodeParser {
*/ */
const BINDING_REGEXP = /<EFBFBD>(\d+):?\d*<2A>/gi; const BINDING_REGEXP = /<2F>(\d+):?\d*<2A>/gi;
const ICU_REGEXP = /({\s*<EFBFBD>\d+:?\d*<2A>\s*,\s*\S{6}\s*,[\s\S]*})/gi; const ICU_REGEXP = /({\s*<2A>\d+:?\d*<2A>\s*,\s*\S{6}\s*,[\s\S]*})/gi;
const NESTED_ICU = /<EFBFBD>(\d+)<29>/; const NESTED_ICU = /<2F>(\d+)<29>/;
const ICU_BLOCK_REGEXP = /^\s*(<EFBFBD>\d+:?\d*<2A>)\s*,\s*(select|plural)\s*,/; const ICU_BLOCK_REGEXP = /^\s*(<28>\d+:?\d*<2A>)\s*,\s*(select|plural)\s*,/;
const MARKER = `<EFBFBD>`; const MARKER = `<60>`;
const SUBTEMPLATE_REGEXP = /<EFBFBD>\/?\*(\d+:\d+)<29>/gi; const SUBTEMPLATE_REGEXP = /<2F>\/?\*(\d+:\d+)<29>/gi;
const PH_REGEXP = /<EFBFBD>(\/?[#*]\d+):?\d*<2A>/gi; const PH_REGEXP = /<2F>(\/?[#*]\d+):?\d*<2A>/gi;
/** /**
* Angular Dart introduced &ngsp; as a placeholder for non-removable space, see: * Angular Dart introduced &ngsp; as a placeholder for non-removable space, see:
* https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart#L25-L32 * https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart#L25-L32
@ -64942,7 +64942,7 @@ function i18nStartFirstCreatePass(tView, parentTNodeIndex, lView, index, message
} }
} else { } else {
// Odd indexes are placeholders (elements and sub-templates) // Odd indexes are placeholders (elements and sub-templates)
// At this point value is something like: '/#1:2' (originally coming from '<EFBFBD>/#1:2<>') // At this point value is something like: '/#1:2' (originally coming from '<27>/#1:2<>')
const isClosing = value.charCodeAt(0) === 47 const isClosing = value.charCodeAt(0) === 47
/* CharCode.SLASH */ /* CharCode.SLASH */
; ;
@ -65298,7 +65298,7 @@ function icuStart(tView, lView, updateOpCodes, parentIdx, icuExpression, anchorI
// It is an nested ICU expression // It is an nested ICU expression
const icuIndex = nestedIcus.push(value) - 1; // Replace nested ICU expression by a comment node const icuIndex = nestedIcus.push(value) - 1; // Replace nested ICU expression by a comment node
valueArr[j] = `<!--<EFBFBD>${icuIndex}<EFBFBD>-->`; valueArr[j] = `<!--<2D>${icuIndex}<7D>-->`;
} }
} }
@ -65597,11 +65597,11 @@ function addCreateAttribute(create, newIndex, attr) {
const ROOT_TEMPLATE_ID = 0; const ROOT_TEMPLATE_ID = 0;
const PP_MULTI_VALUE_PLACEHOLDERS_REGEXP = /\[(<EFBFBD>.+?<3F>?)\]/; const PP_MULTI_VALUE_PLACEHOLDERS_REGEXP = /\[(<28>.+?<3F>?)\]/;
const PP_PLACEHOLDERS_REGEXP = /\[(<EFBFBD>.+?<3F>?)\]|(<28>\/?\*\d+:\d+<2B>)/g; const PP_PLACEHOLDERS_REGEXP = /\[(<28>.+?<3F>?)\]|(<28>\/?\*\d+:\d+<2B>)/g;
const PP_ICU_VARS_REGEXP = /({\s*)(VAR_(PLURAL|SELECT)(_\d+)?)(\s*,)/g; const PP_ICU_VARS_REGEXP = /({\s*)(VAR_(PLURAL|SELECT)(_\d+)?)(\s*,)/g;
const PP_ICU_PLACEHOLDERS_REGEXP = /{([A-Z0-9_]+)}/g; const PP_ICU_PLACEHOLDERS_REGEXP = /{([A-Z0-9_]+)}/g;
const PP_ICUS_REGEXP = /<EFBFBD>I18N_EXP_(ICU(_\d+)?)<29>/g; const PP_ICUS_REGEXP = /<2F>I18N_EXP_(ICU(_\d+)?)<29>/g;
const PP_CLOSE_TEMPLATE_REGEXP = /\/\*/; const PP_CLOSE_TEMPLATE_REGEXP = /\/\*/;
const PP_TEMPLATE_ID_REGEXP = /\d+\:(\d+)/; const PP_TEMPLATE_ID_REGEXP = /\d+\:(\d+)/;
/** /**
@ -65611,10 +65611,10 @@ const PP_TEMPLATE_ID_REGEXP = /\d+\:(\d+)/;
* format (that might contain some markers that we need to replace) to the final * format (that might contain some markers that we need to replace) to the final
* form, consumable by i18nStart instruction. Post processing steps include: * form, consumable by i18nStart instruction. Post processing steps include:
* *
* 1. Resolve all multi-value cases (like [<EFBFBD>*1:1<EFBFBD><EFBFBD>#2:1<EFBFBD>|<EFBFBD>#4:1<EFBFBD>|<EFBFBD>5<EFBFBD>]) * 1. Resolve all multi-value cases (like [<5B>*1:1<><31>#2:1<>|<7C>#4:1<>|<7C>5<EFBFBD>])
* 2. Replace all ICU vars (like "VAR_PLURAL") * 2. Replace all ICU vars (like "VAR_PLURAL")
* 3. Replace all placeholders used inside ICUs in a form of {PLACEHOLDER} * 3. Replace all placeholders used inside ICUs in a form of {PLACEHOLDER}
* 4. Replace all ICU references with corresponding values (like <EFBFBD>ICU_EXP_ICU_1<EFBFBD>) * 4. Replace all ICU references with corresponding values (like <20>ICU_EXP_ICU_1<5F>)
* in case multiple ICUs have the same placeholder name * in case multiple ICUs have the same placeholder name
* *
* @param message Raw translation string for post processing * @param message Raw translation string for post processing
@ -65627,13 +65627,13 @@ const PP_TEMPLATE_ID_REGEXP = /\d+\:(\d+)/;
function i18nPostprocess(message, replacements = {}) { function i18nPostprocess(message, replacements = {}) {
/** /**
* Step 1: resolve all multi-value placeholders like [<EFBFBD>#5<EFBFBD>|<EFBFBD>*1:1<EFBFBD><EFBFBD>#2:1<EFBFBD>|<EFBFBD>#4:1<EFBFBD>] * Step 1: resolve all multi-value placeholders like [<5B>#5<>|<7C>*1:1<><31>#2:1<>|<7C>#4:1<>]
* *
* Note: due to the way we process nested templates (BFS), multi-value placeholders are typically * Note: due to the way we process nested templates (BFS), multi-value placeholders are typically
* grouped by templates, for example: [<EFBFBD>#5<EFBFBD>|<EFBFBD>#6<EFBFBD>|<EFBFBD>#1:1<EFBFBD>|<EFBFBD>#3:2<EFBFBD>] where <EFBFBD>#5<EFBFBD> and <EFBFBD>#6<EFBFBD> belong to root * grouped by templates, for example: [<5B>#5<>|<7C>#6<>|<7C>#1:1<>|<7C>#3:2<>] where <20>#5<> and <20>#6<> belong to root
* template, <EFBFBD>#1:1<EFBFBD> belong to nested template with index 1 and <EFBFBD>#1:2<EFBFBD> - nested template with index * template, <20>#1:1<> belong to nested template with index 1 and <20>#1:2<> - nested template with index
* 3. However in real templates the order might be different: i.e. <EFBFBD>#1:1<EFBFBD> and/or <EFBFBD>#3:2<EFBFBD> may go in * 3. However in real templates the order might be different: i.e. <20>#1:1<> and/or <20>#3:2<> may go in
* front of <EFBFBD>#6<EFBFBD>. The post processing step restores the right order by keeping track of the * front of <20>#6<>. The post processing step restores the right order by keeping track of the
* template id stack and looks for placeholders that belong to the currently active template. * template id stack and looks for placeholders that belong to the currently active template.
*/ */
let result = message; let result = message;
@ -65704,7 +65704,7 @@ function i18nPostprocess(message, replacements = {}) {
return replacements.hasOwnProperty(key) ? replacements[key] : match; return replacements.hasOwnProperty(key) ? replacements[key] : match;
}); });
/** /**
* Step 4: replace all ICU references with corresponding values (like <EFBFBD>ICU_EXP_ICU_1<EFBFBD>) in case * Step 4: replace all ICU references with corresponding values (like <20>ICU_EXP_ICU_1<5F>) in case
* multiple ICUs have the same placeholder name * multiple ICUs have the same placeholder name
*/ */
@ -65739,14 +65739,14 @@ function i18nPostprocess(message, replacements = {}) {
* contain placeholders which associate inner elements and sub-templates within the translation. * contain placeholders which associate inner elements and sub-templates within the translation.
* *
* The translation `message` placeholders are: * The translation `message` placeholders are:
* - `<EFBFBD>{index}(:{block})<29>`: *Binding Placeholder*: Marks a location where an expression will be * - `<60>{index}(:{block})<29>`: *Binding Placeholder*: Marks a location where an expression will be
* interpolated into. The placeholder `index` points to the expression binding index. An optional * interpolated into. The placeholder `index` points to the expression binding index. An optional
* `block` that matches the sub-template in which it was declared. * `block` that matches the sub-template in which it was declared.
* - `<EFBFBD>#{index}(:{block})<29>`/`<EFBFBD>/#{index}(:{block})<29>`: *Element Placeholder*: Marks the beginning * - `<60>#{index}(:{block})<29>`/`<60>/#{index}(:{block})<29>`: *Element Placeholder*: Marks the beginning
* and end of DOM element that were embedded in the original translation block. The placeholder * and end of DOM element that were embedded in the original translation block. The placeholder
* `index` points to the element index in the template instructions set. An optional `block` that * `index` points to the element index in the template instructions set. An optional `block` that
* matches the sub-template in which it was declared. * matches the sub-template in which it was declared.
* - `<EFBFBD>*{index}:{block}<7D>`/`<EFBFBD>/*{index}:{block}<7D>`: *Sub-template Placeholder*: Sub-templates must be * - `<60>*{index}:{block}<7D>`/`<60>/*{index}:{block}<7D>`: *Sub-template Placeholder*: Sub-templates must be
* split up and translated separately in each angular template function. The `index` points to the * split up and translated separately in each angular template function. The `index` points to the
* `template` instruction index. A `block` that matches the sub-template in which it was declared. * `template` instruction index. A `block` that matches the sub-template in which it was declared.
* *
@ -65801,14 +65801,14 @@ function ɵɵi18nEnd() {
* contain placeholders which associate inner elements and sub-templates within the translation. * contain placeholders which associate inner elements and sub-templates within the translation.
* *
* The translation `message` placeholders are: * The translation `message` placeholders are:
* - `<EFBFBD>{index}(:{block})<29>`: *Binding Placeholder*: Marks a location where an expression will be * - `<60>{index}(:{block})<29>`: *Binding Placeholder*: Marks a location where an expression will be
* interpolated into. The placeholder `index` points to the expression binding index. An optional * interpolated into. The placeholder `index` points to the expression binding index. An optional
* `block` that matches the sub-template in which it was declared. * `block` that matches the sub-template in which it was declared.
* - `<EFBFBD>#{index}(:{block})<29>`/`<EFBFBD>/#{index}(:{block})<29>`: *Element Placeholder*: Marks the beginning * - `<60>#{index}(:{block})<29>`/`<60>/#{index}(:{block})<29>`: *Element Placeholder*: Marks the beginning
* and end of DOM element that were embedded in the original translation block. The placeholder * and end of DOM element that were embedded in the original translation block. The placeholder
* `index` points to the element index in the template instructions set. An optional `block` that * `index` points to the element index in the template instructions set. An optional `block` that
* matches the sub-template in which it was declared. * matches the sub-template in which it was declared.
* - `<EFBFBD>*{index}:{block}<7D>`/`<EFBFBD>/*{index}:{block}<7D>`: *Sub-template Placeholder*: Sub-templates must be * - `<60>*{index}:{block}<7D>`/`<60>/*{index}:{block}<7D>`: *Sub-template Placeholder*: Sub-templates must be
* split up and translated separately in each angular template function. The `index` points to the * split up and translated separately in each angular template function. The `index` points to the
* `template` instruction index. A `block` that matches the sub-template in which it was declared. * `template` instruction index. A `block` that matches the sub-template in which it was declared.
* *
@ -65877,10 +65877,10 @@ function ɵɵi18nApply(index) {
* format (that might contain some markers that we need to replace) to the final * format (that might contain some markers that we need to replace) to the final
* form, consumable by i18nStart instruction. Post processing steps include: * form, consumable by i18nStart instruction. Post processing steps include:
* *
* 1. Resolve all multi-value cases (like [<EFBFBD>*1:1<EFBFBD><EFBFBD>#2:1<EFBFBD>|<EFBFBD>#4:1<EFBFBD>|<EFBFBD>5<EFBFBD>]) * 1. Resolve all multi-value cases (like [<5B>*1:1<><31>#2:1<>|<7C>#4:1<>|<7C>5<EFBFBD>])
* 2. Replace all ICU vars (like "VAR_PLURAL") * 2. Replace all ICU vars (like "VAR_PLURAL")
* 3. Replace all placeholders used inside ICUs in a form of {PLACEHOLDER} * 3. Replace all placeholders used inside ICUs in a form of {PLACEHOLDER}
* 4. Replace all ICU references with corresponding values (like <EFBFBD>ICU_EXP_ICU_1<EFBFBD>) * 4. Replace all ICU references with corresponding values (like <20>ICU_EXP_ICU_1<5F>)
* in case multiple ICUs have the same placeholder name * in case multiple ICUs have the same placeholder name
* *
* @param message Raw translation string for post processing * @param message Raw translation string for post processing
@ -67599,19 +67599,19 @@ class EventEmitter_ extends rxjs__WEBPACK_IMPORTED_MODULE_0__.Subject {
subscribe(observerOrNext, error, complete) { subscribe(observerOrNext, error, complete) {
let nextFn = observerOrNext; let nextFn = observerOrNext;
let Errorn = error || (() => null); let errorFn = error || (() => null);
let completeFn = complete; let completeFn = complete;
if (observerOrNext && typeof observerOrNext === 'object') { if (observerOrNext && typeof observerOrNext === 'object') {
const observer = observerOrNext; const observer = observerOrNext;
nextFn = observer.next?.bind(observer); nextFn = observer.next?.bind(observer);
Errorn = observer.error?.bind(observer); errorFn = observer.error?.bind(observer);
completeFn = observer.complete?.bind(observer); completeFn = observer.complete?.bind(observer);
} }
if (this.__isAsync) { if (this.__isAsync) {
Errorn = _wrapInTimeout(Errorn); errorFn = _wrapInTimeout(errorFn);
if (nextFn) { if (nextFn) {
nextFn = _wrapInTimeout(nextFn); nextFn = _wrapInTimeout(nextFn);
@ -67624,7 +67624,7 @@ class EventEmitter_ extends rxjs__WEBPACK_IMPORTED_MODULE_0__.Subject {
const sink = super.subscribe({ const sink = super.subscribe({
next: nextFn, next: nextFn,
error: Errorn, error: errorFn,
complete: completeFn complete: completeFn
}); });

File diff suppressed because one or more lines are too long

View File

@ -5,11 +5,13 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"errors" "errors"
"flag"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"os" "os"
"os/exec" "os/exec"
"os/user"
"path/filepath" "path/filepath"
"strings" "strings"
"text/template" "text/template"
@ -23,9 +25,11 @@ import (
"github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object" "github.com/go-git/go-git/v5/plumbing/object"
httpauth "github.com/go-git/go-git/v5/plumbing/transport/http" httpauth "github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/jdx/go-netrc"
yamlcodec "go.unistack.org/micro-codec-yaml/v4" yamlcodec "go.unistack.org/micro-codec-yaml/v4"
envconfig "go.unistack.org/micro-config-env/v4" envconfig "go.unistack.org/micro-config-env/v4"
fileconfig "go.unistack.org/micro-config-file/v4" fileconfig "go.unistack.org/micro-config-file/v4"
microflag "go.unistack.org/micro-config-flag/v4"
"go.unistack.org/micro/v4/config" "go.unistack.org/micro/v4/config"
"go.unistack.org/micro/v4/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v4/logger/slog" "go.unistack.org/micro/v4/logger/slog"
@ -36,6 +40,24 @@ import (
// https://docs.github.com/ru/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file // https://docs.github.com/ru/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
var initMsg = `
Pkgdashcli allows you to define a version update for a dependency and start
merge requests in version control systems.
Usage:
pkgdashcli --command {{command}} --path {{name of dep}}
Commands:
checkupdate | CheckUpdate collects a list of dependencies with the latest updates.
list | Returns a list of PR for this repository with update dependencies.
update --path {{name of one dep or empty for update all dep}} | Creates a PR with the specified dependency update in path or creates a PR with dependency updates for all modules if path is empty.
close --path {{name of one dep or empty for close all pr}} | Closes the PR for the specified dependency or closes all PRs with dependency updates if path is empty .
Flags:
--command | The command to execute
--path | The name of the module to create/close the PR, if empty, the command is executed for all modules.
`
var ( var (
DefaultPullRequestTitle = `Bump {{.Name}} from {{.VersionOld}} to {{.VersionNew}}` DefaultPullRequestTitle = `Bump {{.Name}} from {{.VersionOld}} to {{.VersionNew}}`
DefaultPullRequestBody = `Bumps {{.Name}} from {{.VersionOld}} to {{.VersionNew}}` DefaultPullRequestBody = `Bumps {{.Name}} from {{.VersionOld}} to {{.VersionNew}}`
@ -58,13 +80,19 @@ var (
".github": "github", ".github": "github",
".gitlab": "gitlab", ".gitlab": "gitlab",
} }
repoAPI = map[string]string{
".gitea": "git.unistack.org",
".gogs": "gogs",
".github": "github.com/unistack-org",
".gitlab": "gitlab.mtsbank.ru",
}
) )
type Data struct { type Data struct {
Modules map[string]modules.Update Modules map[string]modules.Update
} }
func pkgdashcli() { func main() {
var err error var err error
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
@ -94,14 +122,18 @@ func pkgdashcli() {
for _, configDir := range configDirs { for _, configDir := range configDirs {
for _, configFile := range configFiles { for _, configFile := range configFiles {
logger.Info(ctx, fmt.Sprintf("path: %s", filepath.Join(configDir, configFile))) path := filepath.Join(configDir, configFile)
if _, err = os.Stat(path); os.IsNotExist(err) {
continue
}
c := fileconfig.NewConfig( c := fileconfig.NewConfig(
config.AllowFail(false), config.AllowFail(false),
config.Struct(cfg), config.Struct(cfg),
options.Codec(yamlcodec.NewCodec()), options.Codec(yamlcodec.NewCodec()),
fileconfig.Path(".gitea/pkgdashcli.yaml"), fileconfig.Path(path),
) )
err = c.Init(options.Context(ctx)) err = c.Init()
if err != nil { if err != nil {
logger.Error(ctx, fmt.Sprintf("failed to init config: %v", err)) logger.Error(ctx, fmt.Sprintf("failed to init config: %v", err))
} }
@ -111,8 +143,6 @@ func pkgdashcli() {
} }
} }
logger.Info(ctx, fmt.Sprintf("Load config... %s", cfg.Source.Repository))
if cfg.PullRequestBody == "" { if cfg.PullRequestBody == "" {
cfg.PullRequestBody = DefaultPullRequestBody cfg.PullRequestBody = DefaultPullRequestBody
} }
@ -121,6 +151,22 @@ func pkgdashcli() {
cfg.PullRequestTitle = DefaultPullRequestTitle cfg.PullRequestTitle = DefaultPullRequestTitle
} }
cliCfg := &configcli.Cli{}
c := microflag.NewConfig(config.Struct(cliCfg), microflag.FlagErrorHandling(flag.ContinueOnError))
if err = c.Init(); err != nil {
logger.Fatal(ctx, fmt.Sprintf("init cli cfg failed: %v", err))
}
if err = c.Load(ctx); err != nil {
logger.Fatal(ctx, fmt.Sprintf("load cli cfg failed: %v", err))
}
if cliCfg.Path == "" && cliCfg.Command == "" {
fmt.Print(initMsg)
return
}
path := "." path := "."
if len(os.Args) > 1 { if len(os.Args) > 1 {
path = os.Args[1] path = os.Args[1]
@ -173,71 +219,138 @@ func pkgdashcli() {
modules.Updates(updateOptions) modules.Updates(updateOptions)
/*var repoGit, tokenGit string // nameGit = gitea, repoGit = pkgdash, tokenGit = {xxx}, machine?? if err = getRepoMgmt(ctx, cfg); err != nil { // Filling in empty config fields.
if cfg.Source != nil { logger.Error(ctx, err.Error())
repoGit = cfg.Source.TypeGit
tokenGit = cfg.Source.Token
} else {
repoGit = getRepoMgmt()
if repoGit == "unknown" {
logger.Fatal(ctx, "pkgdash/main failed to get repo management")
}
} }
usr, err := user.Current()
if err != nil {
logger.Error(ctx, "pkgdash/main can t get info user: %s", err)
} else {
n, err := netrc.Parse(filepath.Join(usr.HomeDir, ".netrc"))
if err != nil {
logger.Error(ctx, "pkgdash/main can t parse .netrc: %s", err)
}
tokenGit = n.Machine(repoGit).Get("password")
}
switch repoGit {
case "gitea":
for _, branch := range cfg.Branches {
err = giteaPullRequest(ctx, cfg, branch, mvs)
}
}*/
logger.Info(ctx, fmt.Sprintf("cfg: %v", cfg))
gitSource := source.NewSourceControl(*cfg) gitSource := source.NewSourceControl(*cfg)
for _, branch := range cfg.Branches {
for pathMod, mod := range mvs { Execute(ctx, gitSource, mvs, *cliCfg, *cfg)
logger.Debug(ctx, fmt.Sprintf("Start update %s from %s to %s", pathMod, mod.Module.Version, mod.Version))
err = gitSource.RequestOpen(ctx, branch, pathMod, mod)
if err != nil {
logger.Error(ctx, fmt.Sprintf("failed to create pr: %v", err))
}
logger.Debug(ctx, fmt.Sprintf("Update successful for %s", pathMod))
}
}
// err = gitSource.RequestClose(ctx, "master", "modernc.org/ccgo/v4")
logger.Info(ctx, "Pkgdash successfully updated dependencies") logger.Info(ctx, "Pkgdash successfully updated dependencies")
} }
func getRepoMgmt() string { func Execute(ctx context.Context, gitSource source.SourceControl, mvs map[string]modules.Update, cliCfg configcli.Cli, cfg configcli.Config) {
var mod modules.Update
var ok bool
var path string
prList := make(map[string]map[string]string)
switch cliCfg.Command {
case "checkupdate":
js, err := json.Marshal(mvs)
fmt.Println(fmt.Sprintf(`Modules get update: %s, %s`, js, err))
case "update":
if cliCfg.Path != "" { // update one dep
path = cliCfg.Path
if mod, ok = mvs[path]; !ok {
logger.Fatal(ctx, fmt.Sprintf("For %s update not exist", path))
}
logger.Debugf(ctx, fmt.Sprintf("Start update %s from %s to %s", path, mod.Module.Version, mod.Version))
for _, branch := range cfg.Branches {
if err := gitSource.RequestOpen(ctx, branch, path, mod); err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to create pr: %v", err))
}
}
logger.Debugf(ctx, fmt.Sprintf("Update successful for %s", path))
return
}
for _, branch := range cfg.Branches { // update all dep
for path, mod = range mvs {
logger.Debugf(ctx, fmt.Sprintf("Start update %s from %s to %s", path, mod.Module.Version, mod.Version))
err := gitSource.RequestOpen(ctx, branch, path, mod)
if err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to create pr: %v", err))
}
logger.Debugf(ctx, fmt.Sprintf("Update successful for %s", path))
}
}
case "close":
if cliCfg.Path != "" { // close one dep
path = cliCfg.Path
logger.Debugf(ctx, fmt.Sprintf("Start close for %s", path))
for _, branch := range cfg.Branches {
if err := gitSource.RequestClose(ctx, branch, path); err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to close pr: %v", err))
}
}
logger.Debugf(ctx, fmt.Sprintf("Close successful for %s", path))
return
}
for _, branch := range cfg.Branches {
logger.Info(ctx, fmt.Sprintf("Start getting pr for %s", branch))
rMap, err := gitSource.RequestList(ctx, branch)
if err != nil {
logger.Fatal(ctx, fmt.Sprintf("Error with getting pr list for branch: %s", branch))
}
logger.Info(ctx, fmt.Sprintf("for %s:\n%s", branch, rMap))
logger.Info(ctx, fmt.Sprintf("Start close pr for base branch %s", branch))
for path, _ = range rMap {
logger.Debugf(ctx, fmt.Sprintf("Start close for %s", path))
if err = gitSource.RequestClose(ctx, branch, path); err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to close pr: %v", err))
}
logger.Debugf(ctx, fmt.Sprintf("Close successful for %s", path))
}
}
case "list":
for _, branch := range cfg.Branches {
rMap, err := gitSource.RequestList(ctx, branch)
if err != nil {
logger.Fatal(ctx, fmt.Sprintf("RequestList: error %s", err))
}
prList[branch] = rMap
}
js, err := json.Marshal(prList)
if err != nil {
logger.Error(ctx, fmt.Sprintf("error: %s", err))
}
fmt.Println(fmt.Sprintf("for %s:\n%s", cfg.Source.Repository, js))
default:
fmt.Print(initMsg)
}
}
func getRepoMgmt(ctx context.Context, cfg *configcli.Config) error {
wd, err := os.Getwd() wd, err := os.Getwd()
if err != nil { if err != nil {
return "unknown" return err
} }
p := filepath.Clean(wd) p := filepath.Clean(wd)
for { for _, configDir := range configDirs {
for _, configDir := range configDirs { _, err := os.Stat(filepath.Join(p, configDir))
_, err := os.Stat(filepath.Join(p, configDir)) if name, ok := repoMgmt[configDir]; ok && cfg.Source.TypeGit == "" && err == nil {
if name, ok := repoMgmt[configDir]; ok && err == nil { cfg.Source.TypeGit = name
return name
}
} }
if p == "/" { if api, ok := repoAPI[configDir]; ok && cfg.Source.APIURL == "" && err == nil {
return "unknown" cfg.Source.APIURL = api
} }
p = filepath.Clean(filepath.Join(p, ".."))
} }
if p == "/" && cfg.Source.TypeGit == "" && cfg.Source.APIURL == "" {
return fmt.Errorf("unknown")
}
p = filepath.Clean(filepath.Join(p, ".."))
usr, err := user.Current()
if err != nil {
logger.Fatal(ctx, fmt.Sprintf("pkgdash/main can t get info about user: %s", err))
}
n, err := netrc.Parse(filepath.Join(usr.HomeDir, ".netrc"))
if err != nil {
logger.Error(ctx, "pkgdash/main can t parse .netrc: %s", err)
}
if cfg.Source.Owner == "" {
cfg.Source.Owner = n.Machine(cfg.Source.APIURL).Get("login")
}
if cfg.Source.Token == "" {
cfg.Source.Token = n.Machine(cfg.Source.APIURL).Get("password")
}
return nil
} }
func giteaPullRequest(ctx context.Context, cfg *configcli.Config, branch string, mods map[string]modules.Update) error { func giteaPullRequest(ctx context.Context, cfg *configcli.Config, branch string, mods map[string]modules.Update) error {

View File

@ -1,7 +0,0 @@
package main
import "git.unistack.org/unistack-org/pkgdash/internal/cli"
func main() {
cli.Execute()
}

103
go.mod
View File

@ -4,108 +4,117 @@ go 1.20
require ( require (
github.com/envoyproxy/protoc-gen-validate v1.0.4 github.com/envoyproxy/protoc-gen-validate v1.0.4
github.com/go-git/go-git/v5 v5.11.0 github.com/go-git/go-git/v5 v5.8.1
github.com/golang-migrate/migrate/v4 v4.17.0 github.com/golang-migrate/migrate/v4 v4.15.1
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/jackc/pgx/v4 v4.18.3 github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c
github.com/jmoiron/sqlx v1.3.5 github.com/jdx/go-netrc v1.0.0
github.com/jmoiron/sqlx v1.3.1
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.8.0 github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.3
go.unistack.org/micro-client-http/v4 v4.0.3 go.unistack.org/micro-client-http/v4 v4.0.2
go.unistack.org/micro-codec-json/v4 v4.0.0 go.unistack.org/micro-codec-json/v4 v4.0.0
go.unistack.org/micro-codec-jsonpb/v4 v4.0.1 go.unistack.org/micro-codec-jsonpb/v4 v4.0.0
go.unistack.org/micro-codec-yaml/v4 v4.0.0 go.unistack.org/micro-codec-yaml/v4 v4.0.0
go.unistack.org/micro-config-env/v4 v4.0.3 go.unistack.org/micro-config-env/v4 v4.0.1
go.unistack.org/micro-config-vault/v4 v4.0.4 go.unistack.org/micro-config-flag/v4 v4.0.4
go.unistack.org/micro-config-vault/v4 v4.0.2
go.unistack.org/micro-meter-victoriametrics/v4 v4.0.1 go.unistack.org/micro-meter-victoriametrics/v4 v4.0.1
go.unistack.org/micro-proto/v4 v4.1.0 go.unistack.org/micro-proto/v4 v4.0.1
go.unistack.org/micro-server-http/v4 v4.0.14 go.unistack.org/micro-server-http/v4 v4.0.13
go.unistack.org/micro/v4 v4.0.19 go.unistack.org/micro/v4 v4.0.18
go.unistack.org/protoc-gen-go-micro/v4 v4.0.13 go.unistack.org/protoc-gen-go-micro/v4 v4.0.7
golang.org/x/mod v0.16.0 golang.org/x/mod v0.14.0
golang.org/x/sync v0.6.0 golang.org/x/sync v0.6.0
golang.org/x/tools v0.19.0 golang.org/x/tools v0.13.0
google.golang.org/protobuf v1.33.0 google.golang.org/protobuf v1.33.0
modernc.org/sqlite v1.29.5 modernc.org/sqlite v1.21.0
) )
require ( require (
github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/silas/dag v0.0.0-20220518035006-a7e85ada93c5 // indirect github.com/silas/dag v0.0.0-20220518035006-a7e85ada93c5 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240311132316-a219d84964c2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
) )
require ( require (
dario.cat/mergo v1.0.0 // indirect dario.cat/mergo v1.0.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/ProtonMail/go-crypto v1.0.0 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 // indirect
github.com/VictoriaMetrics/metrics v1.33.0 // indirect github.com/VictoriaMetrics/metrics v1.24.0 // indirect
github.com/acomagu/bufpipe v1.0.4 // indirect
github.com/cenkalti/backoff/v3 v3.2.2 // indirect github.com/cenkalti/backoff/v3 v3.2.2 // indirect
github.com/cloudflare/circl v1.3.7 // indirect github.com/cloudflare/circl v1.3.3 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/emirpasic/gods v1.18.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect
github.com/fatih/structtag v1.2.0 // indirect github.com/fatih/structtag v1.2.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.5.0 // indirect github.com/go-git/go-billy/v5 v5.4.1 // indirect
github.com/go-jose/go-jose/v3 v3.0.3 // indirect github.com/go-jose/go-jose/v3 v3.0.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/gnostic v0.7.0 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic v0.6.9 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8 // indirect github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 // indirect
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
github.com/hashicorp/go-sockaddr v1.0.6 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/vault/api v1.12.2 // indirect github.com/hashicorp/vault/api v1.9.2 // indirect
github.com/iancoleman/strcase v0.3.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.14.3 // indirect github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530 // indirect
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 // indirect github.com/jackc/pgerrcode v0.0.0-20201024163028-a0d42d470451 // indirect
github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.3 // indirect github.com/jackc/pgproto3/v2 v2.1.1 // indirect
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgtype v1.14.3 // indirect github.com/jackc/pgtype v1.14.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/lyft/protoc-gen-star/v2 v2.0.3 // indirect github.com/lyft/protoc-gen-star/v2 v2.0.3 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect
github.com/sergi/go-diff v1.3.1 // indirect github.com/sergi/go-diff v1.1.0 // indirect
github.com/skeema/knownhosts v1.2.2 // indirect github.com/skeema/knownhosts v1.2.0 // indirect
github.com/spf13/afero v1.10.0 // indirect github.com/spf13/afero v1.10.0 // indirect
github.com/valyala/fastrand v1.1.0 // indirect github.com/valyala/fastrand v1.1.0 // indirect
github.com/valyala/histogram v1.2.0 // indirect github.com/valyala/histogram v1.2.0 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect
go.uber.org/atomic v1.11.0 // indirect go.uber.org/atomic v1.6.0 // indirect
go.unistack.org/micro-config-file/v4 v4.0.3 go.unistack.org/micro-config-file/v4 v4.0.3
golang.org/x/crypto v0.21.0 // indirect golang.org/x/crypto v0.19.0 // indirect
golang.org/x/net v0.22.0 // indirect golang.org/x/net v0.21.0 // indirect
golang.org/x/sys v0.18.0 // indirect golang.org/x/sys v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect golang.org/x/time v0.3.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/libc v1.47.0 // indirect lukechampine.com/uint128 v1.3.0 // indirect
modernc.org/cc/v3 v3.41.0 // indirect
modernc.org/ccgo/v3 v3.16.15 // indirect
modernc.org/libc v1.41.0 // indirect
modernc.org/mathutil v1.6.0 // indirect modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.7.2 // indirect modernc.org/memory v1.7.2 // indirect
modernc.org/opt v0.1.3 // indirect
modernc.org/strutil v1.2.0 // indirect modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect modernc.org/token v1.1.0 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect sigs.k8s.io/yaml v1.3.0 // indirect
) )

1926
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -1,94 +0,0 @@
/*
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package cli
import (
"context"
"fmt"
"os"
"strings"
"git.unistack.org/unistack-org/pkgdash/internal/modules"
"github.com/spf13/cobra"
"go.unistack.org/micro/v4/logger"
"golang.org/x/mod/modfile"
"golang.org/x/mod/semver"
)
// checkupdateCmd represents the checkupdate command
var checkupdateCmd = NewCheckUpdateCommand()
var mvs = make(map[string]modules.Update)
func init() {
rootCmd.AddCommand(checkupdateCmd)
}
func NewCheckUpdateCommand() *cobra.Command {
ctx := context.Background()
cmd := &cobra.Command{
Use: "checkupdate",
Short: "CheckUpdate collects a list of dependencies with the latest updates.",
Long: `CheckUpdate collects a list of dependencies with the latest updates.`,
RunE: func(cmd *cobra.Command, args []string) error {
fmt.Println("checkupdate called")
path := "."
if len(os.Args) > 1 {
path = os.Args[1]
}
name, err := modules.FindModFile(path)
if err != nil {
panic(err)
}
buf, err := os.ReadFile(name)
if err != nil {
panic(err)
}
mfile, err := modfile.Parse(name, buf, nil)
if err != nil {
panic(err)
}
mvs = make(map[string]modules.Update)
updateOptions := modules.UpdateOptions{
Pre: cfg.UpdateOpt.Pre,
Major: cfg.UpdateOpt.Major,
UpMajor: cfg.UpdateOpt.UpMajor,
Cached: cfg.UpdateOpt.Cached,
OnUpdate: func(u modules.Update) {
var modpath string // new mod path with major
if u.Err != nil {
logger.Error(ctx, fmt.Sprintf("%s: failed: %v", u.Module.Path, u.Err))
return
}
modpath = u.Module.Path
v := semver.Major(u.Version)
p := modules.ModPrefix(modpath)
if !strings.HasPrefix(u.Module.Version, v) && v != "v1" && v != "v0" {
switch strings.HasPrefix(u.Module.Path, "gopkg.in") {
case true:
modpath = p + "." + v
case false:
modpath = p + "/" + v
}
}
mvs[modpath] = u
},
}
for _, req := range mfile.Require {
updateOptions.Modules = append(updateOptions.Modules, req.Mod)
}
modules.Updates(updateOptions)
logger.Info(ctx, fmt.Sprintf("Modules get update: /n %s", mvs))
return nil
},
}
return cmd
}

View File

@ -1,74 +0,0 @@
/*
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package cli
import (
"context"
"fmt"
"github.com/spf13/cobra"
)
var deleteCmd = NewDeleteCommand()
type DeleteFlags struct {
all bool
mod string
}
func init() {
rootCmd.AddCommand(deleteCmd)
}
func NewDeleteCommand() *cobra.Command {
var flags DeleteFlags
ctx := context.Background()
cmd := &cobra.Command{
Use: "delete",
Short: "Delete closes the merge requests created with a dependency update.",
Long: `Delete closes the merge requests created with a dependency update.`,
RunE: func(cmd *cobra.Command, args []string) error {
fmt.Println("delete called")
var err error
if gitsource == nil {
return errSourceNil
}
if len(prList) == 0 {
return errPRNotExist
}
if flags.all {
for _, branch := range cfg.Branches {
rMap := prList[branch]
for path, _ := range rMap {
err = gitsource.RequestClose(ctx, branch, path)
if err != nil {
return err
}
}
}
}
if flags.mod != "" {
for _, branch := range cfg.Branches {
err = gitsource.RequestClose(ctx, branch, flags.mod)
if err != nil {
return err
}
}
}
return errFlagsNotExist
},
}
cmd.Flags().BoolVarP(&flags.all, "all", "a", false, "Deletes everything depending")
cmd.Flags().StringVarP(&flags.mod, "mod", "m", "", "Deletes one dependency")
return cmd
}

View File

@ -1,121 +0,0 @@
/*
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package cli
import (
"context"
"fmt"
"path/filepath"
"git.unistack.org/unistack-org/pkgdash/internal/configcli"
"git.unistack.org/unistack-org/pkgdash/internal/source"
"github.com/spf13/cobra"
yamlcodec "go.unistack.org/micro-codec-yaml/v4"
envconfig "go.unistack.org/micro-config-env/v4"
fileconfig "go.unistack.org/micro-config-file/v4"
"go.unistack.org/micro/v4/config"
"go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v4/logger/slog"
"go.unistack.org/micro/v4/options"
)
// initCmd represents the init command
var initCmd = NewInitCommand()
var gitsource = source.SourceControl(nil)
var cfg = configcli.NewConfig()
var (
DefaultPullRequestTitle = `Bump {{.Name}} from {{.VersionOld}} to {{.VersionNew}}`
DefaultPullRequestBody = `Bumps {{.Name}} from {{.VersionOld}} to {{.VersionNew}}`
)
var (
configFiles = []string{
"dependabot.yml",
"pkgdashcli.yml",
"pkgdashcli.yaml",
}
configDirs = []string{
".gitea",
".github",
".gitlab",
}
)
func init() {
rootCmd.AddCommand(initCmd)
}
func NewInitCommand() *cobra.Command {
ctx := context.Background()
logger.DefaultLogger = slog.NewLogger()
if err := logger.DefaultLogger.Init(logger.WithCallerSkipCount(3), logger.WithLevel(logger.DebugLevel)); err != nil {
logger.Error(ctx, fmt.Sprintf("logger init error: %v", err))
}
cmd := &cobra.Command{
Use: "init",
Short: "Init fills the config with data from the configuration file.",
Long: `Init fills the config with data from the configuration file.`,
RunE: func(cmd *cobra.Command, args []string) error {
fmt.Println("init called")
var err error
if err = config.Load(ctx,
[]config.Config{
config.NewConfig(
config.Struct(cfg),
),
envconfig.NewConfig(
config.Struct(cfg),
),
},
config.LoadOverride(true),
); err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to load config: %v", err))
}
for _, configDir := range configDirs {
for _, configFile := range configFiles {
logger.Info(ctx, fmt.Sprintf("path: %s", filepath.Join(configDir, configFile)))
c := fileconfig.NewConfig(
config.AllowFail(false),
config.Struct(cfg),
options.Codec(yamlcodec.NewCodec()),
fileconfig.Path(".gitea/pkgdashcli.yaml"),
)
err = c.Init()
if err != nil {
logger.Error(ctx, fmt.Sprintf("failed to init config: %v", err))
return err
}
if err = c.Load(ctx, config.LoadOverride(true)); err != nil {
logger.Error(ctx, fmt.Sprintf("failed to load config: %v", err))
return err
}
}
}
logger.Info(ctx, fmt.Sprintf("Load config... %s", cfg.Source.Repository))
if cfg.PullRequestBody == "" {
cfg.PullRequestBody = DefaultPullRequestBody
}
if cfg.PullRequestTitle == "" {
cfg.PullRequestTitle = DefaultPullRequestTitle
}
gitsource = source.NewSourceControl(*cfg)
return nil
},
}
return cmd
}

View File

@ -1,73 +0,0 @@
/*
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package cli
import (
"context"
"fmt"
"github.com/spf13/cobra"
"go.unistack.org/micro/v4/logger"
)
// updateCmd represents the update command
var listCmd = NewListCommand()
var prList = map[string]map[string]string{}
/* [
"master":
[
"go.unistack.org/micro/v4" : "Bump go.unistack.org/micro/v4 from v4.0.0 to v4.0.1",
"go.unistack.org/micro-client-http/v4":"Bump go.unistack.org/micro-client-http/v4 from v4.0.0 to v4.0.2",
],
"v3":
[
"go.unistack.org/micro/v3" : "Bump go.unistack.org/micro/v4 from v3.0.0 to v3.0.1",
],
] */
func init() {
rootCmd.AddCommand(listCmd)
}
func NewListCommand() *cobra.Command {
ctx := context.Background()
logger.Info(ctx, "RequestList start")
cmd := &cobra.Command{
Use: "list",
Short: "Update allows you to start the process of creating a PR in the repository",
Long: `
Update allows you to start the process of creating a PR in the repository.
Use the -a flag to update all dependencies or -m flag a specific module.
`,
RunE: func(cmd *cobra.Command, args []string) error {
if gitsource == nil {
return errSourceNil
}
if cfg == nil {
return errCfgNil
}
prList = make(map[string]map[string]string)
for _, branch := range cfg.Branches {
rMap, err := gitsource.RequestList(ctx, branch)
if err != nil {
return err
}
prList[branch] = rMap
logger.Info(ctx, fmt.Sprintf("for %s:\n%s", branch, rMap))
}
return nil
},
}
return cmd
}

View File

@ -1,42 +0,0 @@
/*
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package cli
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
var (
errUpdateNotExist = fmt.Errorf("mod not in list of update. Call init")
errFlagsNotExist = fmt.Errorf("empty flags")
errSourceNil = fmt.Errorf("source nil. Call init")
errCfgNil = fmt.Errorf("cfg nil. Call init")
errPRNotExist = fmt.Errorf("pr not exist. Call list")
)
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "pkgdashcli <command> [flags]",
Short: "Pkgdashcli application to update dependencies.",
Long: `Pkgdashcli allows you to define a version update for a dependency and start merge requests in version control systems.`,
// Uncomment the following line if your bare application
// has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { },
}
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
func init() {
}

View File

@ -1,95 +0,0 @@
/*
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package cli
import (
"context"
"fmt"
"github.com/spf13/cobra"
"go.unistack.org/micro/v4/logger"
)
var updateCmd = NewUpdateCommand()
type UpdateFlags struct {
all bool
mod string
}
func init() {
rootCmd.AddCommand(updateCmd)
}
func NewUpdateCommand() *cobra.Command {
var flags UpdateFlags
ctx := context.Background()
cmd := &cobra.Command{
Use: "update",
Short: "Update allows you to start the process of creating a PR in the repository",
Long: `
Update allows you to start the process of creating a PR in the repository.
Use the -a flag to update all dependencies or -m flag a specific module.
`,
RunE: func(cmd *cobra.Command, args []string) error {
var err error
if gitsource == nil {
return errSourceNil
}
if len(mvs) == 0 {
return errUpdateNotExist
}
if flags.all {
logger.Info(ctx, "update all")
for pathMod, m := range mvs {
for _, branch := range cfg.Branches {
logger.Info(ctx, fmt.Sprintf("update mod: %s", m))
if err = gitsource.RequestOpen(ctx, branch, pathMod, m); err != nil {
logger.Error(ctx, fmt.Sprintf("PR open error: %s, base branch: %s", pathMod, branch))
return err
}
logger.Info(ctx, fmt.Sprintf("Successful update mod: %s", pathMod))
}
delete(mvs, pathMod) // todo возможно чисть не стоит и нужно просто пропускать
}
return nil
}
if flags.mod != "" {
for _, branch := range cfg.Branches {
logger.Info(ctx, fmt.Sprintf("update mod: %s", flags.mod))
if _, ok := mvs[flags.mod]; !ok {
return errUpdateNotExist
}
if err = gitsource.RequestOpen(ctx, branch, flags.mod, mvs[flags.mod]); err != nil {
logger.Error(ctx, fmt.Sprintf("PR open error: %s, base branch: %s", flags.mod, branch))
return err
}
logger.Info(ctx, fmt.Sprintf("Successful update mod: %s", flags.mod))
}
delete(mvs, flags.mod)
return nil
}
return errFlagsNotExist
},
}
cmd.Flags().BoolVarP(&flags.all, "all", "a", false, "Updates everything depending")
cmd.Flags().StringVarP(&flags.mod, "mod", "m", "", "Update one dependency")
return cmd
}

View File

@ -9,11 +9,11 @@ type Config struct {
} }
type Source struct { type Source struct {
TypeGit string `json:"type" yaml:"type"` TypeGit string `json:"type" yaml:"type" env:"GIT_TYPE"`
Token string `json:"token" yaml:"token"` Token string `json:"token" yaml:"token" env:"GIT_TOKEN"`
APIURL string `json:"apiurl" yaml:"apiurl"` APIURL string `json:"apiurl" yaml:"apiurl" env:"GIT_API"`
Repository string `json:"repository" yaml:"repository"` Repository string `json:"repository" yaml:"repository" env:"GIT_REPO"`
Owner string `json:"owner" yaml:"owner"` Owner string `json:"owner" yaml:"owner" env:"GIT_OWNER"`
} }
type UpdateOpt struct { type UpdateOpt struct {
@ -23,8 +23,14 @@ type UpdateOpt struct {
Cached bool `json:"cached" yaml:"cached" default:"true"` Cached bool `json:"cached" yaml:"cached" default:"true"`
} }
type Cli struct {
Command string `flag:"name=command,desc='choice command(update, close, checkupdaue, list)',default=''"`
Path string `flag:"name=path,desc='title of mod',default=''"`
}
func NewConfig() *Config { func NewConfig() *Config {
return &Config{ return &Config{
Source: &Source{}, Source: &Source{},
UpdateOpt: &UpdateOpt{},
} }
} }

View File

@ -80,7 +80,7 @@ func ParseDSN(cfg *appconfig.DatabaseConfig) error {
case "sqlite", "sqlite3": case "sqlite", "sqlite3":
u.Scheme = "sqlite" u.Scheme = "sqlite"
default: default:
return fmt.Errorf("unknown database %s", u.Scheme) return fmt.Error("unknown database %s", u.Scheme)
} }
cfg.Type = u.Scheme cfg.Type = u.Scheme
@ -104,7 +104,7 @@ func connect(ctx context.Context, cfg *appconfig.DatabaseConfig, log logger.Logg
db, err = connectSqlite(ctx, cfg.ConnStr) db, err = connectSqlite(ctx, cfg.ConnStr)
cfg.Type = "sqlite" cfg.Type = "sqlite"
default: default:
return nil, fmt.Errorf("unknown database type %s", cfg.Type) return nil, fmt.Error("unknown database type %s", cfg.Type)
} }
if err != nil { if err != nil {

View File

@ -8,7 +8,6 @@ import (
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"os"
"os/exec" "os/exec"
"regexp" "regexp"
"strings" "strings"
@ -34,12 +33,13 @@ type Gitea struct {
PRBody string PRBody string
Repository string Repository string
Owner string Owner string
pulls []*giteaPull
} }
func NewGitea(cfg configcli.Config) *Gitea { func NewGitea(cfg configcli.Config) *Gitea {
return &Gitea{ return &Gitea{
URL: cfg.Source.APIURL, URL: cfg.Source.APIURL,
Token: os.Getenv("gitea_token"), Token: cfg.Source.Token,
PRTitle: cfg.PullRequestTitle, PRTitle: cfg.PullRequestTitle,
PRBody: cfg.PullRequestBody, PRBody: cfg.PullRequestBody,
Repository: cfg.Source.Repository, Repository: cfg.Source.Repository,
@ -59,8 +59,12 @@ type giteaPull struct {
ID int64 `json:"id"` ID int64 `json:"id"`
} }
func (g *Gitea) Name() string {
return "gitea"
}
func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod modules.Update) error { func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod modules.Update) error {
logger.Debug(ctx, fmt.Sprintf("RequestOpen start, mod title: %s", path)) logger.Debugf(ctx, fmt.Sprintf("RequestOpen start, mod title: %s", path))
var buf []byte var buf []byte
var err error var err error
@ -97,16 +101,16 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
if err != nil { if err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to open repo: %v", err)) logger.Fatal(ctx, fmt.Sprintf("failed to open repo: %v", err))
} }
// извлекаем ссылки с объектами из удаленного объекта?? //извлекаем ссылки с объектами из удаленного объекта??
if err = repo.FetchContext(ctx, &git.FetchOptions{ if err = repo.FetchContext(ctx, &git.FetchOptions{
Auth: &httpauth.BasicAuth{Username: g.Token, Password: g.Token}, Auth: &httpauth.BasicAuth{Username: g.Token, Password: g.Token},
Force: true, Force: true,
}); err != nil && err != git.NoErrAlreadyUpToDate { }); err != nil && err != git.NoErrAlreadyUpToDate {
logger.Fatal(ctx, fmt.Sprintf("failed to fetch repo: %v", err)) logger.Fatal(ctx, fmt.Sprintf("failed to fetch repo: %v", err))
} // обновляем репозиторий } //обновляем репозиторий
var headRef *plumbing.Reference // вроде ссылка на гит var headRef *plumbing.Reference // вроде ссылка на гит
refIter, err := repo.Branches() // получение веток refIter, err := repo.Branches() //получение веток
if err != nil { if err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to get branches: %v", err)) logger.Fatal(ctx, fmt.Sprintf("failed to get branches: %v", err))
return err return err
@ -116,11 +120,11 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
if err != nil { if err != nil {
break break
} }
if strings.Contains(ref.Name().String(), branch) { // todo вот тут возможно нужно переделать if ref.Name().Short() == branch { //todo вот тут возможно нужно переделать
headRef = ref headRef = ref
break break
} }
} // перебираем получение ветки и когда находим нужную выходим из цикла записав ветку в headRef } //перебираем получение ветки и когда находим нужную выходим из цикла записав ветку в headRef
refIter.Close() refIter.Close()
if headRef == nil { if headRef == nil {
@ -130,19 +134,18 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
logger.Info(ctx, fmt.Sprintf("repo head %s", headRef)) logger.Info(ctx, fmt.Sprintf("repo head %s", headRef))
wtree, err := repo.Worktree() // todo вроде рабочее дерево не нужно wtree, err := repo.Worktree() //todo вроде рабочее дерево не нужно
if err != nil { if err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to get worktree: %v", err)) logger.Fatal(ctx, fmt.Sprintf("failed to get worktree: %v", err))
} }
pulls, err := GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Token) g.pulls, err = GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Token)
if err != nil && err != ErrPRNotExist { if err != nil && err != ErrPRNotExist {
logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err)) logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err))
return err return err
} }
for _, pull := range pulls { for _, pull := range g.pulls {
logger.Debug(ctx, fmt.Sprintf("PULL title - %s | ref - %s", pull.Title, pull.Base.Ref))
if strings.Contains(pull.Title, path) && strings.Contains(pull.Base.Ref, branch) { if strings.Contains(pull.Title, path) && strings.Contains(pull.Base.Ref, branch) {
logger.Info(ctx, fmt.Sprintf("PR for %s exists %s, call RequestUpdate", path, pull.URL)) logger.Info(ctx, fmt.Sprintf("PR for %s exists %s, call RequestUpdate", path, pull.URL))
return g.RequestUpdate(ctx, branch, path, mod) return g.RequestUpdate(ctx, branch, path, mod)
@ -154,7 +157,7 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
logger.Info(ctx, "reset worktree") logger.Info(ctx, "reset worktree")
if err = wtree.Reset(&git.ResetOptions{Mode: git.HardReset}); err != nil { if err = wtree.Reset(&git.ResetOptions{Mode: git.HardReset}); err != nil {
logger.Error(ctx, fmt.Sprintf("failed to reset repo branch: %v", err)) logger.Error(ctx, fmt.Sprintf("failed to reset repo branch: %v", err))
} // вроде меняем ветку todo вроде можно удалить } //вроде меняем ветку todo вроде можно удалить
if err = wtree.PullContext(ctx, &git.PullOptions{ if err = wtree.PullContext(ctx, &git.PullOptions{
Auth: &httpauth.BasicAuth{Username: g.Token, Password: g.Token}, Auth: &httpauth.BasicAuth{Username: g.Token, Password: g.Token},
@ -163,7 +166,7 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
Force: true, Force: true,
RemoteName: "origin", RemoteName: "origin",
}); err != nil && err != git.NoErrAlreadyUpToDate { }); err != nil && err != git.NoErrAlreadyUpToDate {
logger.Error(ctx, fmt.Sprintf("failed to pull repo: %v", err)) // подтягиваем изменения с удаленого репозитория logger.Error(ctx, fmt.Sprintf("failed to pull repo: %v", err)) //подтягиваем изменения с удаленого репозитория
} }
logger.Info(ctx, fmt.Sprintf("checkout ref %s", headRef)) logger.Info(ctx, fmt.Sprintf("checkout ref %s", headRef))
@ -175,7 +178,7 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
}); err != nil { }); err != nil {
logger.Error(ctx, fmt.Sprintf("failed to checkout tree: %v", err)) logger.Error(ctx, fmt.Sprintf("failed to checkout tree: %v", err))
return err return err
} // создаем новую ветку } //создаем новую ветку
epath, err := exec.LookPath("go") epath, err := exec.LookPath("go")
if errors.Is(err, exec.ErrDot) { if errors.Is(err, exec.ErrDot) {
@ -226,7 +229,7 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
logger.Fatal(ctx, fmt.Sprintf("failed to commit: %v", err)) logger.Fatal(ctx, fmt.Sprintf("failed to commit: %v", err))
} }
refspec := gitconfig.RefSpec(fmt.Sprintf("+refs/heads/pkgdash/go_modules/%s-%s:refs/heads/pkgdash/go_modules/%s-%s", path, mod.Version, path, mod.Version)) // todo как будто нужно переделать refspec := gitconfig.RefSpec(fmt.Sprintf("+refs/heads/pkgdash/go_modules/%s-%s:refs/heads/pkgdash/go_modules/%s-%s", path, mod.Version, path, mod.Version)) //todo как будто нужно переделать
logger.Info(ctx, fmt.Sprintf("try to push refspec %s", refspec)) logger.Info(ctx, fmt.Sprintf("try to push refspec %s", refspec))
@ -256,7 +259,7 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
req, err := http.NewRequestWithContext( req, err := http.NewRequestWithContext(
ctx, ctx,
http.MethodPost, http.MethodPost,
fmt.Sprintf("%s/repos/%s/%s/pulls?token=%s", g.URL, g.Owner, g.Repository, g.Token), fmt.Sprintf("https://%s/api/v1/repos/%s/%s/pulls?token=%s", g.URL, g.Owner, g.Repository, g.Token),
bytes.NewReader(buf), bytes.NewReader(buf),
) )
if err != nil { if err != nil {
@ -268,7 +271,7 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
rsp, err := http.DefaultClient.Do(req) rsp, err := http.DefaultClient.Do(req)
if err != nil { if err != nil {
return err return err
} // Вроде создаем новый реквест на создание пулл реквеста } //Вроде создаем новый реквест на создание пулл реквеста
if rsp.StatusCode != http.StatusCreated { if rsp.StatusCode != http.StatusCreated {
buf, _ = io.ReadAll(rsp.Body) buf, _ = io.ReadAll(rsp.Body)
return fmt.Errorf("unknown error: %s", buf) return fmt.Errorf("unknown error: %s", buf)
@ -276,11 +279,16 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
logger.Info(ctx, fmt.Sprintf("PR create for %s-%s", path, mod.Version)) logger.Info(ctx, fmt.Sprintf("PR create for %s-%s", path, mod.Version))
repo, err = git.PlainOpenWithOptions(".", &git.PlainOpenOptions{DetectDotGit: true})
if err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to open repo: %v", err))
}
return nil return nil
} }
func (g *Gitea) RequestClose(ctx context.Context, branch string, path string) error { func (g *Gitea) RequestClose(ctx context.Context, branch string, path string) error {
logger.Debug(ctx, fmt.Sprintf("RequestClose start, mod title: %s", path)) logger.Debugf(ctx, fmt.Sprintf("RequestClose start, mod title: %s", path))
pulls, err := GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Token) pulls, err := GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Token)
if err != nil { if err != nil {
@ -309,7 +317,7 @@ func (g *Gitea) RequestClose(ctx context.Context, branch string, path string) er
} }
rsp, err := http.DefaultClient.Do(req) rsp, err := http.DefaultClient.Do(req)
if err != nil { if err != nil {
logger.Error(ctx, fmt.Sprintf("failed to do request for delete the branch: %s, err: %s, code: %s", branch, err, rsp.StatusCode)) logger.Error(ctx, fmt.Sprintf("failed to do request for delete the branch: %s, err: %s, code: %v", branch, err, rsp.StatusCode))
return err return err
} }
@ -318,19 +326,22 @@ func (g *Gitea) RequestClose(ctx context.Context, branch string, path string) er
} }
func (g *Gitea) RequestUpdate(ctx context.Context, branch string, path string, mod modules.Update) error { func (g *Gitea) RequestUpdate(ctx context.Context, branch string, path string, mod modules.Update) error {
logger.Debug(ctx, fmt.Sprintf("RequestUpdate start, mod title: %s", path)) logger.Debugf(ctx, fmt.Sprintf("RequestUpdate start, mod title: %s", path))
var err error
pulls, err := GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Token) if len(g.pulls) == 0 {
if err != nil { g.pulls, err = GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Token)
logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err)) if err != nil {
return err logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err))
return err
}
} }
prExist := false prExist := false
for _, pull := range pulls { for _, pull := range g.pulls {
if strings.Contains(pull.Title, path) && pull.Base.Ref == branch { if strings.Contains(pull.Title, path) && pull.Base.Ref == branch {
logger.Info(ctx, fmt.Sprintf("don't skip %s since pr exist %s", path, pull.URL)) // todo logger.Info(ctx, fmt.Sprintf("don't skip %s since pr exist %s", path, pull.URL)) //todo
tVersion := getVersions(pull.Head.Ref) // Надо взять просто из названия ветки последнюю версию tVersion := getVersions(pull.Head.Ref) //Надо взять просто из названия ветки последнюю версию
if modules.IsNewerVersion(tVersion, mod.Version, false) { if modules.IsNewerVersion(tVersion, mod.Version, false) {
reqDel, err := DeleteBranch(ctx, g.URL, g.Owner, g.Repository, pull.Head.Ref, g.Token) reqDel, err := DeleteBranch(ctx, g.URL, g.Owner, g.Repository, pull.Head.Ref, g.Token)
if err != nil { if err != nil {
@ -340,10 +351,11 @@ func (g *Gitea) RequestUpdate(ctx context.Context, branch string, path string, m
rsp, err := http.DefaultClient.Do(reqDel) rsp, err := http.DefaultClient.Do(reqDel)
if err != nil { if err != nil {
logger.Error(ctx, fmt.Sprintf("Error with do request for branch: %s, err: %s, code: %v", branch, err, rsp.StatusCode)) logger.Error(ctx, fmt.Sprintf("Error with do request for branch: %s, err: %s, code: %v", branch, err, rsp.StatusCode))
continue // думаю что если не можем удалить ветку не стоит заканчивать работу, а перейти к следующей итерации continue //думаю что если не можем удалить ветку не стоит заканчивать работу, а перейти к следующей итерации
} }
logger.Info(ctx, fmt.Sprintf("Old pr %s successful delete", pull.Head.Ref)) logger.Info(ctx, fmt.Sprintf("Old pr %s successful delete", pull.Head.Ref))
} else { } else {
logger.Debugf(ctx, "The existing PR is relevant")
return nil return nil
} }
prExist = true prExist = true
@ -360,7 +372,7 @@ func (g *Gitea) RequestUpdate(ctx context.Context, branch string, path string, m
} }
func (g *Gitea) RequestList(ctx context.Context, branch string) (map[string]string, error) { func (g *Gitea) RequestList(ctx context.Context, branch string) (map[string]string, error) {
logger.Debug(ctx, fmt.Sprintf("RequestList for %s", branch)) logger.Debugf(ctx, fmt.Sprintf("RequestList for %s", branch))
gPulls, err := GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Token) gPulls, err := GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Token)
if err != nil { if err != nil {
@ -371,7 +383,10 @@ func (g *Gitea) RequestList(ctx context.Context, branch string) (map[string]stri
rMap := make(map[string]string) rMap := make(map[string]string)
for _, pull := range gPulls { for _, pull := range gPulls {
path = strings.Split(pull.Title, " ")[1] // todo Работет только для дефолтного шаблона if !strings.HasPrefix(pull.Title, "Bump ") { //добавляем только реквесты бота по обновлению модулей
continue
}
path = strings.Split(pull.Title, " ")[1] //todo Работет только для дефолтного шаблона
rMap[path] = pull.Title rMap[path] = pull.Title
} }
@ -388,7 +403,7 @@ func getVersions(s string) string {
func DeleteBranch(ctx context.Context, url, owner, repo, branch, token string) (*http.Request, error) { func DeleteBranch(ctx context.Context, url, owner, repo, branch, token string) (*http.Request, error) {
var buf []byte var buf []byte
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, fmt.Sprintf("%s/repos/%s/%s/branches/%s?token=%s", url, owner, repo, branch, token), bytes.NewReader(buf)) req, err := http.NewRequestWithContext(ctx, http.MethodDelete, fmt.Sprintf("https://%s/api/v1/repos/%s/%s/branches/%s?token=%s", url, owner, repo, branch, token), bytes.NewReader(buf))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -398,39 +413,48 @@ func DeleteBranch(ctx context.Context, url, owner, repo, branch, token string) (
} }
func GetPulls(ctx context.Context, url, owner, repo, token string) ([]*giteaPull, error) { func GetPulls(ctx context.Context, url, owner, repo, token string) ([]*giteaPull, error) {
var pulls []*giteaPull var pullsAll, pulls []*giteaPull
var err error page := 1
req, err := http.NewRequestWithContext( for {
ctx, req, err := http.NewRequestWithContext(
http.MethodGet, ctx,
fmt.Sprintf("%s/repos/%s/%s/pulls?state=open&token=%s", url, owner, repo, token), http.MethodGet,
nil) fmt.Sprintf("https://%s/api/v1//repos/%s/%s/pulls?state=open&page=%v&token=%s", url, owner, repo, page, token),
if err != nil { nil)
return nil, err if err != nil {
} // вроде запроса к репозиторию return nil, err
} //вроде запроса к репозиторию
req.Header.Add("Accept", "application/json") req.Header.Add("Accept", "application/json")
req.Header.Add("Content-Type", "application/json") req.Header.Add("Content-Type", "application/json")
rsp, err := http.DefaultClient.Do(req) // выполнение запроса rsp, err := http.DefaultClient.Do(req) // выполнение запроса
if err != nil { if err != nil {
return nil, err
}
buf, _ := io.ReadAll(rsp.Body)
switch rsp.StatusCode {
case http.StatusOK:
if err = json.Unmarshal(buf, &pulls); err != nil {
logger.Error(ctx, fmt.Sprintf("failed to decode response %s err: %v", buf, err))
return nil, err return nil, err
} }
return pulls, nil
case http.StatusNotFound: buf, _ := io.ReadAll(rsp.Body)
logger.Info(ctx, "PL is not exist for %s", repo)
return nil, ErrPRNotExist switch rsp.StatusCode {
default: case http.StatusOK:
return nil, fmt.Errorf("unknown error: %s", buf) if err = json.Unmarshal(buf, &pulls); err != nil {
logger.Error(ctx, fmt.Sprintf("failed to decode response %s err: %v", buf, err))
return nil, err
}
pullsAll = append(pullsAll, pulls...)
page++
case http.StatusNotFound:
logger.Info(ctx, "PL is not exist for %s", repo)
return nil, ErrPRNotExist
default:
return nil, fmt.Errorf("unknown error: %s", buf)
}
if len(pulls) == 0 {
break
}
} }
return pullsAll, nil
} }

View File

@ -2,6 +2,7 @@ package github
import ( import (
"context" "context"
"fmt"
"git.unistack.org/unistack-org/pkgdash/internal/configcli" "git.unistack.org/unistack-org/pkgdash/internal/configcli"
"git.unistack.org/unistack-org/pkgdash/internal/modules" "git.unistack.org/unistack-org/pkgdash/internal/modules"
@ -17,15 +18,19 @@ func NewGithub(cfg configcli.Config) *Github {
} }
} }
func (g *Github) Name() string {
return "github"
}
func (g *Github) RequestOpen(ctx context.Context, branch string, path string, mod modules.Update) error { func (g *Github) RequestOpen(ctx context.Context, branch string, path string, mod modules.Update) error {
return nil return fmt.Errorf("implement me")
} }
func (g *Github) RequestClose(ctx context.Context, branch string, path string) error { func (g *Github) RequestClose(ctx context.Context, branch string, path string) error {
return nil return fmt.Errorf("implement me")
} }
func (g *Github) RequestUpdate(ctx context.Context, branch string, path string, mod modules.Update) error { func (g *Github) RequestUpdate(ctx context.Context, branch string, path string, mod modules.Update) error {
return nil return fmt.Errorf("implement me")
} }
func (g *Github) RequestList(ctx context.Context, branch string) (map[string]string, error) { func (g *Github) RequestList(ctx context.Context, branch string) (map[string]string, error) {
return nil, nil return nil, fmt.Errorf("implement me")
} }

View File

@ -2,6 +2,7 @@ package gitlab
import ( import (
"context" "context"
"fmt"
"git.unistack.org/unistack-org/pkgdash/internal/configcli" "git.unistack.org/unistack-org/pkgdash/internal/configcli"
"git.unistack.org/unistack-org/pkgdash/internal/modules" "git.unistack.org/unistack-org/pkgdash/internal/modules"
@ -17,15 +18,19 @@ func NewGitlab(cfg configcli.Config) *Gitlab {
} }
} }
func (g *Gitlab) Name() string {
return "gitlab"
}
func (g *Gitlab) RequestOpen(ctx context.Context, branch string, path string, mod modules.Update) error { func (g *Gitlab) RequestOpen(ctx context.Context, branch string, path string, mod modules.Update) error {
return nil return fmt.Errorf("implement me")
} }
func (g *Gitlab) RequestClose(ctx context.Context, branch string, path string) error { func (g *Gitlab) RequestClose(ctx context.Context, branch string, path string) error {
return nil return fmt.Errorf("implement me")
} }
func (g *Gitlab) RequestUpdate(ctx context.Context, branch string, path string, mod modules.Update) error { func (g *Gitlab) RequestUpdate(ctx context.Context, branch string, path string, mod modules.Update) error {
return nil return fmt.Errorf("implement me")
} }
func (g *Gitlab) RequestList(ctx context.Context, branch string) (map[string]string, error) { func (g *Gitlab) RequestList(ctx context.Context, branch string) (map[string]string, error) {
return nil, nil return nil, fmt.Errorf("implement me")
} }

View File

@ -2,6 +2,7 @@ package gogs
import ( import (
"context" "context"
"fmt"
"git.unistack.org/unistack-org/pkgdash/internal/configcli" "git.unistack.org/unistack-org/pkgdash/internal/configcli"
"git.unistack.org/unistack-org/pkgdash/internal/modules" "git.unistack.org/unistack-org/pkgdash/internal/modules"
@ -17,15 +18,19 @@ func NewGogs(cfg configcli.Config) *Gogs {
} }
} }
func (g *Gogs) Name() string {
return "gogs"
}
func (g *Gogs) RequestOpen(ctx context.Context, branch string, path string, mod modules.Update) error { func (g *Gogs) RequestOpen(ctx context.Context, branch string, path string, mod modules.Update) error {
return nil return fmt.Errorf("implement me")
} }
func (g *Gogs) RequestClose(ctx context.Context, branch string, path string) error { func (g *Gogs) RequestClose(ctx context.Context, branch string, path string) error {
return nil return fmt.Errorf("implement me")
} }
func (g *Gogs) RequestUpdate(ctx context.Context, branch string, path string, mod modules.Update) error { func (g *Gogs) RequestUpdate(ctx context.Context, branch string, path string, mod modules.Update) error {
return nil return fmt.Errorf("implement me")
} }
func (g *Gogs) RequestList(ctx context.Context, branch string) (map[string]string, error) { func (g *Gogs) RequestList(ctx context.Context, branch string) (map[string]string, error) {
return nil, nil return nil, fmt.Errorf("implement me")
} }

View File

@ -12,6 +12,7 @@ import (
) )
type SourceControl interface { type SourceControl interface {
Name() string
RequestOpen(ctx context.Context, branch string, path string, mod modules.Update) error RequestOpen(ctx context.Context, branch string, path string, mod modules.Update) error
RequestClose(ctx context.Context, branch string, path string) error RequestClose(ctx context.Context, branch string, path string) error
RequestUpdate(ctx context.Context, branch string, path string, mod modules.Update) error RequestUpdate(ctx context.Context, branch string, path string, mod modules.Update) error

View File

@ -64,11 +64,11 @@ func (s *Sqlite) PackageModulesCreate(ctx context.Context, pkg *models.Package,
} }
func (s *Sqlite) PackageDelete(ctx context.Context, req *pb.PackageDeleteReq) error { func (s *Sqlite) PackageDelete(ctx context.Context, req *pb.PackageDeleteReq) error {
return fmt.Errorf("need implement") return fmt.Error("need implement")
} }
func (s *Sqlite) PackageUpdate(ctx context.Context, req *pb.PackageUpdateReq) (*models.Package, error) { func (s *Sqlite) PackageUpdate(ctx context.Context, req *pb.PackageUpdateReq) (*models.Package, error) {
return nil, fmt.Errorf("need implement") return nil, fmt.Error("need implement")
} }
func (s *Sqlite) PackageLookup(ctx context.Context, req *pb.PackageLookupReq) (*models.Package, error) { func (s *Sqlite) PackageLookup(ctx context.Context, req *pb.PackageLookupReq) (*models.Package, error) {

View File

@ -107,12 +107,12 @@ func parseModFile(ctx context.Context, store storage.Storage, pkg *models.Packag
ref, err := repo.Head() ref, err := repo.Head()
if err != nil { if err != nil {
return fmt.Errorf("failed to get head: %v", err) return fmt.Error("failed to get head: %v", err)
} }
commit, err := repo.CommitObject(ref.Hash()) commit, err := repo.CommitObject(ref.Hash())
if err != nil { if err != nil {
return fmt.Errorf("failed to get commit: %v", err) return fmt.Error("failed to get commit: %v", err)
} }
tree, err := commit.Tree() tree, err := commit.Tree()