Skip to content

Commit

Permalink
Merge pull request #2 from PRODYNA/feature/1-make-template-configurable
Browse files Browse the repository at this point in the history
Feature/1 make template configurable
  • Loading branch information
dkrizic authored Mar 2, 2024
2 parents be44e4d + 144abec commit a77b4b5
Show file tree
Hide file tree
Showing 8 changed files with 297 additions and 220 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Build the Docker image
run: docker build . --file Dockerfile --tag my-image-name:$(date +%s)
run: docker build . --file Dockerfile --tag deployment-overview:latest
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,17 @@ go buid main.go -o deployment-overview

## Parrameters

| Paramter | Environment | Required | Default | Example | Description |
| --- | --- |-------|---------|---------------------------------------------------------------------------------|-------------------------------------------------------------------------------|
| --github-token | GITHUB_TOKEN | true | - | - | The GitHub Personal Access Token (PAT) |
| --environments | ENVIRONMENTS | true | - | dev,staging,prod | Environments to query. Comma separated list. |
| --organization | ORGANIZATION | true | - | myorga | The GitHub Organization to query for repositories. |
| --repositories | REPOSITORIES | true | - | frontend,backend | Repositories to query. Comma separated list. |
| --target-repository | TARGET_REPOSITORY | true | - | .github | The target repository to commit the result to. |
| --target-repository-file | TARGET_REPOSITORY_FILE | true | - | profile/README.md | The target repository file to commit the result to. |
| --verbose | VERBOSE | false | 1 | 0 | Verbosity level, 0=info, 1=debug. Overrides the environment variable VERBOSE. |
| Paramter | Environment | Required | Default | Example | Description |
| --- | --- |-------|---------|-----------------------------------------------------------------------------|-------------------------------------------------------------------------------|
| --github-token | GITHUB_TOKEN | true | - | - | The GitHub Personal Access Token (PAT) |
| --environments | ENVIRONMENTS | true | - | dev,staging,prod | Environments to query. Comma separated list. |
| --organization | ORGANIZATION | true | - | myorga | The GitHub Organization to query for repositories. |
| --repositories | REPOSITORIES | true | - | frontend,backend | Repositories to query. Comma separated list. |
| --target-repository | TARGET_REPOSITORY | true | - | .github | The target repository to commit the result to. |
| --target-repository-file | TARGET_REPOSITORY_FILE | true | - | profile/README.md | The target repository file to commit the result to. |
| --verbose | VERBOSE | false | 1 | 0 | Verbosity level, 0=info, 1=debug. Overrides the environment variable VERBOSE. |
| --environment-links | ENVIRONMENT_LINKS | false | - | https://dev.example.com,https://staging.example.com,https://www.example.com | Links to the environments. Comma separated list. |
| --template-file | TEMPLATE_FILE | false | - | template/default.md | The template file to use. |

## Use as GitHub Action

