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

Circleci project setup #135

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
40 changes: 21 additions & 19 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
version: 2
# Use the latest 2.1 version of CircleCI pipeline process engine.
# See: https://circleci.com/docs/2.0/configuration-reference
version: 2.1

# Define a job to be invoked later in a workflow.
# See: https://circleci.com/docs/2.0/configuration-reference/#jobs
jobs:
release:
say-hello:
# Specify the execution environment. You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI's Developer Hub.
# See: https://circleci.com/docs/2.0/configuration-reference/#docker-machine-macos-windows-executor
docker:
- image: circleci/golang:1.16.6
working_directory: /go/src/github.com/tenderly/tenderly-cli
environment:
GO111MODULE: "on"
- image: cimg/base:stable
# Add steps to the job
# See: https://circleci.com/docs/2.0/configuration-reference/#steps
steps:
- checkout
- run: go get ./...
- run: GOOS=windows go get github.com/spf13/cobra
- run: GOOS=windows go get github.com/konsorten/go-windows-terminal-sequences
- run: curl -sL https://git.io/goreleaser | bash
- checkout
- run:
name: "Say hello"
command: "echo Hello, World!"

# Invoke jobs via workflows
# See: https://circleci.com/docs/2.0/configuration-reference/#workflows
workflows:
version: 2
release:
say-hello-workflow:
jobs:
- release:
filters:
branches:
ignore: /.*/
tags:
only: /v[0-9]+(\.[0-9]+)*(-.*)*/
- say-hello
74 changes: 74 additions & 0 deletions .github/workflows/azure-webapps-node.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# This workflow will build and push a node.js application to an Azure Web App when a commit is pushed to your default branch.
#
# This workflow assumes you have already created the target Azure App Service web app.
# For instructions see https://docs.microsoft.com/en-us/azure/app-service/quickstart-nodejs?tabs=linux&pivots=development-environment-cli
#
# To configure this workflow:
#
# 1. Download the Publish Profile for your Azure Web App. You can download this file from the Overview page of your Web App in the Azure Portal.
# For more information: https://docs.microsoft.com/en-us/azure/app-service/deploy-github-actions?tabs=applevel#generate-deployment-credentials
#
# 2. Create a secret in your repository named AZURE_WEBAPP_PUBLISH_PROFILE, paste the publish profile contents as the value of the secret.
# For instructions on obtaining the publish profile see: https://docs.microsoft.com/azure/app-service/deploy-github-actions#configure-the-github-secret
#
# 3. Change the value for the AZURE_WEBAPP_NAME. Optionally, change the AZURE_WEBAPP_PACKAGE_PATH and NODE_VERSION environment variables below.
#
# For more information on GitHub Actions for Azure: https://github.com/Azure/Actions
# For more information on the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy
# For more samples to get started with GitHub Action workflows to deploy to Azure: https://github.com/Azure/actions-workflow-samples

on:
push:
branches:
- master
workflow_dispatch:

env:
AZURE_WEBAPP_NAME: your-app-name # set this to your application's name
AZURE_WEBAPP_PACKAGE_PATH: '.' # set this to the path to your web app project, defaults to the repository root
NODE_VERSION: '14.x' # set this to the node version to use

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: npm install, build, and test
run: |
npm install
npm run build --if-present
npm run test --if-present

- name: Upload artifact for deployment job
uses: actions/upload-artifact@v2
with:
name: node-app
path: .

deploy:
runs-on: ubuntu-latest
needs: build
environment:
name: 'Development'
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}

steps:
- name: Download artifact from build job
uses: actions/download-artifact@v2
with:
name: node-app

- name: 'Deploy to Azure WebApp'
id: deploy-to-webapp
uses: azure/webapps-deploy@v2
with:
app-name: ${{ env.AZURE_WEBAPP_NAME }}
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
package: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
97 changes: 68 additions & 29 deletions commands/actions/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ package actions

