Skip to content

Downloader helper user agent #227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 41 commits into from
Jun 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
83d1ce7
add global variables and Info struct in order to inject build time va…
Jun 5, 2019
86fecf2
replace cli.AppName with global variable global.GetAppName() getter
Jun 5, 2019
7b2337c
replaced cli.Version var with global getter
Jun 5, 2019
232632f
add .idea to .gitignore
Jun 5, 2019
1008f1f
re organize imports
Jun 5, 2019
4c44d5d
add license to global.go
Jun 5, 2019
04d91be
add hardcoded fallback version string
Jun 5, 2019
6018efd
organize imports step2
Jun 5, 2019
ca62d75
organize imports step3
Jun 5, 2019
9456352
replace cli.AppName with global variable global.GetAppName() getter
Jun 5, 2019
0fba528
re organize imports
Jun 5, 2019
241292e
add User-Agent header to downloader helper configuration
May 31, 2019
a2f4117
add testing for user agent-string generation
Jun 4, 2019
de1e994
refactor global package into version package and rename and replace h…
Jun 6, 2019
c1196a5
refactor versioning variables in version package and implement Info s…
Jun 6, 2019
8a832d5
refactor Info cosntructor to use directly package vars and renamed pa…
Jun 6, 2019
7411926
replace package name from global to version
Jun 6, 2019
2a8b48e
solve package name clash for version and cli/version
Jun 6, 2019
7415b9a
replace application name getter with VersionInfo.Application field
Jun 6, 2019
cb3a572
search and replace version string getter with VersionInfo.VersionStri…
Jun 6, 2019
2bccd1f
implement empty http.Header struct propagation from cli to resources
Jun 7, 2019
f4b2e07
align downloader helper to use propagated http.Header from upper laye…
Jun 7, 2019
ddd6bd1
align daemon to use empty http.Header as struct field in ArduinoCoreS…
Jun 7, 2019
5f571ef
clean inside cobra commands for empty http.Header struct and inject h…
Jun 7, 2019
4613a88
remove unused runDaemonCommand in daemon
Jun 7, 2019
13a12ac
add user agent specific for daemon mode via DownloaderHeaders propert…
Jun 7, 2019
a1d2a92
add testing information in README.md
Jun 7, 2019
2035384
removed getters and related usage for version package
Jun 7, 2019
b2bb96a
update dependencies
Jun 7, 2019
a363e86
finalize helpers_test User-Agent header value
Jun 10, 2019
c51d2a1
add integration test for version info injection via vars
Jun 10, 2019
3d55de0
tidy go mod and reorganize imports and tidy long lines
Jun 10, 2019
87ba210
inject ldflags variables in build task in Taskfile.yml
Jun 11, 2019
0ea3f42
replace commands in /travis.yml with tasks properly merging flags
Jun 11, 2019
685e1aa
fix install command for go-task to solve "undefined: interp.EnvFromLi…
Jun 11, 2019
5fc270c
add coverage files to .gitignore
Jun 11, 2019
e2586ca
tidy dependencies in go.mod
Jun 11, 2019
47ff9c0
update task executable path in tasks due to install path generated by…
Jun 11, 2019
b724edf
implement exported variable cli.HTTPClientHeader in order to have it …
Jun 11, 2019
b6bb5af
fix comment replacing "version config" with "global config"
Jun 11, 2019
c296fa0
leverage cli.VersionInfo to present a better terminal and json data f…
Jun 11, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
/cmd/formatter/debug.test
/arduino-cli.yaml
/wiki
.idea
coverage_*.txt
8 changes: 5 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ env:
# Make sure golangci-lint is vendored.
before_install:
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.16.0
- curl -sL https://taskfile.dev/install.sh | sh

install: true

Expand All @@ -20,9 +21,10 @@ script:
# Run linter
- golangci-lint run
# Build and test
- go build
- go test -timeout 20m -v -coverpkg=./... -coverprofile=coverage.txt -covermode=atomic ./...
- ./bin/task build
- ./bin/task test