Expand All @@ -70,7 +72,9 @@ jobs:
target-repository-file: profile/README.md
repositories: frontend,backend,infrastructure
environments: dev,staging,prod
environment-links: https://dev.example.com,https://staging.example.com,https://www.example.com
verbose: 1
template-file: template/default.md
github-token: ${{ secrets.OVERVIEW_GITHUB_TOKEN }}
```
Note that you have to use a GitHub Personal Access Token (PAT) as a secret.
Expand Down
15 changes: 15 additions & 0 deletions action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ inputs:
description: 'The list of environments to monitor'
required: true
default: 'dev,staging,prod'
environment-links:
description: 'The list of links to the environments'
required: true
default: 'https://dev.example.com,https://staging.example.com,https://prod.example.com'
verbose:
description: 'The verbosity level'
required: true
Expand All @@ -27,14 +31,25 @@ inputs:
github-token:
description: 'The token to use for the GitHub API'
required: true
title:
description: 'The title of the overview'
required: true
default: 'Deployment overview'
template-file:
description: 'The template file to use for the overview'
required: true
default: 'template/default.tpl'
runs:
using: 'docker'
image: 'Dockerfile'
args:
- --organization=${{ inputs.organization }}
- --repositories=${{ inputs.repositories }}
- --environments=${{ inputs.environments }}
- --environment-links=${{ inputs.environment-links }}
- --verbose=${{ inputs.verbose }}
- --target-repository=${{ inputs.target-repository }}
- --target-repository-file=${{ inputs.target-repository-file }}
- --github-token=${{ inputs.github-token }}
- --title=${{ inputs.title }}
- --template-file=${{ inputs.template-file }}
39 changes: 31 additions & 8 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ const (
keyRepositories = "REPOSITORIES"
keyGithubToken = "GITHUB_TOKEN"
keyEnvironments = "ENVIRONMENTS"
keyEnvironmentLinks = "ENVIRONMENT_LINKS"
keyVerbose = "VERBOSE"
keyTemplateFile = "TEMPLATE_FILE"
keyTitle = "TITLE"
)

type Config struct {
Expand All @@ -27,17 +30,23 @@ type Config struct {
TargetRepositoryFile string
Repositories string
Environments string
EnvironmentLinks string
GithubToken string
TemplateFile string
Title string
}

func CreateConfig(ctx context.Context) (*Config, error) {
config := Config{}
flag.StringVar(&config.Organization, "organization", lookupEnvOrString(keyOrganization, ""), "The GitHub Organization to query for repositories.")
flag.StringVar(&config.TargetRepository, "target-repository", lookupEnvOrString(keyTargetRepository, ""), "The target repository to commit the result to.")
flag.StringVar(&config.TargetRepositoryFile, "target-repository-file", lookupEnvOrString(keyTargetRepositoryFile, ""), "The target repository file to commit the result to.")
flag.StringVar(&config.Repositories, "repositories", lookupEnvOrString(keyRepositories, ""), "Repositories to query. Comma separated list.")
flag.StringVar(&config.GithubToken, "github-token", lookupEnvOrString(keyGithubToken, ""), "The GitHub Token to use for authentication.")
flag.StringVar(&config.Environments, "environments", lookupEnvOrString(keyEnvironments, ""), "Environments to query. Comma separated list.")
c := Config{}
flag.StringVar(&c.Organization, "organization", lookupEnvOrString(keyOrganization, ""), "The GitHub Organization to query for repositories.")
flag.StringVar(&c.TargetRepository, "target-repository", lookupEnvOrString(keyTargetRepository, ""), "The target repository to commit the result to.")
flag.StringVar(&c.TargetRepositoryFile, "target-repository-file", lookupEnvOrString(keyTargetRepositoryFile, ""), "The target repository file to commit the result to.")
flag.StringVar(&c.Repositories, "repositories", lookupEnvOrString(keyRepositories, ""), "Repositories to query. Comma separated list.")
flag.StringVar(&c.GithubToken, "github-token", lookupEnvOrString(keyGithubToken, ""), "The GitHub Token to use for authentication.")
flag.StringVar(&c.Environments, "environments", lookupEnvOrString(keyEnvironments, ""), "Environments to query. Comma separated list.")
flag.StringVar(&c.EnvironmentLinks, "environment-links", lookupEnvOrString(keyEnvironmentLinks, ""), "Links to environments. Comma separated list.")
flag.StringVar(&c.TemplateFile, "template-file", lookupEnvOrString(keyTemplateFile, "template/default.tpl"), "The template file to use for rendering the result. Defaults to 'template/default.tpl'.")
flag.StringVar(&c.Title, "title", lookupEnvOrString(keyTitle, "Organization Overview"), "The title to use for the result. Defaults to 'Organization Overview'.")
verbose := flag.Int("verbose", lookupEnvOrInt(keyVerbose, 0), "Verbosity level, 0=info, 1=debug. Overrides the environment variable VERBOSE.")

logLevel := &slog.LevelVar{}
Expand All @@ -50,7 +59,17 @@ func CreateConfig(ctx context.Context) (*Config, error) {
}
flag.Parse()

return &config, nil
slog.InfoContext(ctx, "Configuration",
"Organization", c.Organization,
"Repositories", c.RepositoriesAsList(),
"Environments", c.EnvironmentsAsList(),
"EnvironmentLinks", c.EnvironmentLinksAsList(),
"TargetRepository", c.TargetRepository,
"TargetRepositoryFile", c.TargetRepositoryFile,
"TemplateFile", c.TemplateFile,
"Title", c.Title)

return &c, nil
}

func (c *Config) Validate() error {
Expand Down Expand Up @@ -86,6 +105,10 @@ func (c *Config) EnvironmentsAsList() []string {
return strings.Split(c.Environments, ",")
}

func (c *Config) EnvironmentLinksAsList() []string {
return strings.Split(c.EnvironmentLinks, ",")
}

func lookupEnvOrString(key string, defaultVal string) string {
if val, ok := os.LookupEnv(key); ok {
return val
Expand Down
118 changes: 19 additions & 99 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,41 @@ import (
"github.com/google/go-github/v59/github"
_ "github.com/google/go-github/v59/github"
"github.com/prodyna/deployment-overview/config"
"github.com/prodyna/deployment-overview/publish"
"github.com/prodyna/deployment-overview/result"
"log/slog"
"os"
)

func main() {
ctx := context.Background()
config, err := config.CreateConfig(ctx)
c, err := config.CreateConfig(ctx)
if err != nil {
slog.ErrorContext(ctx, "Unable to create configuration", "error", err)
slog.ErrorContext(ctx, "Unable to create c", "error", err)
return
}
err = config.Validate()
err = c.Validate()
if err != nil {
slog.ErrorContext(ctx, "Invalid configuration", "error", err)
slog.ErrorContext(ctx, "Invalid c", "error", err)
return
}
slog.InfoContext(ctx, "Configuration",
"Organization", config.Organization,
"Repositories", config.RepositoriesAsList(),
"Environments", config.EnvironmentsAsList(),
"TargetRepository", config.TargetRepository,
"TargetRepositoryFile", config.TargetRepositoryFile)

gh := github.NewClient(nil).WithAuthToken(config.GithubToken)
// try to load the template file
template, err := os.ReadFile(c.TemplateFile)
if err != nil {
slog.ErrorContext(ctx, "Unable to read template file", "error", err, "file", c.TemplateFile)
return
}

gh := github.NewClient(nil).WithAuthToken(c.GithubToken)
if gh == nil {
slog.ErrorContext(ctx, "Unable to create github client")
return
}

organization := &result.Organization{Name: config.Organization, Repositories: []result.Repository{}}
err = organization.IterateRepositories(ctx, gh, *config)
organization := &result.Organization{Title: c.Title, Repositories: []result.Repository{}}
err = organization.CreateEnvironmentDescriptions(ctx, c)
err = organization.IterateRepositories(ctx, gh, *c)
if err != nil {
slog.ErrorContext(ctx, "Unable to iterate repositories", "error", err)
return
Expand All @@ -49,96 +52,13 @@ func main() {
}
fmt.Printf("%s\n", json)

md, err := organization.RenderMarkdown(ctx)
md, err := organization.RenderMarkdown(ctx, string(template))
if err != nil {
slog.ErrorContext(ctx, "Unable to render organization", "error", err)
}
filename := "test.md"
err = os.WriteFile(filename, []byte(md), 0644)
if err != nil {
slog.ErrorContext(ctx, "Unable to write file", "error", err)
} else {
slog.InfoContext(ctx, "File written", "file", filename)
}

// commit to github using the API
slog.InfoContext(ctx, "Committing to github", "repository", config.TargetRepository, "organization", config.Organization, "file", config.TargetRepositoryFile)
slog.DebugContext(ctx, "Getting target repository", "repository", config.TargetRepository, "organization", config.Organization)
repo, _, err := gh.Repositories.Get(ctx, config.Organization, config.TargetRepository)
err = publish.PublishToGitHub(ctx, c, md, gh)
if err != nil {
slog.ErrorContext(ctx, "Unable to get target repository", "error", err, "repository", config.TargetRepository, "organization", config.Organization)
return
}
slog.DebugContext(ctx, "Default branch", "branch", *repo.DefaultBranch, "repository", config.TargetRepository, "organization", config.Organization)
defaultBranch := *repo.DefaultBranch

slog.DebugContext(ctx, "Getting branch", "branch", defaultBranch, "repository", config.TargetRepository, "organization", config.Organization)
branch, _, err := gh.Repositories.GetBranch(ctx, config.Organization, config.TargetRepository, defaultBranch, 0)
if err != nil {
slog.ErrorContext(ctx, "Unable to get branch", "error", err, "branch", defaultBranch)
return
}
slog.DebugContext(ctx, "Branch", "branch", branch, "repository", config.TargetRepository, "organization", config.Organization)

// create blob
slog.DebugContext(ctx, "Creating blob", "repository", config.TargetRepository, "organization", config.Organization, "file", config.TargetRepositoryFile)
blob, _, err := gh.Git.CreateBlob(ctx, config.Organization, config.TargetRepository, &github.Blob{
Content: &md,
Size: github.Int(len(md)),
})
if err != nil {
slog.ErrorContext(ctx, "Unable to create blob", "error", err)
return
}
slog.DebugContext(ctx, "Blob created", "repository", config.TargetRepository, "organization", config.Organization)

treeEntry := []*github.TreeEntry{
{
Path: github.String(config.TargetRepositoryFile),
Mode: github.String("100644"),
Type: github.String("blob"),
SHA: blob.SHA,
},
}

// create tree
slog.DebugContext(ctx, "Creating tree", "repository", config.TargetRepository, "organization", config.Organization)
tree, _, err := gh.Git.CreateTree(ctx, config.Organization, config.TargetRepository, *branch.Commit.SHA, treeEntry)
if err != nil {
slog.ErrorContext(ctx, "Unable to create tree", "error", err, "repository", config.TargetRepository, "organization", config.Organization)
return
}
slog.DebugContext(ctx, "Tree created", "repository", config.TargetRepository, "organization", config.Organization)

// create commit
slog.DebugContext(ctx, "Creating commit", "repository", config.TargetRepository, "organization", config.Organization)
commit, _, err := gh.Git.CreateCommit(ctx, config.Organization, config.TargetRepository, &github.Commit{
Message: github.String("Updated deployment overview"),
Tree: tree,
Parents: []*github.Commit{
{
SHA: branch.Commit.SHA,
},
},
}, nil)
if err != nil {
slog.ErrorContext(ctx, "Unable to create commit", "error", err, "repository", config.TargetRepository, "organization", config.Organization)
return
}
slog.DebugContext(ctx, "Commit created", "repository", config.TargetRepository, "organization", config.Organization)

// update branch
slog.DebugContext(ctx, "Updating branch", "repository", config.TargetRepository, "organization", config.Organization)
_, _, err = gh.Git.UpdateRef(ctx, config.Organization, config.TargetRepository, &github.Reference{
Ref: github.String(fmt.Sprintf("refs/heads/%s", defaultBranch)),
Object: &github.GitObject{
SHA: commit.SHA,
},
}, false)
if err != nil {
slog.ErrorContext(ctx, "Unable to update branch", "error", err, "repository", config.TargetRepository, "organization", config.Organization)
return
slog.ErrorContext(ctx, "Unable to publish to github", "error", err)
}
slog.DebugContext(ctx, "Branch updated", "repository", config.TargetRepository, "organization", config.Organization)
slog.InfoContext(ctx, "Updated deployment overview", "repository", config.TargetRepository, "organization", config.Organization)
}
Loading

0 comments on commit a77b4b5

Please sign in to comment.