Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:ojkastl_buildservice:Branch_devel_tools_scm
scm-manager-cli
scm-manager-cli-1.0.1.obscpio
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File scm-manager-cli-1.0.1.obscpio of Package scm-manager-cli
07070100000000000081A400000000000000000000000162D515C00000010E000000000000000000000000000000000000002400000000scm-manager-cli-1.0.1/.editorconfig# EditorConfig is awesome: https://EditorConfig.org # top-most EditorConfig file root = true # Match golang fmt [*] charset = utf-8 end_of_line = lf insert_final_newline = true indent_style = tab indent_size = 4 [{*.yml, *.yaml}] indent_style = space indent_size = 2 07070100000001000081A400000000000000000000000162D515C0000000E0000000000000000000000000000000000000002100000000scm-manager-cli-1.0.1/.gitignore# Default ignored files /shelf/ /.idea/workspace.xml # Editor-based HTTP Client requests /httpRequests/ # Datasource local storage ignored files /dataSources/ /dataSources.local.xml scm scm.exe .cache/ .gnupg/ .idea dist/ 07070100000002000081A400000000000000000000000162D515C000000D12000000000000000000000000000000000000002700000000scm-manager-cli-1.0.1/.goreleaser.yaml# This is an example .goreleaser.yml file with some sensible defaults. # Make sure to check the documentation at https://goreleaser.com project_name: scm release: disable: true before: hooks: # You may remove this if you don't use go modules. - go mod tidy # you may remove this if you don't need go generate - go generate ./... builds: - env: - CGO_ENABLED=0 goos: - linux - windows - darwin - freebsd goarch: - amd64 - arm64 ldflags: - -w -s - -X github.com/scm-manager/cli/pkg.version={{.Version}} - -X github.com/scm-manager/cli/pkg.commitHash={{.Commit}} - -X github.com/scm-manager/cli/pkg.buildTime={{.Date}} archives: - id: archives name_template: "{{ .ProjectName }}-cli_{{ .Version }}_{{ .Os }}_{{ .Arch }}" replacements: darwin: Darwin linux: Linux windows: Windows 386: i386 amd64: x86_64 format_overrides: - goos: windows format: zip snapshot: name_template: "{{ incpatch .Version }}-SNAPSHOT" changelog: skip: true nfpms: - id: rpm package_name: scm-cli vendor: Cloudogu GmbH # TODO CLI subpage homepage: https://scm-manager.org maintainer: SCM Team <scm-team@cloudogu.com> description: SCM-Manager CLI Client license: MIT formats: - rpm bindir: /usr/bin priority: extra section: devel rpm: group: Development/Tools signature: key_file: '{{ .Env.GPG_KEY_PATH }}' - id: deb package_name: scm-cli vendor: Cloudogu GmbH homepage: https://scm-manager.org/cli maintainer: SCM Team <scm-team@cloudogu.com> description: SCM-Manager CLI Client license: MIT formats: - deb bindir: /usr/bin priority: extra section: devel deb: signature: key_file: '{{ .Env.GPG_KEY_PATH }}' brews: - name: scm-cli tap: owner: scm-manager name: homebrew-tap branch: master url_template: https://packages.scm-manager.org/repository/scm-cli-releases/{{.Tag}}/{{.ArtifactName}} homepage: https://scm-manager.org/cli description: SCM-Manager CLI Client license: MIT skip_upload: true scoop: name: scm-cli url_template: https://packages.scm-manager.org/repository/scm-cli-releases/{{.Tag}}/{{.ArtifactName}} bucket: owner: scm-manager name: scoop-bucket branch: main homepage: https://scm-manager.org/cli description: SCM-Manager CLI Client license: MIT skip_upload: true uploads: - name: default ids: - archives mode: archive checksum: true method: PUT target: https://packages.scm-manager.org/repository/scm-cli-releases/{{.Version}} - name: rpm ids: - rpm mode: archive method: PUT target: https://packages.scm-manager.org/repository/yum-v2-releases/ - name: deb ids: - deb mode: archive method: POST custom_artifact_name: true target: https://packages.scm-manager.org/repository/apt-v2-releases/ checksum: name_template: 'checksums.txt' ids: - archives signs: - artifacts: checksum args: - --batch - --pinentry-mode - loopback - --passphrase - "{{ .Env.GPG_PASSWORD }}" - --yes - --armor - --output - "${signature}" - "--detach-sign" - "${artifact}" 07070100000003000081A400000000000000000000000162D515C000000181000000000000000000000000000000000000002300000000scm-manager-cli-1.0.1/CHANGELOG.md# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## 1.0.1 - 2022-07-18 ### Fixed - Improve error messages - Scoop bucket directory ## 1.0.0 - 2022-04-29 ### Added - Initial release 07070100000004000081A400000000000000000000000162D515C00000130A000000000000000000000000000000000000002200000000scm-manager-cli-1.0.1/Jenkinsfile#!groovy pipeline { options { buildDiscarder(logRotator(numToKeepStr: '10')) disableConcurrentBuilds() } agent { node { label 'docker' } } environment { HOME = "${env.WORKSPACE}" LANGUAGE = "en" } stages { stage('Set Version') { when { branch pattern: 'release/*', comparator: 'GLOB' } steps { // fetch all remotes from origin sh 'git config --replace-all "remote.origin.fetch" "+refs/heads/*:refs/remotes/origin/*"' sh 'git fetch --all' // checkout, reset and merge sh 'git checkout main' sh 'git reset --hard origin/main' sh "git merge --ff-only ${env.BRANCH_NAME}" // set tag tag releaseVersion } } stage('Tests') { agent { docker { image 'golang:1.17.5' reuseNode true } } steps { sh 'go test ./...' } } stage('Build') { agent { docker { image 'golang:1.17.5' reuseNode true } } steps { sh 'make build' } } stage('Publish') { when { branch pattern: 'release/*', comparator: 'GLOB' expression { return isBuildSuccess() } } agent { docker { image 'golang:1.17.5' reuseNode true } } steps { withPublishEnvironment { ansiColor('xterm') { sh 'VERSION=v1.7.0 curl -sL https://git.io/goreleaser | bash -s -- release --rm-dist' } sh "go run pkg/build/upload/app.go dist/scm-cli.json scoop-bucket main bucket/scm-cli.json \"Update scoop scm-cli to ${releaseVersion}\"" sh "go run pkg/build/upload/app.go dist/scm-cli.rb homebrew-tap master Formula/scm-cli.rb \"Update brew scm-cli to ${releaseVersion}\"" sh "go run pkg/build/descriptor/app.go dist > dist/release.yaml" sh "go run pkg/build/upload/app.go dist/release.yaml website master content/cli/releases/${hyphenatedReleaseVersion}.yaml \"Release cli version ${releaseVersion}\"" } } } stage('Update Repository') { when { branch pattern: 'release/*', comparator: 'GLOB' } steps { // merge main in to develop sh 'git checkout develop' sh 'git merge main' // push changes back to remote repository authGit 'cesmarvin-github', 'push origin main --tags' authGit 'cesmarvin-github', 'push origin develop --tags' authGit 'cesmarvin-github', "push origin :${env.BRANCH_NAME}" } } } post { failure { mail to: "scm-team@cloudogu.com", subject: "${JOB_NAME} - Build #${BUILD_NUMBER} - ${currentBuild.currentResult}!", body: "Check console output at ${BUILD_URL} to view the results." } } } void withPublishEnvironment(Closure<Void> closure) { withCredentials([ usernamePassword(credentialsId: 'maven.scm-manager.org', usernameVariable: 'UPLOAD_DEFAULT_USERNAME', passwordVariable: 'UPLOAD_DEFAULT_SECRET'), usernamePassword(credentialsId: 'maven.scm-manager.org', usernameVariable: 'UPLOAD_RPM_USERNAME', passwordVariable: 'UPLOAD_RPM_SECRET'), usernamePassword(credentialsId: 'maven.scm-manager.org', usernameVariable: 'UPLOAD_DEB_USERNAME', passwordVariable: 'UPLOAD_DEB_SECRET'), file(credentialsId: 'oss-gpg-secring', variable: 'GPG_KEY_PATH'), usernamePassword(credentialsId: 'oss-keyid-and-passphrase', usernameVariable: 'GPG_KEY_ID', passwordVariable: 'GPG_PASSWORD'), usernamePassword(credentialsId: 'oss-keyid-and-passphrase', usernameVariable: 'NFPM_RPM_KEY_ID', passwordVariable: 'NFPM_RPM_PASSPHRASE'), usernamePassword(credentialsId: 'oss-keyid-and-passphrase', usernameVariable: 'NFPM_DEB_KEY_ID', passwordVariable: 'NFPM_DEB_PASSPHRASE'), usernamePassword(credentialsId: 'cesmarvin-github', usernameVariable: 'GITHUB_USERNAME', passwordVariable: 'GITHUB_API_TOKEN'), ]) { sh 'gpg --no-tty --batch --yes --import $GPG_KEY_PATH' closure.call() } } String getHyphenatedReleaseVersion() { return getReleaseVersion().replace('.', '-') } String getReleaseVersion() { return env.BRANCH_NAME.substring("release/".length()); } void commit(String message) { sh "git -c user.name='CES Marvin' -c user.email='cesmarvin@cloudogu.com' commit -m '${message}'" } void tag(String version) { String message = "Release version ${version}" sh "git -c user.name='CES Marvin' -c user.email='cesmarvin@cloudogu.com' tag -m '${message}' ${version}" } boolean isBuildSuccess() { return currentBuild.result == null || currentBuild.result == 'SUCCESS' } void authGit(String credentials, String command) { withCredentials([ usernamePassword(credentialsId: credentials, usernameVariable: 'AUTH_USR', passwordVariable: 'AUTH_PSW') ]) { sh "git -c credential.helper=\"!f() { echo username='\$AUTH_USR'; echo password='\$AUTH_PSW'; }; f\" ${command}" } } 07070100000005000081A400000000000000000000000162D515C000000434000000000000000000000000000000000000001E00000000scm-manager-cli-1.0.1/LICENSEThe MIT License (MIT) Copyright (c) 2015 gatsbyjs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 07070100000006000081A400000000000000000000000162D515C000000146000000000000000000000000000000000000001F00000000scm-manager-cli-1.0.1/MakefileGITHASH:=$(shell git rev-parse --short HEAD) BUILDTIME:=$(shell TZ=UTC date +"%Y-%m-%dT%H:%M:%SZ") LDFLAGS='-w -extldflags "-static" -s -X github.com/scm-manager/cli/pkg.commitHash=${GITHASH} -X github.com/scm-manager/cli/pkg.buildTime=${BUILDTIME}' .PHONY: build: go build -a -tags netgo -ldflags ${LDFLAGS} -o scm scm.go 07070100000007000081A400000000000000000000000162D515C00000016F000000000000000000000000000000000000002000000000scm-manager-cli-1.0.1/README.md# Usage 1. Run `go build scm.go` to compile the binary 2. Start using the cli with `./scm login {server_url}` 3. Find out which commands are available on your server using `./scm` # Documentation Find out how to implement own cli commands in the related [cli guidelines](https://github.com/scm-manager/scm-manager/blob/develop/docs/en/development/cli-guideline.md) 07070100000008000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000001B00000000scm-manager-cli-1.0.1/docs07070100000009000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000001E00000000scm-manager-cli-1.0.1/docs/en0707010000000A000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002B00000000scm-manager-cli-1.0.1/docs/en/installation0707010000000B000081A400000000000000000000000162D515C0000005B3000000000000000000000000000000000000003500000000scm-manager-cli-1.0.1/docs/en/installation/debian.md--- title: Debian/Ubuntu subtitle: Installation of SCM-Manager CLI Client for Debian-based linux distributions displayToc: true --- ## Quickstart The following code block will configure an apt repository for SCM-Manager CLI Client and install it. ```bash echo "deb [arch=$(dpkg --print-architecture)] https://packages.scm-manager.org/repository/apt-v2-releases/ stable main" | sudo tee /etc/apt/sources.list.d/scm-manager.list sudo apt-key adv --recv-keys --keyserver hkps://keys.openpgp.org 0x975922F193B07D6E sudo apt-get update sudo apt-get install scm-cli ``` ## Detailed installation To install SCM-Manager CLI as a debian package (.deb), we have to configure an apt repository. Replace `<arch>` with your system architecture. You can find it out by using `dpkg --print-architecture`. Create a file at `/etc/apt/sources.list.d/scm-manager.list` with the following content: ```text deb [arch=<arch>] https://packages.scm-manager.org/repository/apt-v2-releases/ stable main ``` This will add the apt repository of the SCM-Manager stable releases to the list of your apt repositories. To ensure the integrity of the debian packages we have to import the gpg key for the repository. ```bash sudo apt-key adv --recv-keys --keyserver hkps://keys.openpgp.org 0x975922F193B07D6E ``` After we have imported the gpg key, we can update the package index and install the SCM-Manager CLI Client: ```bash sudo apt-get update sudo apt-get install scm-cli ``` 0707010000000C000081A400000000000000000000000162D515C00000028C000000000000000000000000000000000000003700000000scm-manager-cli-1.0.1/docs/en/installation/homebrew.md--- title: Homebrew subtitle: SCM-Manager CLI Client installation using homebrew displayToc: true --- # Homebrew To install the SCM-Manager CLI Client we offer a [Homebrew](https://brew.sh/) tap. This CLI Client does not work standalone but need a running SCM-Manager server. ## Quickstart ```bash brew install scm-manager/tap/scm-cli ``` ## Detailed installation To install SCM-Manager with homebrew we had to add the SCM-Manager tap: ```bash brew tap scm-manager/tap ``` After the tap was added, we can install the SCM-Manager CLI Client: ```bash brew install scm-cli ``` Now the CLI Client can be started: ```bash scm login {server_url} ``` 0707010000000D000081A400000000000000000000000162D515C0000000E4000000000000000000000000000000000000003400000000scm-manager-cli-1.0.1/docs/en/installation/index.md--- title: Installation subtitle: Installation of SCM-Manager CLI CLient partiallyActive: true --- * [Debian/Ubuntu](debian/) * [Red Hat/CentOS/Fedora](redhat/) * [Windows](windows/) * [Darwin](darwin/) * [Unix General](unix/) 0707010000000E000081A400000000000000000000000162D515C0000005C1000000000000000000000000000000000000003500000000scm-manager-cli-1.0.1/docs/en/installation/redhat.md--- title: Redhat/CentOS/Fedora subtitle: Installation of SCM-Manager CLI Client for RedHat-based linux distributions displayToc: true --- ## Quickstart The following code block will configure a yum repository for scm-manager and install it. ```bash cat << EOF | sudo tee /etc/yum.repos.d/SCM-Manager.repo [scm-manager] name=SCM-Manager Repository baseurl=https://packages.scm-manager.org/repository/yum-v2-releases/ enabled=1 gpgcheck=1 priority=1 gpgkey=file:///etc/pki/rpm-gpg/SCM-Manager EOF sudo curl -o /etc/pki/rpm-gpg/SCM-Manager https://packages.scm-manager.org/repository/keys/gpg/oss-cloudogu-com.pub sudo yum install scm-cli ``` ## Detailed installation To install SCM-Manager as a redhat package (.rpm), we have to configure a yum repository. Create a file at `/etc/yum.repos.d/SCM-Manager.repo` with the following content: ```ini [scm-manager] name=SCM-Manager Repository baseurl=https://packages.scm-manager.org/repository/yum-v2-releases/ enabled=1 gpgcheck=1 priority=1 gpgkey=file:///etc/pki/rpm-gpg/SCM-Manager ``` This will add the yum repository of the scm-manager stable releases to the list of your yum repositories. To ensure the integrity of the rpm packages we have to import the gpg key for the repository. ```bash sudo curl -o /etc/pki/rpm-gpg/SCM-Manager https://packages.scm-manager.org/repository/keys/gpg/oss-cloudogu-com.pub ``` After we have imported the gpg key, we can install scm-manager: ```bash sudo yum install scm-cli ``` 0707010000000F000081A400000000000000000000000162D515C0000002E6000000000000000000000000000000000000003300000000scm-manager-cli-1.0.1/docs/en/installation/unix.md--- title: Unix subtitle: General unix installation displayToc: true --- ## Requirements This tool does not work standalone but need a running SCM-Manager server. ## Installation Grab the latest version and checksum from [download page](/cli) and replace `<version>` and `<checksum>` in the code blocks below. Download and verify the checksum. ```bash wget https://packages.scm-manager.org/repository/scm-cli-releases/<version>/scm-cli_<version>_<os>_<arch>.tar.gz echo "<checksum> *scm-cli_<version>_<os>_<arch>.tar.gz" | sha256sum -c - ``` Extract the archive: ```bash sudo tar xvfz scm-cli_<version>_<os>_<arch>.tar.gz -C /usr/local/bin ``` ## First start The cli client can be started by using `scm` in your terminal. ```bash scm ``` 07070100000010000081A400000000000000000000000162D515C000000632000000000000000000000000000000000000003600000000scm-manager-cli-1.0.1/docs/en/installation/windows.md--- title: Windows subtitle: Install SCM-Manager CLI Client on Windows displayToc: true --- The following document describes the installation process for SCM-Manager CLI Client on Windows. ## Install SCM-Manager CLI ### Install via Scoop To install the CLI CLient via Scoop run the following commands: ``` scoop bucket add scm https://github.com/scm-manager/scoop-bucket scoop install scm-cli ``` ### Manual installation To install SCM-Manager CLI you have to download the latest Windows package from the [download page](/cli/). After unpacking the archive move the file to a new directory. To make it available on your `PATH` you can follow this [instruction](https://stackoverflow.com/questions/1618280/where-can-i-set-path-to-make-exe-on-windows). ## First start Now we have to open a Terminal (PowerShell, Bash or CMD), in order to run the SCM-Manager CLI Client. For this to work you must have an SCM-Manager server running and connect your client first. You can start with the following command: ```bash scm.exe login {server_url} ``` ### Known problems with mintty (Git Bash, Cygwin) On some terminals under Windows, problems with stdin or stdout/stderr may occur. For example, when you try to log in, hitting enter on your username generates a second enter which prevents the possibility to enter your password and the login fails. Or, if you have previously logged in e.g. via Powershell, running the CLI won't create any output and the CLI won't exit. You can fix these problems by adding the following line to your `.minttyrc` file: ```properties ConPTY=on ``` 07070100000011000081A400000000000000000000000162D515C000000279000000000000000000000000000000000000001D00000000scm-manager-cli-1.0.1/go.modmodule github.com/scm-manager/cli go 1.17 require ( github.com/Xuanwo/go-locale v1.1.0 github.com/stretchr/testify v1.7.1 github.com/zalando/go-keyring v0.2.1 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b ) require ( github.com/alessio/shellescape v1.4.1 // indirect github.com/danieljoos/wincred v1.1.0 // indirect github.com/davecgh/go-spew v1.1.0 // indirect github.com/godbus/dbus/v5 v5.0.6 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/sys v0.0.0-20211023085530-d6a326fbbf70 // indirect golang.org/x/text v0.3.7 // indirect ) 07070100000012000081A400000000000000000000000162D515C0000011DC000000000000000000000000000000000000001D00000000scm-manager-cli-1.0.1/go.sumgithub.com/Xuanwo/go-locale v1.1.0 h1:51gUxhxl66oXAjI9uPGb2O0qwPECpriKQb2hl35mQkg= github.com/Xuanwo/go-locale v1.1.0/go.mod h1:UKrHoZB3FPIk9wIG2/tVSobnHgNnceGSH3Y8DY5cASs= github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/danieljoos/wincred v1.1.0 h1:3RNcEpBg4IhIChZdFRSdlQt1QjCp1sMAPIrOnm7Yf8g= github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.7 h1:I6tZjLXD2Q1kjvNbIzB1wvQBsXmKXiVrhpRE8ZjP5jY= github.com/smartystreets/goconvey v1.6.7/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/zalando/go-keyring v0.2.1 h1:MBRN/Z8H4U5wEKXiD67YbDAr5cj/DOStmSga70/2qKc= github.com/zalando/go-keyring v0.2.1/go.mod h1:g63M2PPn0w5vjmEbwAX3ib5I+41zdm4esSETOn9Y6Dw= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211023085530-d6a326fbbf70 h1:SeSEfdIxyvwGJliREIJhRPPXvW6sDlLT+UQ3B0hD0NA= golang.org/x/sys v0.0.0-20211023085530-d6a326fbbf70/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 07070100000013000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000001A00000000scm-manager-cli-1.0.1/pkg07070100000014000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000001E00000000scm-manager-cli-1.0.1/pkg/api07070100000015000081A400000000000000000000000162D515C00000078F000000000000000000000000000000000000002800000000scm-manager-cli-1.0.1/pkg/api/apikey.gopackage api import ( "bytes" "encoding/json" "fmt" "github.com/scm-manager/cli/pkg" "io" "io/ioutil" "net/http" ) type CreateApiKeyRequest struct { ApiKey string `json:"apiKey"` } func Create(serverUrl string, username string, password string, apiKeyName string) (string, error) { loginRequest := CreateApiKeyRequest{ApiKey: apiKeyName} payloadBuf := new(bytes.Buffer) err := json.NewEncoder(payloadBuf).Encode(loginRequest) if err != nil { return "", fmt.Errorf("could not encode hostname: %w", err) } req, _ := http.NewRequest("POST", serverUrl+"/api/v2/cli/login", payloadBuf) req.Header.Add("Content-Type", "application/json") req.SetBasicAuth(username, password) client := pkg.CreateHttpClient() res, err := client.Do(req) if err != nil { return "", fmt.Errorf("could not send login request: %w", err) } defer func(Body io.ReadCloser) { _ = Body.Close() }(res.Body) if res.StatusCode >= 400 { return "", fmt.Errorf("could not create new api key on server. Server returned status code: %d", res.StatusCode) } body, err := ioutil.ReadAll(res.Body) if err != nil { return "", fmt.Errorf("could not read login response: %w", err) } return string(body), nil } func Remove(serverUrl string, apiKey string, apiKeyName string) error { // Remove api key on server req, err := http.NewRequest("DELETE", serverUrl+"/api/v2/cli/logout/"+apiKeyName, nil) if err != nil { return fmt.Errorf("could not create delete request: %w", err) } req.Header.Add("Content-Type", "application/json") req.Header.Add("Authorization", "Bearer "+apiKey) client := pkg.CreateHttpClient() res, err := client.Do(req) if err != nil { return fmt.Errorf("could not revoke api key on server: %w", err) } defer func(Body io.ReadCloser) { _ = Body.Close() }(res.Body) if res.StatusCode >= 400 { return fmt.Errorf("could not remove api key. Server returned status code: %d", res.StatusCode) } return nil } 07070100000016000081A400000000000000000000000162D515C0000004FC000000000000000000000000000000000000002D00000000scm-manager-cli-1.0.1/pkg/api/apikey_test.gopackage api import ( "fmt" "github.com/stretchr/testify/assert" "github.com/zalando/go-keyring" "net/http" "net/http/httptest" "testing" ) func init() { keyring.MockInit() } func TestCreate(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, err := fmt.Fprintf(w, "api-secret") assert.NoError(t, err) assert.Equal(t, "Basic YXJ0aHVyOnNlY3JldA==", r.Header.Get("Authorization")) })) defer server.Close() apiKey, err := Create(server.URL, "arthur", "secret", "test-key") assert.NoError(t, err) assert.Equal(t, "api-secret", apiKey) } func TestRemoveIfKeyNotExist(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "Bearer api-token", r.Header.Get("Authorization")) })) defer server.Close() err := Remove(server.URL, "api-token", "scm-test") assert.NoError(t, err) } func TestRemove(t *testing.T) { serviceName := "scm-test" apiKey := "api-token" server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "Bearer "+apiKey, r.Header.Get("Authorization")) })) defer server.Close() err := Remove(server.URL, apiKey, serviceName) assert.NoError(t, err) } 07070100000017000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002000000000scm-manager-cli-1.0.1/pkg/build07070100000018000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002B00000000scm-manager-cli-1.0.1/pkg/build/descriptor07070100000019000081A400000000000000000000000162D515C000000C45000000000000000000000000000000000000003200000000scm-manager-cli-1.0.1/pkg/build/descriptor/app.gopackage main import ( "bufio" "encoding/json" "fmt" "gopkg.in/yaml.v3" "io/ioutil" "log" "os" "path" "path/filepath" "strings" "time" ) type MetadataJson struct { Tag string Date string } type Artifact struct { Name string Type string Goarch string Goos string } type Package struct { Type string Os string `yaml:",omitempty"` Arch string `yaml:",omitempty"` Url string `yaml:",omitempty"` Checksum string `yaml:",omitempty"` } type Descriptor struct { Tag string Date string Type string Packages []Package } func main() { dir := os.Args[1] file, err := ioutil.ReadFile(path.Join(dir, "metadata.json")) if err != nil { log.Fatal("could not read metadata.json") } metadata := MetadataJson{} err = json.Unmarshal(file, &metadata) if err != nil { log.Fatal("could not unmarshal metadata.json") } file, err = ioutil.ReadFile(path.Join(dir, "artifacts.json")) if err != nil { log.Fatal("could not read artifacts.json") } var artifacts []Artifact err = json.Unmarshal(file, &artifacts) if err != nil { log.Fatal("could not unmarshal artifacts.json") } var packages []Package checksums := readChecksums(dir) for _, a := range artifacts { if a.Type == "Archive" { checksum := checksums[a.Name] url := fmt.Sprintf("https://packages.scm-manager.org/repository/scm-cli-releases/%s/%s", metadata.Tag, a.Name) packages = append(packages, Package{ Os: a.Goos, Arch: a.Goarch, Checksum: checksum, Type: filepath.Ext(a.Name)[1:], Url: url, }) } else if a.Type == "Linux Package" { packages = append(packages, Package{Os: a.Goos, Arch: a.Goarch, Type: filepath.Ext(a.Name)[1:]}) } else if a.Type == "Brew Tap" { packages = append(packages, Package{Type: "homebrew", Os: "linux", Arch: "arm64"}) packages = append(packages, Package{Type: "homebrew", Os: "linux", Arch: "amd64"}) packages = append(packages, Package{Type: "homebrew", Os: "darwin", Arch: "arm64"}) packages = append(packages, Package{Type: "homebrew", Os: "darwin", Arch: "amd64"}) } else if a.Type == "Scoop Manifest" { packages = append(packages, Package{Type: "scoop", Os: "windows", Arch: "amd64"}) } } date, err := time.Parse(time.RFC3339Nano, metadata.Date) if err != nil { log.Fatal("could not parse release date") } descriptor := Descriptor{Tag: metadata.Tag, Date: date.UTC().Format(time.RFC3339), Type: "cli", Packages: packages} bytes, err := yaml.Marshal(&descriptor) if err != nil { log.Fatal("could not unmarshal artifacts.json") } fmt.Println(string(bytes)) } func readChecksums(dir string) map[string]string { checksumFile, err := os.Open(path.Join(dir, "checksums.txt")) if err != nil { log.Fatal("could not read checksums.txt") } defer checksumFile.Close() scanner := bufio.NewScanner(checksumFile) checksums := make(map[string]string) for scanner.Scan() { line := scanner.Text() result := strings.Split(line, " ") checksums[result[1]] = result[0] } err = scanner.Err() if err != nil { log.Fatal("error during scanning checksums.txt") } return checksums } 0707010000001A000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002700000000scm-manager-cli-1.0.1/pkg/build/upload0707010000001B000081A400000000000000000000000162D515C000000ACC000000000000000000000000000000000000002E00000000scm-manager-cli-1.0.1/pkg/build/upload/app.gopackage main import ( "bytes" "encoding/base64" "encoding/json" "fmt" "io/ioutil" "log" "net/http" "os" ) type Person struct { Name string `json:"name"` Email string `json:"email"` } type GitHubUploadRequest struct { Message string `json:"message"` Branch string `json:"branch"` Author Person `json:"author"` Content string `json:"content"` Sha string `json:"sha,omitempty"` } type GitHubContent struct { Sha string } func receiveSha(token string, url string, branch string) string { request, err := http.NewRequest("GET", url+"?ref="+branch, nil) if err != nil { log.Fatal("Failed to create get request", err) } request.Header.Set("Authorization", "Token "+token) request.Header.Set("Accept", "application/vnd.github.v3+json") response, err := http.DefaultClient.Do(request) if err != nil { log.Fatal("Get request failed", err) } defer response.Body.Close() if response.StatusCode == 404 { return "" } if response.StatusCode >= 300 { log.Fatal("Get request failed with status code", response.StatusCode) } data, err := ioutil.ReadAll(response.Body) if err != nil { log.Fatal("failed to read response body") } content := GitHubContent{} err = json.Unmarshal(data, &content) if err != nil { log.Fatal("Failed to unmarshal content", err) } return content.Sha } func main() { token := os.Getenv("GITHUB_API_TOKEN") if token == "" { log.Fatal("missing GitHub API Token") } args := os.Args source := args[1] repo := args[2] branch := args[3] path := args[4] commitMessage := args[5] url := fmt.Sprintf("https://api.github.com/repos/scm-manager/%s/contents/%s", repo, path) file, err := ioutil.ReadFile(source) if err != nil { log.Fatal("could not read source file") } content := base64.StdEncoding.EncodeToString(file) uploadRequest := GitHubUploadRequest{ Message: commitMessage, Branch: branch, Author: Person{Name: "CES Marvin", Email: "cesmarvin@cloudogu.com"}, Content: content, Sha: receiveSha(token, url, branch), } data, err := json.Marshal(&uploadRequest) if err != nil { log.Fatal("Could not marshal json") } request, err := http.NewRequest("PUT", url, bytes.NewBuffer(data)) if err != nil { log.Fatal("could not create upload request") } request.Header.Set("Authorization", "Token "+token) request.Header.Set("Accept", "application/vnd.github.v3+json") response, err := http.DefaultClient.Do(request) if err != nil { log.Fatal("could not send upload request") } if response.StatusCode >= 300 { defer response.Body.Close() body, err := ioutil.ReadAll(response.Body) if err != nil { log.Fatal("Could not read response body") } log.Fatalf("upload request failed: %d\n\n%s", response.StatusCode, string(body)) } } 0707010000001C000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002200000000scm-manager-cli-1.0.1/pkg/command0707010000001D000081A400000000000000000000000162D515C000000CDC000000000000000000000000000000000000002A00000000scm-manager-cli-1.0.1/pkg/command/exec.gopackage command import ( "encoding/json" "fmt" "github.com/Xuanwo/go-locale" "github.com/scm-manager/cli/pkg" "io" "net/http" "os" ) type ExecuteResponse struct { Out string Err string Exit int } func CreateExecutor(stdout io.Writer, stderr io.Writer, stdin io.Reader, config *pkg.Configuration) *Executor { return &Executor{stdout: stdout, stderr: stderr, stdin: stdin, config: config} } func CreateDefaultExecutor(config *pkg.Configuration) (*Executor, error) { stdin, err := createStdin() if err != nil { return nil, err } return CreateExecutor(os.Stdout, os.Stderr, stdin, config), nil } func createStdin() (io.Reader, error) { stat, err := os.Stdin.Stat() if err != nil { return nil, fmt.Errorf("failed to read stat from stdin: %w", err) } if (stat.Mode() & os.ModeCharDevice) == 0 { return os.Stdin, nil } return nil, nil } type Executor struct { stdout io.Writer stderr io.Writer stdin io.Reader config *pkg.Configuration } func (e *Executor) Execute(args ...string) (int, error) { req, err := e.createRequest(args) if err != nil { return -1, err } res, err := e.sendRequest(req) if err != nil { return -1, err } defer func(Body io.ReadCloser) { _ = Body.Close() }(res.Body) return e.processResponse(res) } func (e *Executor) sendRequest(req *http.Request) (*http.Response, error) { client := pkg.CreateHttpClient() res, err := client.Do(req) if err != nil { return res, fmt.Errorf("could not send execution request: %w", err) } if res.StatusCode >= 400 { return res, fmt.Errorf("HTTP Error %d", res.StatusCode) } return res, nil } func (e *Executor) createRequest(args []string) (*http.Request, error) { req, _ := http.NewRequest("POST", e.config.ServerUrl+"/api/v2/cli/exec", e.stdin) req.Header.Add("Authorization", "Bearer "+e.config.ApiKey) e.setCommandVarArgs(req, args) err := e.setRequestLocale(req) if err != nil { return req, err } return req, nil } func (e *Executor) processResponse(res *http.Response) (int, error) { decoder := json.NewDecoder(res.Body) _, err := decoder.Token() if err != nil { return -1, fmt.Errorf("could not read token from json: %w", err) } for decoder.More() { response := &ExecuteResponse{} err := decoder.Decode(response) if err != nil { if err == io.EOF { break } return -1, fmt.Errorf("could not decode response body: %w", err) } if response.Out != "" { _, err := e.stdout.Write([]byte(response.Out)) if err != nil { return -1, fmt.Errorf("could not write to stdout: %w", err) } } if response.Err != "" { _, err := e.stderr.Write([]byte(response.Err)) if err != nil { return -1, fmt.Errorf("could not write to stderr: %w", err) } } if response.Exit != 0 { return response.Exit, nil } } return 0, nil } func (e *Executor) setCommandVarArgs(req *http.Request, args []string) { queryString := req.URL.Query() for _, arg := range args { queryString.Add("args", arg) } req.URL.RawQuery = queryString.Encode() } func (e *Executor) setRequestLocale(req *http.Request) error { language, err := locale.Detect() if err != nil { return fmt.Errorf("could not detect client locale: %w", err) } baseLang, _ := language.Base() req.Header.Add("Accept-Language", baseLang.String()) return nil } 0707010000001E000081A400000000000000000000000162D515C00000111C000000000000000000000000000000000000002F00000000scm-manager-cli-1.0.1/pkg/command/exec_test.gopackage command import ( "bytes" "fmt" "github.com/scm-manager/cli/pkg" "github.com/stretchr/testify/assert" "net/http" "net/http/httptest" "testing" ) func TestExecutor_Execute(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, err := fmt.Fprintf(w, "[{\"out\":\"Hello World\"}]") assert.NoError(t, err) })) defer server.Close() var stdout bytes.Buffer configuration := &pkg.Configuration{ServerUrl: server.URL, Username: "scmadmin", ApiKey: "secret"} executor := CreateExecutor(&stdout, nil, nil, configuration) exitCode, err := executor.Execute("some", "command") assert.NoError(t, err) assert.Equal(t, 0, exitCode) assert.Equal(t, "Hello World", stdout.String()) } func TestExecutor_ExecuteCheckForArgs(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() assert.NoError(t, err) assert.Equal(t, []string{"some", "command"}, r.Form["args"]) _, err = fmt.Fprintf(w, "[{\"out\":\"Hello World\"}]") assert.NoError(t, err) })) defer server.Close() var stdout bytes.Buffer configuration := &pkg.Configuration{ServerUrl: server.URL, Username: "scmadmin", ApiKey: "secret"} executor := CreateExecutor(&stdout, nil, nil, configuration) _, err := executor.Execute("some", "command") assert.NoError(t, err) } func TestExecutor_ExecuteCheckWithApiKey(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "Bearer secret", r.Header.Get("Authorization")) _, err := fmt.Fprintf(w, "[{\"out\":\"Hello World\"}]") assert.NoError(t, err) })) defer server.Close() var stdout bytes.Buffer configuration := &pkg.Configuration{ServerUrl: server.URL, Username: "scmadmin", ApiKey: "secret"} executor := CreateExecutor(&stdout, nil, nil, configuration) _, err := executor.Execute("some", "command") assert.NoError(t, err) } func TestExecutor_ExecuteCheckStderr(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, err := fmt.Fprintf(w, "[{\"err\":\"Missing entity\"}]") assert.NoError(t, err) })) defer server.Close() var stderr bytes.Buffer configuration := &pkg.Configuration{ServerUrl: server.URL, Username: "scmadmin", ApiKey: "secret"} executor := CreateExecutor(nil, &stderr, nil, configuration) _, err := executor.Execute("some", "command") assert.NoError(t, err) assert.Equal(t, "Missing entity", stderr.String()) } func TestExecutor_ExecuteCheckExitCode(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, err := fmt.Fprintf(w, "[{\"exit\":42}]") assert.NoError(t, err) })) defer server.Close() configuration := &pkg.Configuration{ServerUrl: server.URL, Username: "scmadmin", ApiKey: "secret"} executor := CreateExecutor(nil, nil, nil, configuration) exitCode, err := executor.Execute("some", "command") assert.NoError(t, err) assert.Equal(t, 42, exitCode) } func TestExecutor_ExecuteCheckLocale(t *testing.T) { t.Setenv("LANGUAGE", "es_MX") server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "es", r.Header.Get("Accept-Language")) _, err := fmt.Fprintf(w, "[{\"exit\":0}]") assert.NoError(t, err) })) defer server.Close() configuration := &pkg.Configuration{ServerUrl: server.URL, Username: "scmadmin", ApiKey: "secret"} executor := CreateExecutor(nil, nil, nil, configuration) _, err := executor.Execute("some", "command") assert.NoError(t, err) } func TestExecutor_ExecuteCheckHttpError(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not found", http.StatusNotFound) })) defer server.Close() configuration := &pkg.Configuration{ServerUrl: server.URL, Username: "scmadmin", ApiKey: "secret"} executor := CreateExecutor(nil, nil, nil, configuration) _, err := executor.Execute("some", "command") assert.ErrorContains(t, err, "HTTP Error 404") } func TestCreateDefaultExecutor(t *testing.T) { configuration := &pkg.Configuration{ServerUrl: "myServer", Username: "scmadmin", ApiKey: "secret"} executor, err := CreateDefaultExecutor(configuration) assert.NoError(t, err) assert.NotNil(t, executor) } 0707010000001F000081A400000000000000000000000162D515C00000006C000000000000000000000000000000000000002400000000scm-manager-cli-1.0.1/pkg/config.gopackage pkg type Configuration struct { ServerUrl string Username string ApiKey string `json:"-"` } 07070100000020000081A400000000000000000000000162D515C0000004E3000000000000000000000000000000000000002200000000scm-manager-cli-1.0.1/pkg/http.gopackage pkg import ( "fmt" "net/http" "runtime" ) // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent // name/version (os arch; commithash; buildtime) const cliName = "scm-cli" var ( version string = "x.y.z" commitHash string buildTime string ) func createDevUserAgent(version, osName, arch string) string { return fmt.Sprintf("%s/%s (%s %s)", cliName, version, osName, arch) } func createProdUserAgent(version, osName, arch, gitHash, buildTime string) string { return fmt.Sprintf("%s/%s (%s %s; %s; %s)", cliName, version, osName, arch, gitHash, buildTime) } func createUserAgent(version, osName, arch, gitHash, buildTime string) string { if gitHash != "" && buildTime != "" { return createProdUserAgent(version, osName, arch, gitHash, buildTime) } return createDevUserAgent(version, osName, arch) } func CreateHttpClient() *http.Client { client := &http.Client{} client.Transport = &userAgentTransport{} return client } type userAgentTransport struct { } func (t *userAgentTransport) RoundTrip(r *http.Request) (*http.Response, error) { ua := createUserAgent(version, runtime.GOOS, runtime.GOARCH, commitHash, buildTime) r.Header.Set("User-Agent", ua) return http.DefaultTransport.RoundTrip(r) } 07070100000021000081A400000000000000000000000162D515C000000352000000000000000000000000000000000000002700000000scm-manager-cli-1.0.1/pkg/http_test.gopackage pkg import ( "github.com/stretchr/testify/assert" "net/http" "net/http/httptest" "testing" ) func TestCreateUserAgent(t *testing.T) { userAgent := createUserAgent("1.0.0", "linux", "arm64", "bb4d50d", "2022-04-04T09:41:03Z") assert.Equal(t, "scm-cli/1.0.0 (linux arm64; bb4d50d; 2022-04-04T09:41:03Z)", userAgent) } func TestCreateUserAgent_WithoutGitHashAndBuildTime(t *testing.T) { userAgent := createUserAgent("x.y.z", "darwin", "arm64", "", "") assert.Equal(t, "scm-cli/x.y.z (darwin arm64)", userAgent) } func TestCreateHttpClient(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Contains(t, r.Header.Get("User-Agent"), "scm-cli/x.y.z") })) defer server.Close() client := CreateHttpClient() _, err := client.Get(server.URL) assert.NoError(t, err) } 07070100000022000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002000000000scm-manager-cli-1.0.1/pkg/store07070100000023000081A400000000000000000000000162D515C000000D61000000000000000000000000000000000000002900000000scm-manager-cli-1.0.1/pkg/store/store.gopackage store import ( "encoding/json" "fmt" "github.com/scm-manager/cli/pkg" "github.com/zalando/go-keyring" "io/ioutil" "os" "path" ) const keyName = "scm-cli" func readFromFilePath(filePath string) (*pkg.Configuration, error) { _, err := os.Stat(filePath) if err != nil { if os.IsNotExist(err) { return nil, nil } else { return nil, fmt.Errorf("could not find config file: %w", err) } } data, err := ioutil.ReadFile(filePath) if err != nil { return nil, fmt.Errorf("could not read config file: %w", err) } configuration := &pkg.Configuration{} err = json.Unmarshal(data, configuration) if err != nil { return nil, fmt.Errorf("could not parse config file: %w", err) } key, err := readApiKey(keyName, configuration.Username) if err != nil { return nil, err } configuration.ApiKey = key return configuration, err } func Read() (*pkg.Configuration, error) { configFilePath, err := resolveConfigFilePath() if err != nil { return nil, err } return readFromFilePath(configFilePath) } func writeToFilePath(filePath string, configuration *pkg.Configuration) error { file, err := os.Create(filePath) if err != nil { return fmt.Errorf("could not create cli config file: %w", err) } defer func(file *os.File) { _ = file.Close() }(file) jsonConfig, err := json.Marshal(configuration) if err != nil { return fmt.Errorf("could not marshal config json: %w", err) } _, err = file.Write(jsonConfig) if err != nil { return fmt.Errorf("could not write config to file: %w", err) } err = storeApiKey(keyName, configuration.Username, configuration.ApiKey) if err != nil { return fmt.Errorf("could not store api key to keyring: %w", err) } return nil } func Write(configuration *pkg.Configuration) error { configFilePath, err := resolveConfigFilePath() if err != nil { return err } return writeToFilePath(configFilePath, configuration) } func removeFilePath(filePath string) error { config, err := readFromFilePath(filePath) if err != nil { return err } err = os.Remove(filePath) if err != nil { return fmt.Errorf("could not remove config file: %w", err) } err = removeApiKey(keyName, config.Username) if err != nil { return fmt.Errorf("could not remove api key from keystore: %w", err) } return nil } func Remove() error { configFilePath, err := resolveConfigFilePath() if err != nil { return err } return removeFilePath(configFilePath) } func storeApiKey(apiKeyName string, username string, apiKey string) error { err := keyring.Set(apiKeyName, username, apiKey) if err != nil { return fmt.Errorf("could not store apikey to keyring: %w", err) } return nil } func readApiKey(apiKeyName string, username string) (string, error) { apiKey, err := keyring.Get(apiKeyName, username) if err != nil { return apiKey, fmt.Errorf("could not read apikey from keyring: %w", err) } return apiKey, nil } func removeApiKey(apiKeyName string, username string) error { // Remove stored api key err := keyring.Delete(apiKeyName, username) if err != nil { if err != nil { return fmt.Errorf("could not remove stored api key: %w", err) } } return nil } func resolveConfigFilePath() (string, error) { // Read config (server url, username) => .scm-cli.json homeDir, err := os.UserHomeDir() if err != nil { return "", fmt.Errorf("could not find home directory: %w", err) } return path.Join(homeDir, ".scm-cli.json"), nil } 07070100000024000081A400000000000000000000000162D515C0000007CB000000000000000000000000000000000000002E00000000scm-manager-cli-1.0.1/pkg/store/store_test.gopackage store import ( "github.com/scm-manager/cli/pkg" "github.com/stretchr/testify/assert" "github.com/zalando/go-keyring" "os" "path" "testing" ) func init() { keyring.MockInit() } func TestRead(t *testing.T) { err := keyring.Set("scm-cli", "trillian", "secret") config, err := readFromFilePath(path.Join("testdata", "cli-config.json")) assert.NoError(t, err) assert.Equal(t, "localhost", config.ServerUrl) assert.Equal(t, "trillian", config.Username) assert.Equal(t, "secret", config.ApiKey) } func TestStore(t *testing.T) { filePath := path.Join(t.TempDir(), "testpath") err := writeToFilePath(filePath, &pkg.Configuration{ServerUrl: "server", Username: "user"}) assert.NoError(t, err) config, err := readFromFilePath(filePath) assert.Equal(t, "server", config.ServerUrl) assert.Equal(t, "user", config.Username) } func TestRemoveIfConfigNotExist(t *testing.T) { filePath := path.Join(t.TempDir(), "testpath") err := removeFilePath(filePath) assert.Error(t, err) _, err = os.Stat(filePath) assert.True(t, os.IsNotExist(err)) } func TestRemove(t *testing.T) { filePath := path.Join(t.TempDir(), "testpath") err := writeToFilePath(filePath, &pkg.Configuration{ServerUrl: "server", Username: "user"}) assert.NoError(t, err) err = removeFilePath(filePath) assert.NoError(t, err) _, err = os.Stat(filePath) assert.True(t, os.IsNotExist(err)) } func TestStoreApiKey(t *testing.T) { keyname := "scm-cli" username := "scmadmin" apiKey := "secret_key" err := storeApiKey(keyname, username, apiKey) assert.NoError(t, err) storedKey, err := readApiKey(keyname, username) assert.NoError(t, err) assert.Equal(t, apiKey, storedKey) } func TestRemoveApiKey(t *testing.T) { keyname := "scm-cli" username := "scmadmin" apiKey := "secret_key" err := keyring.Set(keyname, username, apiKey) assert.NoError(t, err) err = removeApiKey(keyname, username) assert.NoError(t, err) key, err := keyring.Get(keyname, username) assert.Empty(t, key) } 07070100000025000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002900000000scm-manager-cli-1.0.1/pkg/store/testdata07070100000026000081A400000000000000000000000162D515C000000037000000000000000000000000000000000000003900000000scm-manager-cli-1.0.1/pkg/store/testdata/cli-config.json{ "ServerUrl": "localhost", "Username": "trillian" } 07070100000027000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002300000000scm-manager-cli-1.0.1/pkg/terminal07070100000028000081A400000000000000000000000162D515C000000219000000000000000000000000000000000000003200000000scm-manager-cli-1.0.1/pkg/terminal/credentials.gopackage terminal import ( "bufio" "fmt" "golang.org/x/term" "os" "strings" ) func ReadCredentials() (string, string, error) { r := bufio.NewReader(os.Stdin) fmt.Print("Username: ") username, err := r.ReadString('\n') if err != nil { return "", "", fmt.Errorf("could not read username: %w", err) } fmt.Print("Password: ") password, err := term.ReadPassword(int(os.Stdin.Fd())) if err != nil { return "", "", fmt.Errorf("could not read password: %w", err) } return strings.TrimSpace(username), string(password), nil } 07070100000029000081A400000000000000000000000162D515C000000ACE000000000000000000000000000000000000001D00000000scm-manager-cli-1.0.1/scm.gopackage main import ( "fmt" "github.com/scm-manager/cli/pkg" "github.com/scm-manager/cli/pkg/api" "github.com/scm-manager/cli/pkg/command" "github.com/scm-manager/cli/pkg/store" "github.com/scm-manager/cli/pkg/terminal" "log" "os" "strings" ) func main() { configuration := readConfig() if configuration == nil { if len(os.Args) > 2 && os.Args[1] == "login" { login() return } else { fmt.Println("Please login first calling \"scm login 'https://{server-url:port}/scm'\"") os.Exit(1) } } if len(os.Args) > 1 && os.Args[1] == "logout" { logout(configuration) } else { executeCommand(configuration) } } func createApiKeyName() string { hostname, err := os.Hostname() if err != nil { return "scm-cli" } return "scm-cli-" + hostname } func readConfig() *pkg.Configuration { configuration, err := store.Read() if err != nil { log.Fatalf("Could not read configuration: %v", err) } return configuration } func login() { // Collect login parameters serverUrl := os.Args[2] if strings.HasSuffix(serverUrl, "/") { serverUrl = serverUrl[0 : len(serverUrl)-1] } username, password, err := terminal.ReadCredentials() // line break after Password: fmt.Println() if err != nil { printLoginError("Could not read credentials: %v", err) } // Create api key apiKey, err := api.Create(serverUrl, username, password, createApiKeyName()) if err != nil { printLoginError("Could not create api key: %v\nMost likely there is already an api key for the CLI client issued for this user/system. Please delete this api key manually on your scm server and retry to log in via the CLI.", err) } // Write Config err = store.Write(&pkg.Configuration{ServerUrl: serverUrl, Username: username, ApiKey: apiKey}) if err != nil { printLoginError("Could not write config to store: %v", err) } fmt.Println("Login successful") } func printLoginError(format string, err error) { fmt.Println() log.Fatalf(format, err) } func logout(configuration *pkg.Configuration) { err := api.Remove(configuration.ServerUrl, configuration.ApiKey, createApiKeyName()) if err != nil { fmt.Printf("Failed to remove api key from server: %v", err) fmt.Println("") fmt.Println("We suggest you remove the api key manually on your SCM-Manager server.") } err = store.Remove() if err != nil { log.Fatalf("Could not remove local config: %v", err) } fmt.Println("Successfully logged out") } func executeCommand(configuration *pkg.Configuration) { executor, err := command.CreateDefaultExecutor(configuration) if err != nil { log.Fatalf("Failed to create default executor: %v", err) } exitCode, err := executor.Execute(os.Args[1:]...) if err != nil { log.Fatalf("Failed to execute command: %v", err) } os.Exit(exitCode) } 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!111 blocks
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor