Skip to content

Commit

Permalink
depsync: add xk6-depsync command
Browse files Browse the repository at this point in the history
  • Loading branch information
roobre committed Sep 22, 2023
1 parent 00c7813 commit b2111f6
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 2 deletions.
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ WORKDIR /build
COPY . .

ARG GOFLAGS="-ldflags=-w -ldflags=-s"
RUN CGO_ENABLED=0 go build -o xk6 -trimpath ./cmd/xk6/main.go
RUN CGO_ENABLED=0 go build -o xk6 -trimpath ./cmd/xk6/main.go && \
CGO_ENABLED=0 go build -o xk6-depsync -trimpath ./cmd/xk6-depsync/main.go


FROM golang:${GO_VERSION}-${VARIANT}
Expand All @@ -24,7 +25,7 @@ RUN USER=xk6 && \
mkdir -p /etc/fixuid && \
printf "user: $USER\ngroup: $GROUP\n" > /etc/fixuid/config.yml

COPY --from=builder /build/xk6 /usr/local/bin/
COPY --from=builder /build/xk6 /build/xk6-depsync /usr/local/bin/

COPY docker-entrypoint.sh /usr/local/bin/entrypoint.sh

Expand Down
112 changes: 112 additions & 0 deletions cmd/xk6-depsync/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// main is the main package for xk6-depsync, a script that checks and provides commands to synchronize
// common dependencies with k6 core.
package main

import (
"bufio"
"errors"
"fmt"
"io"
"log"
"net/http"
"os"
"sort"
"strings"
)

const (
k6Core = "go.k6.io/k6"
k6GoModURL = "https://proxy.golang.org/" + k6Core + "/@v/%s.mod"
)

func main() {
gomod := "go.mod"
if len(os.Args) >= 2 {
gomod = os.Args[1]
}

file, err := os.Open(gomod)
if err != nil {
log.Fatalf("opening local go.mod: %v", err)
}

ownDeps, err := dependencies(file)
if err != nil {
log.Fatalf("reading dependencies: %v", err)
}

k6Version := ownDeps[k6Core]
if k6Version == "" {
log.Fatalf("K6 core %q not found in %q", k6Core, gomod)
}

log.Printf("detected k6 core version %s", k6Version)

k6CoreVersionedURL := fmt.Sprintf(k6GoModURL, k6Version)
//nolint:bodyclose // Single-run script.
response, err := http.Get(k6CoreVersionedURL)
if err != nil {
log.Fatalf("error fetching k6 go.mod: %v", err)
}

if response.StatusCode != http.StatusOK {
log.Fatalf("got HTTP status %d for %s", response.StatusCode, k6CoreVersionedURL)
}

coreDeps, err := dependencies(response.Body)
if err != nil {
log.Fatalf("reading k6 core dependencies: %v", err)
}

//nolint:prealloc // Number of mismatched deps cannot be accurately predicted.
var mismatched []string
for dep, version := range ownDeps {
coreVersion, inCore := coreDeps[dep]
if !inCore {
continue
}

if version == coreVersion {
continue
}

log.Printf("Mismatched versions for %s: %s (this package) -> %s (core)", dep, version, coreVersion)
mismatched = append(mismatched, fmt.Sprintf("%s@%s", dep, coreVersion))
}

if len(mismatched) == 0 {
log.Println("All deps are in sync, nothing to do.")
return
}

// TODO: Use slices.Sort when we move to a go version that has it on the stdlib.
sort.Strings(mismatched)

//nolint:forbidigo // We are willingly writing to stdout here.
fmt.Printf("go get %s\n", strings.Join(mismatched, " "))
}

// dependencies reads a go.mod file from an io.Reader and returns a map of dependency name to their specified versions.
func dependencies(reader io.Reader) (map[string]string, error) {
buf := bufio.NewReader(reader)

deps := make(map[string]string)
for {
line, err := buf.ReadString('\n')
if errors.Is(err, io.EOF) {
return deps, nil
}

if err != nil {
return nil, fmt.Errorf("reading go.mod: %w", err)
}

if !strings.HasPrefix(line, "\t") {
continue
}

line = strings.Trim(line, "\t\n")
depVer := strings.Split(line, " ")
deps[depVer[0]] = depVer[1]
}
}

0 comments on commit b2111f6

Please sign in to comment.