Skip to content

Commit

Permalink
Merge pull request #98 from moul/dev/moul/airtable-more-fields
Browse files Browse the repository at this point in the history
feat: add more airtable fields + error handling
  • Loading branch information
moul authored Oct 6, 2018
2 parents 39737a9 + 06782a8 commit 0801e44
Showing 1 changed file with 96 additions and 39 deletions.
135 changes: 96 additions & 39 deletions cmd_airtable.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"encoding/json"
"reflect"
"time"

airtable "github.com/fabioberger/airtable-go"
Expand Down Expand Up @@ -79,10 +80,30 @@ func airtableSync(opts *airtableOptions) error {
}
logger().Debug("fetched airtable records", zap.Int("count", len(records)))

// create new records
for _, record := range records {
alreadyInAirtable[record.Fields.URL] = true
}
for _, issue := range issues {
if issue.Hidden {
continue
}
if _, found := alreadyInAirtable[issue.URL]; found {
continue
}
logger().Debug("creating airtable record without slices", zap.String("URL", issue.URL))
r := issue.ToAirtableRecord()
r.Fields.Labels = []string{}
r.Fields.Assignees = []string{}
if err := at.CreateRecord(opts.AirtableTableName, r); err != nil {
return err
}
}

// update/destroy existing ones
for _, record := range records {
if issue, found := issues[record.Fields.URL]; !found {
logger().Debug("destroying airtable record", zap.String("ID", record.Fields.URL))
logger().Debug("destroying airtable record", zap.String("URL", record.Fields.URL))
if err := at.DestroyRecord(opts.AirtableTableName, record.ID); err != nil {
return errors.Wrap(err, "failed to destroy record")
}
Expand All @@ -95,69 +116,105 @@ func airtableSync(opts *airtableOptions) error {
continue
}

logger().Debug("updating airtable record", zap.String("ID", issue.URL))
if err := at.UpdateRecord(opts.AirtableTableName, record.ID, issue.ToAirtableRecord().Fields.Map(), &record); err != nil {
return errors.Wrap(err, "failed to update record")
logger().Debug("updating airtable record", zap.String("URL", issue.URL))
m := issue.ToAirtableRecord().Fields.Map()
if err := at.UpdateRecord(opts.AirtableTableName, record.ID, m, &record); err != nil {
logger().Warn("failed to update record, retrying without slices", zap.String("URL", issue.URL), zap.Error(err))
m["Labels"] = []string{}
m["Assignees"] = []string{}
m["Errors"] = err.Error()
if err := at.UpdateRecord(opts.AirtableTableName, record.ID, m, &record); err != nil {
logger().Error("failed to update record without slices", zap.String("URL", issue.URL), zap.Error(err))
}
}
}
}

for _, issue := range issues {
if issue.Hidden {
continue
}
if _, found := alreadyInAirtable[issue.URL]; found {
continue
}
logger().Debug("creating airtable record", zap.String("ID", issue.URL))
if err := at.CreateRecord(opts.AirtableTableName, issue.ToAirtableRecord()); err != nil {
return err
}
}
return nil
}

type airtableRecord struct {
ID string `json:"id,omitempty"`
Fields airtableIssue `json:"fields,omitempty"`
}

func (ai airtableIssue) String() string {
out, _ := json.Marshal(ai)
return string(out)
}

func (i Issue) ToAirtableRecord() airtableRecord {
typ := "issue"
if i.IsPR {
typ = "pull-request"
}
labels := []string{}
for _, label := range i.Labels {
labels = append(labels, label.Name)
}
assignees := []string{}
for _, assignee := range i.Assignees {
assignees = append(assignees, assignee.Username)
}

return airtableRecord{
ID: "",
Fields: airtableIssue{
URL: i.URL,
Created: i.CreatedAt,
Updated: i.UpdatedAt,
Title: i.Title,
URL: i.URL,
Created: i.CreatedAt,
Updated: i.UpdatedAt,
Title: i.Title,
Type: typ,
Labels: labels,
Assignees: assignees,
Provider: string(i.Provider),
RepoURL: i.RepoURL,
Body: i.Body,
State: i.State,
},
}
}

type airtableRecord struct {
ID string `json:"id,omitempty"`
Fields airtableIssue `json:"fields,omitempty"`
}

type airtableIssue struct {
URL string
Created time.Time
Updated time.Time
Title string
URL string
Created time.Time
Updated time.Time
Title string
Provider string
State string
Body string
RepoURL string
Type string
Labels []string
Assignees []string
}

func (ai airtableIssue) Equals(other airtableIssue) bool {
return ai.URL == other.URL &&
ai.Created.Truncate(time.Millisecond).UTC() == other.Created.Truncate(time.Millisecond).UTC() &&
ai.Updated.Truncate(time.Millisecond).UTC() == other.Updated.Truncate(time.Millisecond).UTC() &&
ai.Title == other.Title
}

func (ai airtableIssue) String() string {
out, _ := json.Marshal(ai)
return string(out)
ai.Title == other.Title &&
ai.Provider == other.Provider &&
ai.State == other.State &&
ai.Body == other.Body &&
ai.RepoURL == other.RepoURL &&
ai.Type == other.Type &&
reflect.DeepEqual(ai.Labels, other.Labels) &&
reflect.DeepEqual(ai.Assignees, other.Assignees)
}

func (a airtableIssue) Map() map[string]interface{} {
return map[string]interface{}{
"URL": a.URL,
"Created": a.Created,
"Updated": a.Updated,
"Title": a.Title,
"URL": a.URL,
"Created": a.Created,
"Updated": a.Updated,
"Title": a.Title,
"Provider": a.Provider,
"State": a.State,
"Body": a.Body,
"RepoURL": a.RepoURL,
"Type": a.Type,
"Labels": a.Labels,
"Assignees": a.Assignees,
}
}

0 comments on commit 0801e44

Please sign in to comment.