Skip to content
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

build and release typegen #582

Merged
merged 2 commits into from
Jun 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,7 @@ jobs:
run: |
cd go
make all
- name: Test typegen
run: |
cd ts/typegen
make all
35 changes: 35 additions & 0 deletions .github/workflows/release-typegen.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: release-typegen

on:
push:
tags:
- release-typegen-*

jobs:
release:
runs-on: ubuntu-latest
env:
GOPATH: /home/runner/work/kpt-functions-sdk/ts/typegen
GO111MODULE: on
steps:
- name: Set up Go 1.17
uses: actions/setup-go@v1
with:
go-version: 1.17
id: go
- name: Check out code into GOPATH
uses: actions/checkout@v1
with:
path: go/src/github.com/GoogleContainerTools/kpt-functions-sdk
- name: Build, Test, Lint
run: |
cd ts/typegen
make package-typegen
- name: Set up gcloud
uses: GoogleCloudPlatform/github-actions/setup-gcloud@v0.6.0
with:
version: '388.0.0'
service_account_email: ${{ secrets.GCP_SA_EMAIL }}
service_account_key: ${{ secrets.GCP_SA_KEY }}
- name: Upload binaries
run: ./ts/scripts/publish-bins.sh $GITHUB_REF
49 changes: 49 additions & 0 deletions ts/typegen/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.PHONY: fix vet fmt test lint

GOPATH := $(shell go env GOPATH)
GOBIN := $(shell go env GOPATH)/bin
OUT_DIR := .out
MODULES = $(shell find . -name 'go.mod' -print)

all: fix fmt lint test

.PHONY: fix
fix: $(MODULES)
@for f in $(^D); do (cd $$f; echo "Fixing $$f"; go fix ./...) || exit 1; done

.PHONY: fmt
fmt: $(MODULES)
@for f in $(^D); do (cd $$f; echo "Formatting $$f"; gofmt -s -w .); done

.PHONY: lint
lint: $(MODULES)
@for f in $(^D); do \
(cd $$f; echo "Checking golangci-lint $$f"; \
(which $(GOPATH)/bin/golangci-lint || go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.44.2); \
$(GOPATH)/bin/golangci-lint run ./...); \
done

.PHONY: test
test: $(MODULES)
@for f in $(^D); do (cd $$f; echo "Testing $$f"; go test ./...) || exit 1; done

.PHONY: vet
vet: $(MODULES)
@#for f in $(^D); do (cd $$f; echo "Checking $$f"; go run honnef.co/go/tools/cmd/staticcheck@latest ./...); done
@for f in $(^D); do (cd $$f; echo "Vetting $$f"; go vet ./...); done

build-typegen: fix fmt test lint
env GOOS=linux GOARCH=amd64 go build -o $(OUT_DIR)/linux/amd64/typegen ./cmd
env GOOS=darwin GOARCH=amd64 go build -o $(OUT_DIR)/darwin/amd64/typegen ./cmd
env GOOS=windows GOARCH=amd64 go build -o $(OUT_DIR)/windows/amd64/typegen ./cmd
env GOOS=linux GOARCH=arm64 go build -o $(OUT_DIR)/linux/arm64/typegen ./cmd
env GOOS=darwin GOARCH=arm64 go build -o $(OUT_DIR)/darwin/arm64/typegen ./cmd
env GOOS=windows GOARCH=arm64 go build -o $(OUT_DIR)/windows/arm64/typegen ./cmd

package-typegen: build-typegen
tar -C $(OUT_DIR)/linux/amd64 -czvf $(OUT_DIR)/typegen_linux_amd64.tar.gz typegen
tar -C $(OUT_DIR)/darwin/amd64 -czvf $(OUT_DIR)/typegen_darwin_amd64.tar.gz typegen
tar -C $(OUT_DIR)/windows/amd64 -czvf $(OUT_DIR)/typegen_windows_amd64.tar.gz typegen
tar -C $(OUT_DIR)/linux/arm64 -czvf $(OUT_DIR)/typegen_linux_arm64.tar.gz typegen
tar -C $(OUT_DIR)/darwin/arm64 -czvf $(OUT_DIR)/typegen_darwin_arm64.tar.gz typegen
tar -C $(OUT_DIR)/windows/arm64 -czvf $(OUT_DIR)/typegen_windows_arm64.tar.gz typegen
107 changes: 107 additions & 0 deletions ts/typegen/cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"encoding/json"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"

"github.com/GoogleContainerTools/kpt-functions-sdk/ts/typegen/swagger"
"github.com/GoogleContainerTools/kpt-functions-sdk/ts/typegen/swagger/language"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

var filters []string

func init() {
mainCmd.Flags().StringSliceVar(&filters, "definitions", []string{"*"},
`Comma-delimited list of swagger Definitions to generate types for. Includes transitive dependencies.
Defaults to all Definitions if unset. Use '*' for wildcard.`)
}

