Skip to content
Open
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
59 changes: 49 additions & 10 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,28 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: docker-build
run: docker build -t us.gcr.io/otrego-dev/apiserver:${GITHUB_RUN_NUMBER} .
run: docker build -t us.gcr.io/otrego-dev/apiserver:${GITHUB_RUN_NUMBER} -t us.gcr.io/otrego-prod/apiserver:${GITHUB_RUN_NUMBER} .
- name: Login to GCP
uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
uses: google-github-actions/setup-gcloud@master
with:
version: '281.0.0'
project_id: ${{ secrets.DEV_GCP_PROJECT_ID }}
service_account_key: ${{ secrets.DEV_GCP_SA_KEY }}
export_default_credentials: true
- name: Log into GCP Registry
run: gcloud auth configure-docker
- name: upload-build
run: docker push us.gcr.io/otrego-dev/apiserver:${GITHUB_RUN_NUMBER}


- name: Login to GCP Prod
uses: google-github-actions/setup-gcloud@master
with:
project_id: otrego-prod
service_account_key: ${{ secrets.PROD_GA_SA_KEY }}
export_default_credentials: true
- name: Log into GCP Registry
run: gcloud auth configure-docker
- name: upload-build
run: docker push us.gcr.io/otrego-prod/apiserver:${GITHUB_RUN_NUMBER}

deploy:
name: Deploy Dev
runs-on: ubuntu-latest
Expand All @@ -74,23 +83,53 @@ jobs:
- uses: actions/checkout@v2
- uses: hashicorp/setup-terraform@v1
with:
terraform_version: 0.12.26
terraform_version: 0.14.8

- name: Login to GCP
uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
uses: google-github-actions/setup-gcloud@master
with:
version: '281.0.0'
project_id: ${{ secrets.GCP_PROJECT_ID }}
service_account_key: ${{ secrets.DEV_GCP_SA_KEY }}
export_default_credentials: true

- name: Terraform Init
id: init
run: terraform init -input=false tf/
run: terraform init -input=false tf/dev

- name: Terraform Plan
id: plan
run: terraform plan -out=plan.tfplan -var="api_docker_image=us.gcr.io/otrego-dev/apiserver:${GITHUB_RUN_NUMBER}" $GITHUB_WORKSPACE/tf/
run: terraform plan -out=plan.tfplan -var="api_docker_image=us.gcr.io/otrego-dev/apiserver:${GITHUB_RUN_NUMBER}" $GITHUB_WORKSPACE/tf/dev

- name: Terraform Apply
id: tf-apply
run: terraform apply plan.tfplan

deploy-prod:
name: Deploy Prod
runs-on: ubuntu-latest
needs: deploy
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'otrego/clamshell'
steps:
- uses: actions/checkout@v2
- uses: hashicorp/setup-terraform@v1
with:
terraform_version: 0.14.8

- name: Login to GCP
uses: google-github-actions/setup-gcloud@master
with:
project_id: ${{ secrets.PROD_GCP_PROJECT_ID }}
service_account_key: ${{ secrets.PROD_GA_SA_KEY }}
export_default_credentials: true

- name: Terraform Init
id: init
run: terraform init -input=false tf/prod

- name: Terraform Plan
id: plan
run: terraform plan -out=plan.tfplan -var="api_docker_image=us.gcr.io/otrego-prod/apiserver:${GITHUB_RUN_NUMBER}" $GITHUB_WORKSPACE/tf/prod

- name: Terraform Apply
id: tf-apply
run: terraform apply plan.tfplan
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ tmp


