Detailed changes
@@ -1,182 +0,0 @@
-name: CD
-
-on:
- push:
- branches:
- - main
- pull_request:
-
-
-jobs:
- cd:
- strategy:
- matrix:
- go-version: [~1.17]
- runs-on: ubuntu-latest
- env:
- GO111MODULE: "on"
- CONTAINER_REPO: "ghcr.io/${{ github.repository }}"
- ENVIRONMENT: development
- AWS_DEFAULT_REGION: us-east-1
- AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
- AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- SOFT_SERVE_REPO_KEYS: "${{ secrets.SOFT_SERVE_REPO_KEYS }}"
-
- steps:
- - name: Install Go
- uses: actions/setup-go@v2
- with:
- go-version: ${{ matrix.go-version }}
-
- - name: Checkout code
- uses: actions/checkout@v2
- with:
- fetch-depth: 0
-
- # Remove this later
- - name: Clone internal repositories
- run: |
- git clone -b release https://${{ secrets.ACCESS_TOKEN }}@github.com/charmbracelet/charm-internal ../charm
- git clone -b master https://${{ secrets.ACCESS_TOKEN }}@github.com/charmbracelet/bubbletea-internal ../bubbletea
- git clone -b master https://${{ secrets.ACCESS_TOKEN }}@github.com/charmbracelet/wish ../wish
-
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v1
- if: github.event_name == 'push'
- with:
- registry: ghcr.io
- username: ${{ github.repository_owner }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Build Docker images using GoReleaser
- uses: goreleaser/goreleaser-action@master
- if: github.event_name == 'push'
- with:
- version: latest
- # https://github.com/goreleaser/goreleaser/discussions/1534
- args: -f .goreleaser.yml --snapshot
-
- # Must add GH Actions write access
- # https://docs.github.com/en/packages/managing-github-packages-using-github-actions-workflows/publishing-and-installing-a-package-with-github-actions
- - name: Push Docker images
- if: github.event_name == 'push'
- run: |
- docker push $CONTAINER_REPO:snapshot
- docker push $CONTAINER_REPO:$GITHUB_SHA-snapshot
-
- - name: Setup Terraform
- uses: hashicorp/setup-terraform@v1
- with:
- # terraform_version: 0.13.0
- cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
-
- - name: Terraform Variables
- id: tfvars
- run: |
- cat <<EOF >live.auto.tfvars
- environment = "$ENVIRONMENT"
- aws_region = "$AWS_DEFAULT_REGION"
- app_image = "$CONTAINER_REPO:$GITHUB_SHA-snapshot"
- authorization_keys = <<EOT
- $SOFT_SERVE_REPO_KEYS
- EOT
- EOF
- TF_VARS="-var-file=live.auto.tfvars"
- echo "::set-output name=vars::$TF_VARS"
-
- - name: Terraform Format
- id: fmt
- run: terraform fmt -check
-
- - name: Terraform Init
- id: init
- run: terraform init
-
- - name: Terraform Validate
- id: validate
- run: terraform validate -no-color
-
- - name: Terraform Plan
- id: plan
- if: github.event_name == 'pull_request'
- run: terraform plan -no-color ${{ steps.tfvars.outputs.vars }}
- continue-on-error: true
-
- - name: Find Comment
- if: github.event_name == 'pull_request'
- uses: peter-evans/find-comment@v1.2.0
- id: fc
- with:
- issue-number: ${{ github.event.pull_request.number }}
- comment-author: github-actions[bot]
- body-includes: Terraform Summary
-
- - name: Update Pull Request
- uses: actions/github-script@0.9.0
- if: github.event_name == 'pull_request'
- env:
- PLAN: "${{ steps.plan.outputs.stdout }}"
- COMMENT_ID: "${{ steps.fc.outputs.comment-id }}"
- with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
- script: |
- const output = `## Terraform Summary
- - Terraform Format and Style 🖌 \`${{ steps.fmt.outcome }}\`
- - Terraform Initialization ⚙️ \`${{ steps.init.outcome }}\`
- - Terraform Plan 📖 \`${{ steps.plan.outcome }}\`
- - Terraform Validation 🤖 \`${{ steps.validate.outcome }}\`
-
- <details><summary>Show Plan</summary>
-
- \`\`\`\n
- ${process.env.PLAN}
- \`\`\`
-
- </details>
-
- *Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`;
-
- if (process.env.COMMENT_ID) {
- github.issues.updateComment({
- owner: context.repo.owner,
- repo: context.repo.repo,
- comment_id: process.env.COMMENT_ID,
- body: output
- })
- } else {
- github.issues.createComment({
- issue_number: context.issue.number,
- owner: context.repo.owner,
- repo: context.repo.repo,
- body: output
- })
- }
-
- - name: Terraform Plan Status
- if: steps.plan.outcome == 'failure'
- run: exit 1
-
-
- - name: Terraform Apply
- if: github.ref == 'refs/heads/main' && github.event_name == 'push'
- run: terraform apply -auto-approve ${{ steps.tfvars.outputs.vars }}
-
-
- slack-workflow-status:
- if: github.ref == 'refs/heads/main' && github.event_name == 'push'
- name: Post Workflow Status To Slack
- needs:
- - cd
- runs-on: ubuntu-latest
- steps:
- - name: Slack Workflow Notification
- uses: Gamesight/slack-workflow-status@master
- with:
- # Required Input
- repo_token: ${{ secrets.GITHUB_TOKEN }}
- slack_webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }}
- # Optional Input
- channel: '#devops'
- name: "${{ github.repository }} 🥤 workflow"
- icon_emoji: ':cup_with_straw:'
- icon_url: 'https://avatars.githubusercontent.com/u/57376114?s=200&v=4'
@@ -1,34 +0,0 @@
-name: CI
-
-on:
- push:
- branches: [ main ]
- pull_request:
-
-jobs:
-
- build:
- strategy:
- matrix:
- go-version: [~1.17]
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
-
- # Remove this later
- - name: Clone internal repositories
- run: |
- git clone -b release https://${{ secrets.ACCESS_TOKEN }}@github.com/charmbracelet/charm-internal ../charm
- git clone -b master https://${{ secrets.ACCESS_TOKEN }}@github.com/charmbracelet/bubbletea-internal ../bubbletea
- git clone -b master https://${{ secrets.ACCESS_TOKEN }}@github.com/charmbracelet/wish ../wish
-
- - name: Set up Go
- uses: actions/setup-go@v2
- with:
- go-version: ${{ matrix.go-version }}
-
- - name: Build
- run: go build -v ./...
-
- - name: Test
- run: go test -v ./...
@@ -1,22 +0,0 @@
-name: Soft-Serve
-
-on:
- push:
- branches:
- - main
-
-jobs:
- softserve:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout code
- uses: actions/checkout@v2
- with:
- fetch-depth: 0
-
- - name: Push to Soft-Serve
- uses: charmbracelet/soft-serve-action@v1
- with:
- server: "beta.charm.sh"
- ssh-key: "${{ secrets.CHARM_SOFT_SERVE_KEY }}"
- name: "soft-serve"
@@ -1,7 +1,3 @@
-soft-serve
-.ssh
-.repos
-dist
-.terraform*
-*.tfstate*
-*auto.tfvars
+cmd/soft/soft
+cmd/soft/.ssh
+cmd/soft/.repos
@@ -1,23 +0,0 @@
-FROM alpine:latest
-
-RUN apk update && apk add --update nfs-utils git && rm -rf /var/cache/apk/*
-
-COPY soft-serve /usr/local/bin/soft-serve
-
-# Create directories
-WORKDIR /soft-serve
-# Expose data volume
-VOLUME /soft-serve
-
-# Environment variables
-ENV SOFT_SERVE_KEY_PATH "/soft-serve/ssh/soft_serve_server_ed25519"
-ENV SOFT_SERVE_REPO_KEYS ""
-ENV SOFT_SERVE_REPO_KEYS_PATH "/soft-serve/ssh/soft_serve_git_authorized_keys"
-ENV SOFT_SERVE_REPO_PATH "/soft-serve/repos"
-
-# Expose ports
-# SSH
-EXPOSE 23231/tcp
-
-# Set the default command
-ENTRYPOINT [ "/usr/local/bin/soft-serve" ]
@@ -0,0 +1,37 @@
+package main
+
+import (
+ "log"
+
+ "github.com/charmbracelet/soft"
+
+ "github.com/meowgorithm/babyenv"
+)
+
+type serverConfig struct {
+ Host string `env:"SOFT_SERVE_HOST" default:""`
+ Port int `env:"SOFT_SERVE_PORT" default:"23231"`
+ KeyPath string `env:"SOFT_SERVE_KEY_PATH" default:".ssh/soft_serve_server_ed25519"`
+ RepoPath string `env:"SOFT_SERVE_REPO_PATH" default:".repos"`
+ AuthKey string `env:"SOFT_SERVE_AUTH_KEY" default:""`
+}
+
+func main() {
+ var cfg serverConfig
+ err := babyenv.Parse(&cfg)
+ if err != nil {
+ log.Fatalln(err)
+ }
+ s := soft.NewServer(
+ cfg.Host,
+ cfg.Port,
+ cfg.KeyPath,
+ cfg.RepoPath,
+ cfg.AuthKey,
+ )
+ log.Printf("Starting SSH server on %s:%d\n", cfg.Host, cfg.Port)
+ err = s.ListenAndServe()
+ if err != nil {
+ log.Fatalln(err)
+ }
+}
@@ -6,8 +6,8 @@ import (
"fmt"
"os"
"path/filepath"
- "soft-serve/git"
+ "github.com/charmbracelet/soft/git"
gg "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
)
@@ -1,4 +1,4 @@
-module soft-serve
+module github.com/charmbracelet/soft
go 1.17
@@ -1,59 +0,0 @@
-package main
-
-import (
- "fmt"
- "log"
- "soft-serve/config"
- "soft-serve/git"
- "soft-serve/tui"
-
- "github.com/charmbracelet/wish"
- bm "github.com/charmbracelet/wish/bubbletea"
- gm "github.com/charmbracelet/wish/git"
- lm "github.com/charmbracelet/wish/logging"
- "github.com/gliderlabs/ssh"
-
- "github.com/meowgorithm/babyenv"
-)
-
-type serverConfig struct {
- Port int `env:"SOFT_SERVE_PORT" default:"23231"`
- Host string `env:"SOFT_SERVE_HOST" default:""`
- InitKey string `env:"SOFT_SERVE_REPO_KEY" default:""`
- KeyPath string `env:"SOFT_SERVE_KEY_PATH" default:".ssh/soft_serve_server_ed25519"`
- RepoPath string `env:"SOFT_SERVE_REPO_PATH" default:".repos"`
-}
-
-func main() {
- var scfg serverConfig
- var cfg *config.Config
- var err error
- err = babyenv.Parse(&scfg)
- if err != nil {
- log.Fatalln(err)
- }
- rs := git.NewRepoSource(scfg.RepoPath)
- cfg, err = config.NewConfig(scfg.Host, scfg.Port, scfg.InitKey, rs)
- if err != nil {
- log.Fatalln(err)
- }
- s, err := wish.NewServer(
- ssh.PublicKeyAuth(cfg.PublicKeyHandler),
- ssh.PasswordAuth(cfg.PasswordHandler),
- wish.WithAddress(fmt.Sprintf("%s:%d", scfg.Host, scfg.Port)),
- wish.WithHostKeyPath(scfg.KeyPath),
- wish.WithMiddlewares(
- bm.Middleware(tui.SessionHandler(cfg)),
- gm.Middleware(scfg.RepoPath, cfg),
- lm.Middleware(),
- ),
- )
- if err != nil {
- log.Fatalln(err)
- }
- log.Printf("Starting SSH server on %s:%d\n", scfg.Host, scfg.Port)
- err = s.ListenAndServe()
- if err != nil {
- log.Fatalln(err)
- }
-}
@@ -1,45 +0,0 @@
-terraform {
- backend "s3" {
- bucket = "charm-terraform-backend"
- key = "soft-serve-development"
- region = "us-east-1"
- }
-}
-
-variable "environment" {
- default = "development"
-}
-
-variable "aws_region" {
- default = "us-east-1"
-}
-
-variable "app_image" {
- default = "ghcr.io/charmbracelet/soft-serve-internal:snapshot"
-}
-
-variable "force_new_deployment" {
- default = false
-}
-
-variable "authorization_keys" {
- default = ""
-}
-
-module "soft_serve" {
- # source = "../terraform-aws-soft-serve"
- source = "app.terraform.io/charm/soft-serve/aws"
- version = "0.3.2"
-
- environment = var.environment
- aws_region = var.aws_region
- ecs_task_execution_role_name = "softServeEcsTaskExecutionRole-${var.environment}"
- app_image = var.app_image
- app_count = 2
- app_ssh_port = 23231
- fargate_cpu = "1024"
- fargate_memory = "2048"
- force_new_deployment = var.force_new_deployment
- app_use_default_ssh_port = true
- authorization_keys = var.authorization_keys
-}
@@ -0,0 +1,44 @@
+package soft
+
+import (
+ "fmt"
+ "log"
+
+ "github.com/charmbracelet/soft/config"
+ "github.com/charmbracelet/soft/git"
+ "github.com/charmbracelet/soft/tui"
+
+ "github.com/charmbracelet/wish"
+ bm "github.com/charmbracelet/wish/bubbletea"
+ gm "github.com/charmbracelet/wish/git"
+ lm "github.com/charmbracelet/wish/logging"
+ "github.com/gliderlabs/ssh"
+)
+
+// NewServer returns a new *ssh.Server configured to serve Soft Serve. The SSH
+// server key-pair will be created if none exists. An initial admin SSH public
+// key can be provided with authKey. If authKey is provided, access will be
+// restricted to that key. If authKey is not provided, the server will be
+// publicly writable until configured otherwise by cloning the `config` repo.
+func NewServer(host string, port int, serverKeyPath string, repoPath string, authKey string) *ssh.Server {
+ rs := git.NewRepoSource(repoPath)
+ cfg, err := config.NewConfig(host, port, authKey, rs)
+ if err != nil {
+ log.Fatalln(err)
+ }
+ s, err := wish.NewServer(
+ ssh.PublicKeyAuth(cfg.PublicKeyHandler),
+ ssh.PasswordAuth(cfg.PasswordHandler),
+ wish.WithAddress(fmt.Sprintf("%s:%d", host, port)),
+ wish.WithHostKeyPath(serverKeyPath),
+ wish.WithMiddlewares(
+ bm.Middleware(tui.SessionHandler(cfg)),
+ gm.Middleware(repoPath, cfg),
+ lm.Middleware(),
+ ),
+ )
+ if err != nil {
+ log.Fatalln(err)
+ }
+ return s
+}
@@ -2,15 +2,15 @@ package tui
import (
"fmt"
- "soft-serve/config"
- "soft-serve/git"
- "soft-serve/tui/bubbles/repo"
- "soft-serve/tui/bubbles/selection"
- "soft-serve/tui/style"
"strings"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
+ "github.com/charmbracelet/soft/config"
+ "github.com/charmbracelet/soft/git"
+ "github.com/charmbracelet/soft/tui/bubbles/repo"
+ "github.com/charmbracelet/soft/tui/bubbles/selection"
+ "github.com/charmbracelet/soft/tui/style"
)
type sessionState int
@@ -1,7 +1,7 @@
package commits
import (
- "soft-serve/git"
+ "soft-serve/server/git"
"strings"
"github.com/charmbracelet/bubbles/viewport"
@@ -4,8 +4,6 @@ import (
"bytes"
"fmt"
"log"
- "soft-serve/git"
- "soft-serve/tui/style"
"strconv"
"text/template"
"time"
@@ -14,6 +12,8 @@ import (
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/glamour"
"github.com/charmbracelet/lipgloss"
+ "github.com/charmbracelet/soft/git"
+ "github.com/charmbracelet/soft/tui/style"
"github.com/muesli/reflow/truncate"
"github.com/muesli/reflow/wrap"
)
@@ -1,11 +1,11 @@
package selection
import (
- "soft-serve/tui/style"
"strings"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
+ "github.com/charmbracelet/soft/tui/style"
"github.com/muesli/reflow/truncate"
)
@@ -3,13 +3,13 @@ package tui
import (
"fmt"
"log"
- "soft-serve/config"
- "soft-serve/tui/bubbles/repo"
- "soft-serve/tui/bubbles/selection"
"time"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
+ "github.com/charmbracelet/soft/config"
+ "github.com/charmbracelet/soft/tui/bubbles/repo"
+ "github.com/charmbracelet/soft/tui/bubbles/selection"
"github.com/muesli/termenv"
)
@@ -1,94 +0,0 @@
-package tui
-
-import (
- "os"
- "path/filepath"
- "soft-serve/git"
-
- gg "github.com/go-git/go-git/v5"
- "github.com/go-git/go-git/v5/plumbing/object"
-)
-
-const defaultReadme = "# Soft-Serve\n\n Welcome! You can configure your Soft-Serve server by cloning this repo and pushing changes.\n\n## Repos\n\n{{ range .Menu }}* {{ .Name }}{{ if .Note }} - {{ .Note }} {{ end }}\n - `git clone ssh://{{$.Host}}:{{$.Port}}/{{.Repo}}`\n{{ end }}"
-
-const defaultConfig = `{
- "name": "Soft-Serve",
- "show_all_repos": true,
- "host": "localhost",
- "port": 23231,
- "menu": [
- {
- "name": "Home",
- "repo": "config",
- "note": "Configuration and content repo for this server"
- }
- ]
-}`
-
-func createFile(path string, content string) error {
- f, err := os.Create(path)
- if err != nil {
- return err
- }
- defer f.Close()
- _, err = f.WriteString(content)
- if err != nil {
- return err
- }
- return f.Sync()
-}
-
-func createDefaultConfigRepo(rs *git.RepoSource) error {
- cn := "config"
- err := rs.LoadRepos()
- if err != nil {
- return err
- }
- _, err = rs.GetRepo(cn)
- if err == git.ErrMissingRepo {
- cr, err := rs.InitRepo(cn, false)
- if err != nil {
- return err
- }
-
- rp := filepath.Join(rs.Path, cn, "README.md")
- err = createFile(rp, defaultReadme)
- if err != nil {
- return err
- }
- cp := filepath.Join(rs.Path, cn, "config.json")
- err = createFile(cp, defaultConfig)
- if err != nil {
- return err
- }
- wt, err := cr.Repository.Worktree()
- if err != nil {
- return err
- }
- _, err = wt.Add("README.md")
- if err != nil {
- return err
- }
- _, err = wt.Add("config.json")
- if err != nil {
- return err
- }
- _, err = wt.Commit("Default init", &gg.CommitOptions{
- All: true,
- Author: &object.Signature{
- Name: "Soft-Serve Server",
- Email: "vt100@charm.sh",
- },
- })
- if err != nil {
- return err
- }
- err = rs.LoadRepos()
- if err != nil {
- return err
- }
- } else if err != nil {
- return err
- }
- return nil
-}
@@ -2,9 +2,9 @@ package tui
import (
"fmt"
- "soft-serve/config"
tea "github.com/charmbracelet/bubbletea"
+ "github.com/charmbracelet/soft/config"
"github.com/gliderlabs/ssh"
)