import (
"fmt"
"github.com/pkg/errors"
"os"
"os/exec"
"path/filepath"
"time"

"github.com/briandowns/spinner"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"

"github.com/tenderly/tenderly-cli/commands"
"github.com/tenderly/tenderly-cli/commands/util"
"github.com/tenderly/tenderly-cli/config"
Expand All @@ -23,19 +24,21 @@ import (

var (
zipLimitBytes = 45 * 1024 * 1024 // 45 MB
srcZipped = "src/"
nodeModulesZipped = "nodejs/node_modules/"
srcPathInZip = "src/"
nodeModulesPathInZip = "nodejs/node_modules/"
possibleFileExtensions = []string{"ts", "js"}
ActionUrlPattern = "https://dashboard.tenderly.co/%s/action/%s"
)

// Set and access from commands
var (
r *rest.Rest
projectSlug string
actions *actionsModel.ProjectActions
outDir string
sources map[string]string
r *rest.Rest
projectSlug string
actions *actionsModel.ProjectActions
outDir string
sources map[string]string
logicExist bool
dependenciesExist bool
)

func init() {
Expand Down Expand Up @@ -173,7 +176,14 @@ func deployFunc(cmd *cobra.Command, args []string) {
publish(r, actions, sources, projectSlug, outDir, true)
}

func publish(r *rest.Rest, actions *actionsModel.ProjectActions, sources map[string]string, projectSlug string, outDir string, deploy bool) {
func publish(
r *rest.Rest,
actions *actionsModel.ProjectActions,
sources map[string]string,
projectSlug string,
outDir string,
deploy bool,
) {
if !deploy {
logrus.Info("\nPublishing actions:")
} else {
Expand All @@ -184,28 +194,30 @@ func publish(r *rest.Rest, actions *actionsModel.ProjectActions, sources map[str
"- %s", commands.Colorizer.Bold(commands.Colorizer.Green(actionName))))
}

sourcesDir := actions.Sources
dependenciesDir := filepath.Join(sourcesDir, typescript.NodeModulesDir)
logicZip, logicVersion := util.MustZipAndHashDir(outDir, srcPathInZip, zipLimitBytes)
if logicExist {
logicZip = nil
}

logicZip := util.MustZipDir(outDir, srcZipped, zipLimitBytes)
var (
dependenciesZip []byte
dependenciesVersion string
)

var dependenciesZip *[]byte
if util.ExistDir(dependenciesDir) {
dZip := util.MustZipDir(dependenciesDir, nodeModulesZipped, zipLimitBytes)
if len(dZip) > 0 {
dependenciesZip = &dZip
}
dependenciesDir := filepath.Join(actions.Sources, typescript.NodeModulesDir)
if !dependenciesExist {
dependenciesZip, dependenciesVersion = util.ZipAndHashDir(dependenciesDir, nodeModulesPathInZip, zipLimitBytes)
}

// TODO(marko): Send package-lock.json in publish request
request := actions2.PublishRequest{
Actions: actions.ToRequest(sources),
Deploy: deploy,
Commitish: util.GetCommitish(),
LogicZip: logicZip,
LogicVersion: nil,
DependenciesZip: dependenciesZip,
DependenciesVersion: nil,
LogicZip: &logicZip,
LogicVersion: &logicVersion,
DependenciesZip: &dependenciesZip,
DependenciesVersion: &dependenciesVersion,
}

s := spinner.New(spinner.CharSets[33], 100*time.Millisecond)
Expand Down Expand Up @@ -254,15 +266,22 @@ func mustBuildProject(sourcesDir string, tsconfig *typescript.TsConfig) {
userError.NewUserError(err,
commands.Colorizer.Sprintf(
"Failed to run: %s.",
commands.Colorizer.Bold(commands.Colorizer.Red(fmt.Sprintf("npm --prefix %s run build", sourcesDir))),
commands.Colorizer.Bold(
commands.Colorizer.Red(fmt.Sprintf("npm --prefix %s run build", sourcesDir)),
),
),
),
)
os.Exit(1)
}
}

func mustValidateAndGetSources(r *rest.Rest, actions *actionsModel.ProjectActions, projectSlug string, sourcesDir string) map[string]string {
func mustValidateAndGetSources(
r *rest.Rest,
actions *actionsModel.ProjectActions,
projectSlug string,
sourcesDir string,
) map[string]string {
logrus.Info("\nValidating actions...")

validatedSources := make(map[string]string)
Expand All @@ -272,7 +291,7 @@ func mustValidateAndGetSources(r *rest.Rest, actions *actionsModel.ProjectAction
validatedSources[name] = source
}

mustValidate(r, actions, validatedSources, projectSlug)
logicExist, dependenciesExist = mustValidate(r, actions, validatedSources, projectSlug)

return validatedSources
}
Expand Down Expand Up @@ -317,12 +336,28 @@ func mustGetSource(sourcesDir string, locator string) string {
return content
}

func mustValidate(r *rest.Rest, actions *actionsModel.ProjectActions, sources map[string]string, projectSlug string) {
// TODO(marko): Send logic & dependencies version in validate request
// Validates sources and returns if source logic exist (LogicFound) and if dependencies logic exist (DependenciesFound)
func mustValidate(
r *rest.Rest,
actions *actionsModel.ProjectActions,
sources map[string]string,
projectSlug string,
) (bool, bool) {
request := actions2.ValidateRequest{
Actions: actions.ToRequest(sources),
Actions: actions.ToRequest(sources),
LogicVersion: nil,
DependenciesVersion: nil,
}

_, logicVersion := util.MustZipAndHashDir(outDir, srcPathInZip, zipLimitBytes)

request.LogicVersion = &logicVersion

dependenciesDir := filepath.Join(actions.Sources, typescript.NodeModulesDir)

_, dependenciesVersion := util.ZipAndHashDir(dependenciesDir, nodeModulesPathInZip, zipLimitBytes)
request.DependenciesVersion = &dependenciesVersion

response, err := r.Actions.Validate(request, projectSlug)
if err != nil {
userError.LogErrorf("validate request failed",
Expand All @@ -337,13 +372,17 @@ func mustValidate(r *rest.Rest, actions *actionsModel.ProjectActions, sources ma

if len(response.Errors) > 0 {
for name, errs := range response.Errors {
logrus.Info(commands.Colorizer.Sprintf("Validation for %s failed with errors:", commands.Colorizer.Yellow(name)))
logrus.Info(
commands.Colorizer.Sprintf("Validation for %s failed with errors:", commands.Colorizer.Yellow(name)),
)
for _, e := range errs {
logrus.Info(commands.Colorizer.Sprintf("%s: %s", commands.Colorizer.Red(e.Name), e.Message))
}
}
os.Exit(1)
}

return response.LogicFound, response.DependenciesFound
}

func mustValidateTsconfig(tsconfig *typescript.TsConfig) {
Expand Down
20 changes: 20 additions & 0 deletions commands/util/zip.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package util

import (
"crypto/md5"
"encoding/hex"
"fmt"
"os"

Expand Down Expand Up @@ -37,3 +39,21 @@ func MustZipDir(dirPath string, insidePath string, limitBytes int) []byte {

return content
}

func MustZipAndHashDir(dirPath string, insidePath string, limitBytes int) ([]byte, string) {
zipped := MustZipDir(dirPath, insidePath, limitBytes)

hasher := md5.New()
hasher.Write(zipped)
hash := hex.EncodeToString(hasher.Sum(nil))

return zipped, hash
}

func ZipAndHashDir(dirPath, insidePath string, limitBytes int) ([]byte, string) {
if !ExistDir(dirPath) {
return nil, ""
}

return MustZipAndHashDir(dirPath, insidePath, limitBytes)
}
8 changes: 4 additions & 4 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ import (
)

const (
Token = "token"
Token = "0x5ff179d5109f044d7efa49a8fd7009c14ff2c9a5"
AccessKey = "access_key"
AccessKeyId = "access_key_id"

AccountID = "account_id"
Username = "username"
Email = "email"
ProjectSlug = "project_slug"
Username = "GentlemanOO7"
Email = "[email protected]"
ProjectSlug = "face-urevil"
Provider = "provider"

OrganizationName = "org_name"
Expand Down
Loading