# Terraform
tf/.terraform
tf/*.plan
.terraform
*.plan
tf/*.state

# katago analysis/gtp logs
Expand Down
37 changes: 31 additions & 6 deletions core/board/board.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,18 @@ func (b *Board) removeCapturedStones(capturedStones []*point.Point) {
// capturedStones returns the captured stones in group containing Point pt.
// returns nil if no stones were captured.
func (b *Board) capturedStones(pt *point.Point) []*point.Point {
expanded := make(map[point.Point]bool)
stoneGroup, captured := b.getStoneGroup(pt)
if captured {
return stoneGroup
}
return nil
}

// getStoneGroup returns all the points in a stone group containing point pt
// and true if the group is captured
func (b *Board) getStoneGroup(pt *point.Point) ([]*point.Point, bool) {
expanded := make(map[point.Point]bool)
captured := true
// current group color
c := b.colorAt(pt)

Expand All @@ -114,8 +124,7 @@ func (b *Board) capturedStones(pt *point.Point) []*point.Point {
if !b.inBounds(pt1) {
continue
} else if b.colorAt(pt1) == color.Empty {
// Liberty has been found, no need to continue search
return nil
captured = false
} else if b.colorAt(pt1) == c && !expanded[*pt1] {
expanded[*pt1] = true
points := b.getNeighbors(pt1)
Expand All @@ -125,14 +134,14 @@ func (b *Board) capturedStones(pt *point.Point) []*point.Point {
}
}

// The stones that were captured
// The stones in this group
stoneGroup := make([]*point.Point, len(expanded))
i := 0
for key := range expanded {
stoneGroup[i] = point.New(key.X(), key.Y())
i++
}
return stoneGroup
return stoneGroup, captured
}

// inBounds returns true if x and y are in bounds
Expand Down Expand Up @@ -170,11 +179,27 @@ func (b *Board) getNeighbors(pt *point.Point) []*point.Point {
// SetPlacements force-places moves on the go-board, without performing capture
// logic. If an illegal board position results, return an error.
func (b *Board) SetPlacements(ml move.List) error {

for _, m := range ml {
b.setColor(m)
}
// TODO(kashomon): Validate we have a valid board position -- i.e., one

// Validate we have a valid board position -- i.e., one
// without captures lying on the board.
explored := make(map[point.Point]bool)
for _, m := range ml {
pt := m.Point()

if !explored[*pt] {
stoneGroup, captured := b.getStoneGroup(pt)
if captured {
return fmt.Errorf("invalid board state. stones at points %v are captured", stoneGroup)
}
for _, point := range stoneGroup {
explored[*point] = true
}
}
}
return nil
}

Expand Down
67 changes: 67 additions & 0 deletions core/board/board_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,73 @@ func TestRemoveCapturedStones(t *testing.T) {
}
}

func TestSetPlacements(t *testing.T) {
testCases := []struct {
desc string
ml move.List
expErrSubstr string
}{
{
desc: "current placements",
ml: move.List{
move.New(color.White, point.New(1, 4)),
move.New(color.White, point.New(2, 4)),
move.New(color.White, point.New(3, 4)),

move.New(color.White, point.New(4, 1)),
move.New(color.White, point.New(4, 2)),
move.New(color.White, point.New(4, 3)),

move.New(color.White, point.New(4, 5)),
move.New(color.White, point.New(4, 6)),
move.New(color.White, point.New(4, 7)),

move.New(color.White, point.New(5, 4)),
move.New(color.White, point.New(6, 4)),
move.New(color.White, point.New(7, 4)),
},
},
{
desc: "current placements",
ml: move.List{
move.New(color.White, point.New(1, 4)),
move.New(color.White, point.New(2, 4)),
move.New(color.White, point.New(3, 4)),

move.New(color.White, point.New(4, 1)),
move.New(color.White, point.New(4, 2)),
move.New(color.White, point.New(4, 3)),

move.New(color.White, point.New(4, 5)),
move.New(color.White, point.New(4, 6)),
move.New(color.White, point.New(4, 7)),

move.New(color.White, point.New(5, 4)),
move.New(color.White, point.New(6, 4)),
move.New(color.White, point.New(7, 4)),

move.New(color.Black, point.New(4, 4)),
},
expErrSubstr: "invalid board state",
},
}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
b := New(19)
err := b.SetPlacements(tc.ml)

cerr := errcheck.CheckCases(err, tc.expErrSubstr)
if cerr != nil {
t.Error(cerr)
return
}
if err != nil {
return
}

})
}
}
func TestPlaceStone(t *testing.T) {
testCases := []struct {
desc string
Expand Down
33 changes: 20 additions & 13 deletions core/point/point.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package point

import (
"encoding/json"
"fmt"
)

Expand Down Expand Up @@ -42,21 +43,27 @@ func (pt *Point) String() string {
return fmt.Sprintf("{%d,%d}", pt.x, pt.y)
}

// Key is a convenience helper to convert this point to a key-struct.
func (pt *Point) Key() Key {
return Key{X: pt.X(), Y: pt.Y()}
// pointInternal is an internal struct for the purposes of JSON Conversion.
type pointInternal struct {
X int `json:"x"`
Y int `json:"y"`
}

// Key is a point-struct that is used for keys in maps. As such, it's intended
// to be used like the following:
//
// Key{X:12, Y:15}
type Key struct {
X int
Y int
// MarshalJSON indicates to the JSON library how to marshal a Point.
func (pt *Point) MarshalJSON() ([]byte, error) {
return json.Marshal(&pointInternal{
X: pt.x,
Y: pt.y,
})
}

// Point converts a point-Key back to a point.
func (k Key) Point() *Point {
return New(k.X, k.Y)
// UnmarshalJSON indicates to the JSON library how to unmarshal a Point.
func (pt *Point) UnmarshalJSON(data []byte) error {
var pti pointInternal
if err := json.Unmarshal(data, &pti); err != nil {
return err
}
pt.x = pti.X
pt.y = pti.Y
return nil
}
24 changes: 12 additions & 12 deletions core/point/point_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package point

import (
"encoding/json"
"fmt"
"testing"
)
Expand Down Expand Up @@ -142,18 +143,17 @@ func TestSGFToPointTranslate(t *testing.T) {
}
}

func TestKey(t *testing.T) {
pt := New(12, 15)

key := pt.Key()
exp := Key{X: 12, Y: 15}

if key != exp {
t.Errorf("error converting point to key: got %v, but expected %v", key, exp)
func TestJSON(t *testing.T) {
pt := New(1, 2)
by, err := json.Marshal(pt)
if err != nil {
t.Fatal(err)
}

back := exp.Point()
if !pt.Equal(back) {
t.Errorf("error converting key to point: got %v, but expected %v", back, pt)
var back Point
if err := json.Unmarshal(by, &back); err != nil {
t.Fatal(err)
}
if !back.Equal(pt) {
t.Fatalf("got point %v, but expected point %v", back, pt)
}
}
20 changes: 20 additions & 0 deletions tf/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion tf/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ Our infrastructure is managed with Terraform.

## Install terraform.
Note: version 0.12 is required at this time.
`brew install terraform`
`brew install tfenv`
`brew install google-cloud-sdk`
`tfenv install 0.14.8`
`tfenv use 0.14.8`
`brew install tflint`

## Credentials

Expand Down
Loading