after_success:
- bash <(curl -s https://codecov.io/bash)
- bash <(curl -s https://codecov.io/bash) -cF unittests,integration


17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -333,3 +333,20 @@ Because:
#### How can I find the core/FQBN for a board?

See: https://github.com/arduino/arduino-cli#step-4-find-and-install-the-right-core

# Testing

Currently Unit and Integration test are available for launch in 2 ways:

1. classic `go test ./...` to launch both unit and integration test

2. via [task](https://taskfile.dev) that includes the following options:

```
* build: Build the project
* test: Run the full testsuite
* test-integration: Run integration tests only
* test-unit: Run unit tests only
```

For Example to launch unit tests only run: `task test-unit`
23 changes: 20 additions & 3 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ tasks:
build:
desc: Build the project
cmds:
- go build -v -i
- go build -v -i {{.LDFLAGS}}

test:
desc: Run the full testsuite
Expand All @@ -15,9 +15,26 @@ tasks:
test-unit:
desc: Run unit tests only
cmds:
- go test -short {{ default "-v" .GOFLAGS }} {{ default "./..." .TARGETS }}
- go test -short {{ default "-v" .GOFLAGS }} -coverprofile=coverage_unit.txt {{ default "./..." .TARGETS }}

test-integration:
desc: Run integration tests only
cmds:
- go test -run Integration {{ default "-v" .GOFLAGS }} {{ default "./..." .TARGETS }}
- go test -run Integration {{ default "-v" .GOFLAGS }} -coverprofile=coverage_integ.txt {{ default "./..." .TARGETS }} {{.TEST_LDFLAGS}}

vars:
# build vars
VERSIONSTRING: "0.3.6-alpha.preview"
COMMIT:
sh: echo ${TRAVIS_COMMIT:-`git log -n 1 --format=%h`}
LDFLAGS: >
-ldflags '-X github.com/arduino/arduino-cli/version.versionString={{.VERSIONSTRING}}
-X github.com/arduino/arduino-cli/version.commit={{.COMMIT}}'

# test vars
GOFLAGS: "-timeout 5m -v -coverpkg=./... -covermode=atomic"
TEST_VERSIONSTRING: "0.0.0-test.preview"
TEST_COMMIT: "deadbeef"
TEST_LDFLAGS: >
-ldflags '-X github.com/arduino/arduino-cli/version.versionString={{.TEST_VERSIONSTRING}}
-X github.com/arduino/arduino-cli/version.commit={{.TEST_COMMIT}}'
9 changes: 5 additions & 4 deletions arduino/cores/packagemanager/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package packagemanager

import (
"fmt"
"net/http"

"github.com/arduino/arduino-cli/arduino/cores"
"go.bug.st/downloader"
Expand Down Expand Up @@ -102,16 +103,16 @@ func (pm *PackageManager) FindPlatformReleaseDependencies(item *PlatformReferenc

// DownloadToolRelease downloads a ToolRelease. If the tool is already downloaded a nil Downloader
// is returned.
func (pm *PackageManager) DownloadToolRelease(tool *cores.ToolRelease) (*downloader.Downloader, error) {
func (pm *PackageManager) DownloadToolRelease(tool *cores.ToolRelease, downloaderHeaders http.Header) (*downloader.Downloader, error) {
resource := tool.GetCompatibleFlavour()
if resource == nil {
return nil, fmt.Errorf("tool not available for your OS")
}
return resource.Download(pm.DownloadDir)
return resource.Download(pm.DownloadDir, downloaderHeaders)
}

// DownloadPlatformRelease downloads a PlatformRelease. If the platform is already downloaded a
// nil Downloader is returned.
func (pm *PackageManager) DownloadPlatformRelease(platform *cores.PlatformRelease) (*downloader.Downloader, error) {
return platform.Resource.Download(pm.DownloadDir)
func (pm *PackageManager) DownloadPlatformRelease(platform *cores.PlatformRelease, downloaderHeaders http.Header) (*downloader.Downloader, error) {
return platform.Resource.Download(pm.DownloadDir, downloaderHeaders)
}
9 changes: 6 additions & 3 deletions arduino/resources/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ package resources

import (
"fmt"
"net/http"
"os"

paths "github.com/arduino/go-paths-helper"
"github.com/arduino/go-paths-helper"
"go.bug.st/downloader"
)

Expand All @@ -45,7 +46,7 @@ func (r *DownloadResource) IsCached(downloadDir *paths.Path) (bool, error) {
}

// Download a DownloadResource.
func (r *DownloadResource) Download(downloadDir *paths.Path) (*downloader.Downloader, error) {
func (r *DownloadResource) Download(downloadDir *paths.Path, downloaderHeaders http.Header) (*downloader.Downloader, error) {
cached, err := r.TestLocalArchiveIntegrity(downloadDir)
if err != nil {
return nil, fmt.Errorf("testing local archive integrity: %s", err)
Expand Down Expand Up @@ -73,5 +74,7 @@ func (r *DownloadResource) Download(downloadDir *paths.Path) (*downloader.Downlo
return nil, fmt.Errorf("getting archive file info: %s", err)
}

return downloader.Download(path.String(), r.URL)
downloadConfig := downloader.Config{
RequestHeaders: downloaderHeaders}
return downloader.DownloadWithConfig(path.String(), r.URL, downloadConfig)
}
82 changes: 82 additions & 0 deletions arduino/resources/helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* This file is part of arduino-cli.
*
* Copyright 2018 ARDUINO SA (http://www.arduino.cc/)
*
* This software is released under the GNU General Public License version 3,
* which covers the main part of arduino-cli.
* The terms of this license can be found at:
* https://www.gnu.org/licenses/gpl-3.0.en.html
*
* You can be released from the requirements of the above licenses by purchasing
* a commercial license. Buying such a license is mandatory if you want to modify or
* otherwise use the software for commercial activities involving the Arduino
* software without disclosing the source code of your own applications. To purchase
* a commercial license, send an email to license@arduino.cc.
*/

package resources

import (
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/arduino/go-paths-helper"
"github.com/stretchr/testify/require"
)

type EchoHandler struct{}

// EchoHandler echos back the request as a response if used as http handler
func (h *EchoHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
request.Write(writer)
}

func TestDownloadApplyUserAgentHeaderUsingConfig(t *testing.T) {
goldUserAgentValue := fmt.Sprintf("arduino-cli/0.0.0-test.preview (amd64; linux; go1.12.4) Commit:deadbeef/Build:2019-06-12 11:11:11.111")
goldUserAgentString := "User-Agent: " + goldUserAgentValue

tmp, err := paths.MkTempDir("", "")
require.NoError(t, err)
defer tmp.RemoveAll()

// startup echo server
srv := httptest.NewServer(&EchoHandler{})
defer srv.Close()

r := &DownloadResource{
ArchiveFileName: "echo.txt",
CachePath: "cache",
URL: srv.URL,
}

d, err := r.Download(tmp, http.Header{"User-Agent": []string{goldUserAgentValue}})
require.NoError(t, err)
err = d.Run()
require.NoError(t, err)

// leverage the download helper to download the echo for the request made by the downloader itself
//
// expect something like:
// GET /echo HTTP/1.1
// Host: 127.0.0.1:64999
// User-Agent: arduino-cli/0.0.0-test.preview (amd64; linux; go1.12.4) Commit:deadbeef/Build:2019-06-12 11:11:11.111
// Accept-Encoding: gzip

b, err := ioutil.ReadFile(tmp.String() + "/cache/echo.txt") // just pass the file name
require.NoError(t, err)

requestLines := strings.Split(string(b), "\r\n")
userAgentHeaderString := ""
for _, line := range requestLines {
if strings.Contains(line, "User-Agent: ") {
userAgentHeaderString = line
}
}
require.Equal(t, goldUserAgentString, userAgentHeaderString)

}
5 changes: 3 additions & 2 deletions arduino/resources/resources_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package resources
import (
"crypto"
"encoding/hex"
"net/http"
"testing"

paths "github.com/arduino/go-paths-helper"
Expand All @@ -43,7 +44,7 @@ func TestDownloadAndChecksums(t *testing.T) {
require.NoError(t, err)

downloadAndTestChecksum := func() {
d, err := r.Download(tmp)
d, err := r.Download(tmp, http.Header{})
require.NoError(t, err)
err = d.Run()
require.NoError(t, err)
Expand All @@ -59,7 +60,7 @@ func TestDownloadAndChecksums(t *testing.T) {
downloadAndTestChecksum()

// Download with cached file
d, err := r.Download(tmp)
d, err := r.Download(tmp, http.Header{})
require.NoError(t, err)
require.Nil(t, d)

Expand Down
6 changes: 3 additions & 3 deletions cli/board/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ func initAttachCommand() *cobra.Command {
Use: "attach <port>|<FQBN> [sketchPath]",
Short: "Attaches a sketch to a board.",
Long: "Attaches a sketch to a board.",
Example: " " + cli.AppName + " board attach serial:///dev/tty/ACM0\n" +
" " + cli.AppName + " board attach serial:///dev/tty/ACM0 HelloWorld\n" +
" " + cli.AppName + " board attach arduino:samd:mkr1000",
Example: " " + cli.VersionInfo.Application + " board attach serial:///dev/tty/ACM0\n" +
" " + cli.VersionInfo.Application + " board attach serial:///dev/tty/ACM0 HelloWorld\n" +
" " + cli.VersionInfo.Application + " board attach arduino:samd:mkr1000",
Args: cobra.RangeArgs(1, 2),
Run: runAttachCommand,
}
Expand Down
4 changes: 2 additions & 2 deletions cli/board/board.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ func InitCommand() *cobra.Command {
Short: "Arduino board commands.",
Long: "Arduino board commands.",
Example: " # Lists all connected boards.\n" +
" " + cli.AppName + " board list\n\n" +
" " + cli.VersionInfo.Application + " board list\n\n" +
" # Attaches a sketch to a board.\n" +
" " + cli.AppName + " board attach serial:///dev/tty/ACM0 mySketch",
" " + cli.VersionInfo.Application + " board attach serial:///dev/tty/ACM0 mySketch",
}
boardCommand.AddCommand(initAttachCommand())
boardCommand.AddCommand(initDetailsCommand())
Expand Down
2 changes: 1 addition & 1 deletion cli/board/details.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func initDetailsCommand() *cobra.Command {
Use: "details <FQBN>",
Short: "Print details about a board.",
Long: "Show information about a board, in particular if the board has options to be specified in the FQBN.",
Example: " " + cli.AppName + " board details arduino:avr:nano",
Example: " " + cli.VersionInfo.Application + " board details arduino:avr:nano",
Args: cobra.ExactArgs(1),
Run: runDetailsCommand,
}
Expand Down
2 changes: 1 addition & 1 deletion cli/board/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func initListCommand() *cobra.Command {
Use: "list",
Short: "List connected boards.",
Long: "Detects and displays a list of connected boards to the current computer.",
Example: " " + cli.AppName + " board list --timeout 10s",
Example: " " + cli.VersionInfo.Application + " board list --timeout 10s",
Args: cobra.NoArgs,
Run: runListCommand,
}
Expand Down
4 changes: 2 additions & 2 deletions cli/board/listall.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ func initListAllCommand() *cobra.Command {
"List all boards that have the support platform installed. You can search\n" +
"for a specific board if you specify the board name",
Example: "" +
" " + cli.AppName + " board listall\n" +
" " + cli.AppName + " board listall zero",
" " + cli.VersionInfo.Application + " board listall\n" +
" " + cli.VersionInfo.Application + " board listall zero",
Args: cobra.ArbitraryArgs,
Run: runListAllCommand,
}
Expand Down
30 changes: 22 additions & 8 deletions cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,20 @@ package cli
import (
"context"
"errors"
"fmt"
"net/http"
"os"
"path/filepath"
"runtime"

"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
"github.com/arduino/arduino-cli/arduino/libraries/librariesmanager"
"github.com/arduino/arduino-cli/commands"
"github.com/arduino/arduino-cli/common/formatter"
"github.com/arduino/arduino-cli/configs"
"github.com/arduino/arduino-cli/rpc"
paths "github.com/arduino/go-paths-helper"
"github.com/arduino/arduino-cli/version"
"github.com/arduino/go-paths-helper"
"github.com/sirupsen/logrus"
)

Expand All @@ -48,8 +52,13 @@ const (
ErrBadArgument
)

// Version is the current CLI version
var Version = "0.3.6-alpha.preview"
// appName is the command line name of the Arduino CLI executable on the user system (users may change it)
var appName = filepath.Base(os.Args[0])

// VersionInfo contains all info injected during build
var VersionInfo = version.NewInfo(appName)

var HTTPClientHeader = getHTTPClientHeader()

// ErrLogrus represents the logrus instance, which has the role to
// log all non info messages.
Expand All @@ -61,9 +70,6 @@ var GlobalFlags struct {
OutputJSON bool // true output in JSON, false output as Text
}

// AppName is the command line name of the Arduino CLI executable
var AppName = filepath.Base(os.Args[0])

var Config *configs.Configuration

func packageManagerInitReq() *rpc.InitReq {
Expand All @@ -83,10 +89,18 @@ func packageManagerInitReq() *rpc.InitReq {
return &rpc.InitReq{Configuration: conf}
}

func getHTTPClientHeader() http.Header {
userAgentValue := fmt.Sprintf("%s/%s (%s; %s; %s) Commit:%s/Build:%s", VersionInfo.Application,
VersionInfo.VersionString, runtime.GOARCH, runtime.GOOS, runtime.Version(), VersionInfo.Commit, VersionInfo.BuildDate)
downloaderHeaders := http.Header{"User-Agent": []string{userAgentValue}}
return downloaderHeaders
}

func InitInstance() *rpc.InitResp {
logrus.Info("Initializing package manager")
req := packageManagerInitReq()
resp, err := commands.Init(context.Background(), req, OutputProgressBar(), OutputTaskProgress())

resp, err := commands.Init(context.Background(), req, OutputProgressBar(), OutputTaskProgress(), HTTPClientHeader)
if err != nil {
formatter.PrintError(err, "Error initializing package manager")
os.Exit(ErrGeneric)
Expand Down Expand Up @@ -116,7 +130,7 @@ func CreateInstance() *rpc.Instance {
for _, err := range resp.GetPlatformsIndexErrors() {
formatter.PrintError(errors.New(err), "Error loading index")
}
formatter.PrintErrorMessage("Launch '" + AppName + " core update-index' to fix or download indexes.")
formatter.PrintErrorMessage("Launch '" + VersionInfo.Application + " core update-index' to fix or download indexes.")
os.Exit(ErrGeneric)
}
return resp.GetInstance()
Expand Down
2 changes: 1 addition & 1 deletion cli/compile/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func InitCommand() *cobra.Command {
Use: "compile",
Short: "Compiles Arduino sketches.",
Long: "Compiles Arduino sketches.",
Example: " " + cli.AppName + " compile -b arduino:avr:uno /home/user/Arduino/MySketch",
Example: " " + cli.VersionInfo.Application + " compile -b arduino:avr:uno /home/user/Arduino/MySketch",
Args: cobra.MaximumNArgs(1),
Run: run,
}
Expand Down
Loading