Fix API Publisher (#106)

* cleanup

* cleanup go mod

* Remove doc generation

* add no integration test

* fix broken test

* rename workflow

* readd publisher

* update words

* strip down publisher
This commit is contained in:
Asim Aslam
2021-05-17 15:55:00 +01:00
committed by GitHub
parent 114fa6735b
commit 50a6277f69
5 changed files with 250 additions and 5 deletions

103
.github/workflows/publish.yml vendored Normal file
View File

@@ -0,0 +1,103 @@
name: Publish APIs & Clients
on:
push:
branches: [master]
jobs:
docs:
name: Generate docs
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.13
uses: actions/setup-go@v2
with:
go-version: 1.13
id: go
- name: Install Protoc
uses: arduino/setup-protoc@master
- name: Check out this code
uses: actions/checkout@v2
with:
path: services
- name: Check out micro code
uses: actions/checkout@v2
with:
repository: 'micro/micro'
path: 'micro'
ref: 'master'
- name: Enable caching
uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Install protoc gen micro plugin
working-directory: micro/cmd/protoc-gen-micro
run: |
go get -u github.com/golang/protobuf/protoc-gen-go
go install
- name: Install redoc cli
run: |
# https://github.com/actions/virtual-environments/issues/599
sudo npm install -g redoc-cli
- name: Install openapi plugin
working-directory: micro/cmd/protoc-gen-openapi
run: |
go install
# - name: Install hugo
# run: sudo snap install hugo --channel=extended
- name: Generate openapi spec and publish the api
working-directory: services
run: |
go run cmd/publisher/main.go .
env:
MICRO_ADMIN_TOKEN: ${{ secrets.MICRO_ADMIN_TOKEN }}
# - name: Deploy
# if: github.ref == 'refs/heads/master'
# uses: s0/git-publish-subdir-action@develop
# env:
# REPO: self
# BRANCH: gh-pages
# FOLDER: services/docs
# GITHUB_TOKEN: ${{ secrets.GH_PAT }}
- name: Generate package
working-directory: services
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
go run cmd/clients/main.go .
# publish to github first under micro/services
# .npmrc has settings for it
- uses: JS-DevTools/npm-publish@v1
#if: github.ref == 'refs/heads/master'
with:
access: public
package: services/clients/ts/package.json
token: ${{ secrets.NPM_TOKEN }}
# publish to npm m3o/services
- name: Change npm settings
working-directory: services
run: |
rm clients/ts/.npmrc
sed -i 's/micro/m3o/g' clients/ts/package.json
- uses: JS-DevTools/npm-publish@v1
#if: github.ref == 'refs/heads/master'
with:
access: public
package: services/clients/ts/package.json
token: ${{ secrets.NPM_SITE_TOKEN }}

View File

@@ -16,11 +16,6 @@ import (
"github.com/stoewer/go-strcase"
)
const (
postContentPath = "docs/hugo-tania/site/content/post"
docsURL = "services.m3o.com"
)
func main() {
files, err := ioutil.ReadDir(os.Args[1])
if err != nil {

20
cmd/publisher/README.md Normal file
View File

@@ -0,0 +1,20 @@
# API Publisher
This scripts takes open api specs that are generated in each folder by `make proto` (see `api-users.json` and similar in each folder), and existing `README.md` and published the API.
The readmes are taken verbatim and autogenerated client call examples are appended to them to produce an output readme, so there is no need to write curl or micro cli or any other examples. Focus on the describing the service in the readmes.
Some rules on how to write protos so they nicely appear in the output of this script:
- The request types (eg. `LoginRequest`) comments will be taken and used as a description for the endpoint (eg. `Login`) itself. This might change.
- The proto message field comments will be taken and displayed to craft them with care
To provide example values use the following format:
```shell
// rss feed name
// eg. a16z
string name = 1;
```
The part after the `eg. ` until the newline will be used as example value.

127
cmd/publisher/main.go Normal file
View File

@@ -0,0 +1,127 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/getkin/kin-openapi/openapi3"
)
func publishAPI(service, readme, openapiJSON, examplesJSON string, pricing map[string]int64) error {
client := &http.Client{}
apiSpec := map[string]interface{}{
"name": service,
"description": readme,
"open_api_json": openapiJSON,
"pricing": pricing,
"examples_json": examplesJSON,
}
//Encode the data
postBody, _ := json.Marshal(map[string]interface{}{
"api": apiSpec,
})
rbody := bytes.NewBuffer(postBody)
//Leverage Go's HTTP Post function to make request
req, err := http.NewRequest("POST", "https://api.m3o.com/publicapi/Publish", rbody)
// Add auth headers here if needed
req.Header.Add("Authorization", `Bearer `+os.Getenv("MICRO_ADMIN_TOKEN"))
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
io.Copy(ioutil.Discard, resp.Body)
return nil
}
func main() {
files, err := ioutil.ReadDir(os.Args[1])
if err != nil {
log.Fatal(err)
}
workDir, _ := os.Getwd()
for _, f := range files {
if f.IsDir() && !strings.HasPrefix(f.Name(), ".") {
serviceDir := filepath.Join(workDir, f.Name())
serviceFiles, err := ioutil.ReadDir(serviceDir)
if err != nil {
fmt.Println("Failed to read service dir", err)
os.Exit(1)
}
skip := false
for _, serviceFile := range serviceFiles {
if serviceFile.Name() == "skip" {
skip = true
}
}
if skip {
continue
}
fmt.Println("Processing folder", serviceDir)
makeProto := exec.Command("make", "docs")
makeProto.Dir = serviceDir
fmt.Println(serviceDir)
outp, err := makeProto.CombinedOutput()
if err != nil {
fmt.Println("Failed to make docs", string(outp))
os.Exit(1)
}
serviceName := f.Name()
dat, err := ioutil.ReadFile(filepath.Join(serviceDir, "README.md"))
if err != nil {
fmt.Println("Failed to read readme", string(outp))
os.Exit(1)
}
apiJSON := filepath.Join(serviceDir, "api-"+serviceName+".json")
js, err := ioutil.ReadFile(apiJSON)
if err != nil {
apiJSON := filepath.Join(serviceDir, "api-protobuf.json")
js, err = ioutil.ReadFile(apiJSON)
if err != nil {
fmt.Println("Failed to read json spec", err)
os.Exit(1)
}
}
spec := &openapi3.Swagger{}
err = json.Unmarshal(js, &spec)
if err != nil {
fmt.Println("Failed to unmarshal", err)
os.Exit(1)
}
// not every service has examples
examples, _ := ioutil.ReadFile(filepath.Join(serviceDir, "examples.json"))
pricingRaw, _ := ioutil.ReadFile(filepath.Join(serviceDir, "pricing.json"))
pricing := map[string]int64{}
if len(pricingRaw) > 0 {
json.Unmarshal(pricingRaw, &pricing)
}
err = publishAPI(serviceName, string(dat), string(js), string(examples), pricing)
if err != nil {
fmt.Println("Failed to save data to publicapi service", err)
os.Exit(1)
}
}
}
}