var mainCmd = &cobra.Command{
Use: "typegen [SWAGGER_PATH] [OUTPUT_PATH]",
Long: "Generate TypeScript types from a swagger.json.",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
swaggerPath := args[0]
bytes, err := ioutil.ReadFile(swaggerPath)
if err != nil {
return errors.Wrap(err, "unable to find Swagger file")
}

var swaggerMap map[string]interface{}
err = json.Unmarshal(bytes, &swaggerMap)
if err != nil {
return errors.Wrap(err, "unable to parse Swagger file as JSON")
}

definitions, refMap := swagger.ParseSwagger(swaggerMap)
outPath := args[1]

err = os.MkdirAll(outPath, os.ModePerm)
if err != nil {
return err
}

return printTS(outPath, refMap, definitions)
},
}

func printTS(outPath string, refObjects map[swagger.Ref]swagger.Object, definitions []swagger.Definition) error {
pkgs := make(map[string][]swagger.Definition)
for _, definition := range definitions {
pkg := definition.Meta().Package
pkgs[pkg] = append(pkgs[pkg], definition)
}

pkgs = swagger.FilterDefinitions(filters, pkgs)

lang := language.TypeScript{
RefObjects: refObjects,
}
for pkg, defs := range pkgs {
var contents = []string{lang.PrintHeaderComment()}
header := lang.PrintHeader(defs)
if header != "" {
contents = append(contents, header)
}
sort.Slice(defs, func(i, j int) bool {
return swagger.FullName(defs[i]) < swagger.FullName(defs[j])
})
for _, definition := range defs {
contents = append(contents, lang.PrintDefinition(definition))
}

err := ioutil.WriteFile(filepath.Join(outPath, pkg+".ts"), []byte(strings.Join(contents, "\n\n")), 0644)
if err != nil {
return err
}
}

return nil
}

func main() {
err := mainCmd.Execute()
if err != nil {
os.Exit(1)
}
}
14 changes: 14 additions & 0 deletions ts/typegen/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module github.com/GoogleContainerTools/kpt-functions-sdk/ts/typegen

go 1.17

require (
github.com/google/go-cmp v0.5.8
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.4.0
)

require (
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)
14 changes: 14 additions & 0 deletions ts/typegen/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
34 changes: 34 additions & 0 deletions ts/typegen/swagger/alias.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package swagger

// Alias represents a trivial type that doesn't need a full object definition, such as a Reference or a Primitive.
type Alias struct {
DefinitionMeta
Type Type
}

// Meta implements Definition.
func (a Alias) Meta() DefinitionMeta {
return a.DefinitionMeta
}

// Imports implements Definition.
func (a Alias) Imports() []Ref {
if ref, isRef := a.Type.(Ref); isRef {
return []Ref{ref}
}
return nil
}
64 changes: 64 additions & 0 deletions ts/typegen/swagger/arrays.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package swagger

import "strings"

// Array is an array of any Type.
type Array struct {
// Items is the type of elements in the Array. Defined in the "Items" field.
Items Type

// Nested is the set of types nested in this Array. Guaranteed to be either empty or contain exactly one element.
Nested []Object
}

var _ Type = Array{}

// Imports implements Type.
func (a Array) Imports() []Ref {
// An Array's imports may be either the Item it is an array of or the imports required for its nested field.
return a.Items.Imports()
}

// NestedTypes implements Type.
func (a Array) NestedTypes() []Object {
// Arrays may define their "items" type inline, creating a nested field.
return a.Nested
}

func (p parser) parseArray(definitionMeta DefinitionMeta, o map[string]interface{}) Array {
itemsMap := getRequiredMap("items", o)
if isObject(itemsMap) {
description, _ := getString("description", itemsMap)
meta := DefinitionMeta{
Name: "Item",
Package: definitionMeta.Package,
Namespace: append(definitionMeta.Namespace, definitionMeta.Name),
Description: description,
}
object := p.parseObject(meta, itemsMap)
return Array{
Items: Ref{
Package: definitionMeta.Package,
Name: strings.Join(append(meta.Namespace, "Item"), "."),
},
Nested: []Object{object},
}
}
return Array{
Items: p.parseType(definitionMeta, itemsMap),
}
}
50 changes: 50 additions & 0 deletions ts/typegen/swagger/definition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package swagger

import "fmt"

// Definition corresponds to a specific type in a swagger.json file. This includes all types in the "definitions" map
// as well as any nested types.
type Definition interface {
// Meta returns the metadata for this Definition.
Meta() DefinitionMeta
// Imports are the imports required to use this Definition.
Imports() []Ref
}

// DefinitionMeta holds metadata common to all definitions.
type DefinitionMeta struct {
// Name is the name of the definition being declared.
Name string
// Package is the APIVersion containing this definition.
Package string
// Namespace marks nested definitions which should be contained by their outer definition if the language allows it.
Namespace []string
// Description is the human-readable textual comment describing this definition.
Description string
}

func (d DefinitionMeta) ToRef() Ref {
return Ref{
Name: d.Name,
Package: d.Package,
}
}

// FullName implements Definition.
func FullName(d Definition) string {
return fmt.Sprintf("%s.%s", d.Meta().Package, d.Meta().Name)
}
Loading