Skip to content

Commit

Permalink
Merge pull request #2 from duplocloud/release/0.3.1
Browse files Browse the repository at this point in the history
Release v0.3.1
  • Loading branch information
joek-duplo authored Mar 18, 2022
2 parents c83b5ae + 837862e commit 52a1c6b
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 153 deletions.
65 changes: 65 additions & 0 deletions .github/workflows/finish-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Finish Release
on:
pull_request:
types:
- closed
branches:
- master
env:
git_user: duplo-bot
git_email: [email protected]
jobs:
finish-release:
if: github.event.pull_request.merged == true && (startsWith(github.head_ref, 'refs/heads/release/') || startsWith(github.head_ref, 'release/'))
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: master # Always finish releases from the "merged to" master
fetch-depth: 0
persist-credentials: false # Needed so we can push with different credentials.
# NOTE: Pushing with different credentials allows admins to push protected branches.
# NOTE: Pushing with different credentials allow workflows to trigger from the push.

# FINISH THE RELEASE
- name: Initialize mandatory git config
run: |
git config --global user.name $git_user &&
git config --global user.email $git_email
- name: Finish gitflow release
id: finish-release
uses: duplocloud/ghactions-finish-gitflow-release@master
with:
github_token: ${{ secrets.DUPLO_GITHUB_TOKEN }}

version-bump:
runs-on: ubuntu-latest
needs:
- finish-release
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: develop

# BUMP THE DEVELOPMENT VERSION
- name: Initialize mandatory git config
run: |
git config --global user.name $git_user &&
git config --global user.email $git_email
- name: Version bump
run: |
set -euo pipefail
current="$(sed -ne 's/^VERSION=\([0-9\.]*\).*$/\1/p' <Makefile)"
bump="$(( ${current##*.} + 1))"
prefix="${current%.*}"
sed -e 's/^\(VERSION=\)[0-9\.]*/\1'"${prefix}.${bump}"'/g' -i Makefile
git commit -m 'version bump' Makefile
- name: Push develop
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.DUPLO_GITHUB_TOKEN }}
branch: develop
58 changes: 58 additions & 0 deletions .github/workflows/start-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Start Release
on:
workflow_dispatch:
inputs:
version:
description: 'Override Version'
required: false
default: '' # default to current version
env:
git_user: duplo-bot
git_email: [email protected]
jobs:
start-release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: develop # Always release from develop
fetch-depth: 0
persist-credentials: false # Needed so we can push with different credentials.
# NOTE: Pushing with different credentials allows admins to push protected branches.
# NOTE: Pushing with different credentials allow workflows to trigger from the push.

# GET THE RELEASE VERSION
- name: Get release version
id: version
run: |
# Fail on errors
set -euo pipefail
# Use the current version if it is not being overridden
if [ -z "${{ github.event.inputs.version }}" ]; then
echo "::set-output name=release::$(sed -ne 's/^VERSION=\([0-9\.]*\).*$/\1/p' <Makefile)"
# Otherwise, the use the overridden version.
else
echo "::set-output name=release::${{ github.event.inputs.version }}"
fi
# START THE RELEASE
- name: Initialize mandatory git config
run: |
git config --global user.name $git_user &&
git config --global user.email $git_email
- name: Start gitflow release
uses: duplocloud/ghactions-start-gitflow-release@master
with:
github_token: ${{ secrets.DUPLO_GITHUB_TOKEN }}
version: "${{ steps.version.outputs.release }}"
precommit_run: |
# Fail on errors
set -euo pipefail
if [ -z "${{ github.event.inputs.version }}" ]; then
RELEASE_VERSION="${{ steps.version.outputs.release }}"
sed -e 's/^\(VERSION=\)[0-9\.]*/\1'"$RELEASE_VERSION"'/g' -i Makefile
fi
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION=0.3.0
VERSION=0.3.1

default: all

Expand Down
112 changes: 112 additions & 0 deletions cmd/duplo-aws-credential-process/cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package main

import (
"encoding/json"
"errors"
"fmt"
"log"
"os"
"path/filepath"
"time"
)

var cacheDir string
var noCache *bool

// mustInitCache initializes the cacheDir or panics.
func mustInitCache() {
var err error

if *noCache {
return
}

cacheDir, err = os.UserCacheDir()
dieIf(err, "cannot find cache directory")
cacheDir = filepath.Join(cacheDir, "duplo-aws-credential-process")
err = os.MkdirAll(cacheDir, 0700)
dieIf(err, "cannot create cache directory")
}

// cacheReadUnmarshal reads JSON and unmarshals into the target, returning true on success.
func cacheReadUnmarshal(file string, target interface{}) bool {

if !*noCache && cacheDir != "" {
file = filepath.Join(cacheDir, file)
bytes, err := os.ReadFile(file)

if err == nil {
err = json.Unmarshal(bytes, target)
if err == nil {
return true
}

log.Printf("warning: %s: invalid JSON in cache: %s", file, err)
} else if !errors.Is(err, os.ErrNotExist) {
log.Printf("warning: %s: unable to read from cache", file)
}
}

return false
}

// cacheWriteMustMarshal unmarshals the source and writes JSON.
// It returns the JSON bytes and ignores cache write failures.
func cacheWriteMustMarshal(file string, source interface{}) []byte {

// Convert the source to JSON
json, err := json.Marshal(source)
dieIf(err, "cannot marshal to JSON")

// Cache the JSON
if !*noCache {
file = filepath.Join(cacheDir, file)

err = os.WriteFile(file, json, 0600)
if err != nil {
log.Printf("warning: %s: unable to write to cache", file)
}
}

return json
}

// cacheGetAwsConfigOutput tries to read prior AWS creds fromt the cache.
func cacheGetAwsConfigOutput(cacheKey string) (creds *AwsConfigOutput) {
var file string

// Read credentials from the cache.
if !*noCache {
file = fmt.Sprintf("%s,aws-creds.json", cacheKey)
creds = &AwsConfigOutput{}
if !cacheReadUnmarshal(file, creds) {
creds = nil
}
}

// Check credentials for expiry.
if creds != nil {
five_minutes_from_now := time.Now().UTC().Add(5 * time.Minute)
expiration, err := time.Parse(time.RFC3339, creds.Expiration)

// Invalid expiration?
if err != nil {
log.Printf("warning: %s: invalid Expiration time in credentials cache: %s", cacheKey, creds.Expiration)
creds = nil

// Expires in five minutes or less?
} else if five_minutes_from_now.After(expiration) {
creds = nil
}
}

// Clear the cache if the creds expired.
if creds == nil && file != "" {
err := os.Remove(file)
if err != nil && !errors.Is(err, os.ErrNotExist) {
log.Printf("warning: %s: unable to remove from credentials cache", cacheKey)
}
}

return
}
85 changes: 8 additions & 77 deletions cmd/duplo-aws-credential-process/main.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package main

import (
"encoding/json"
"errors"
"flag"
"fmt"
"log"
"os"
"path/filepath"
"strings"
"time"

Expand Down Expand Up @@ -55,77 +53,16 @@ func convertCreds(creds *duplocloud.AwsJitCredentials) *AwsConfigOutput {

func outputCreds(creds *AwsConfigOutput, cacheKey string) {

// Convert the credentials to JSON
json, err := json.Marshal(creds)
dieIf(err, "cannot marshal credentials to JSON")
// Write the creds to the cache.
cacheFile := fmt.Sprintf("%s,aws-creds.json", cacheKey)
json := cacheWriteMustMarshal(cacheFile, creds)

// Write them out
// Write the creds to the output.
os.Stdout.Write(json)
os.Stdout.WriteString("\n")

// Cache them as well.
if (noCache == nil || !*noCache) && cacheDir != "" && cacheKey != "" {
credsCache := filepath.Join(cacheDir, fmt.Sprintf("%s,aws-creds.json", cacheKey))

err = os.WriteFile(credsCache, json, 0600)
if err != nil {
log.Printf("warning: %s: unable to write to credentials cache", cacheKey)
}
}
}

func getCachedCredentials(cacheKey string) (creds *AwsConfigOutput) {
var cacheFile string

// Read credentials from the cache.
if (noCache == nil || !*noCache) && cacheDir != "" && cacheKey != "" {
cacheFile = filepath.Join(cacheDir, fmt.Sprintf("%s,aws-creds.json", cacheKey))

bytes, err := os.ReadFile(cacheFile)
if err == nil {
creds = &AwsConfigOutput{}
err = json.Unmarshal(bytes, creds)
if err != nil {
log.Printf("warning: %s: invalid JSON in credentials cache: %s", cacheKey, err)
creds = nil
}
} else if !errors.Is(err, os.ErrNotExist) {
log.Printf("warning: %s: unable to read from credentials cache", cacheKey)
}
}

// Check credentials for expiry.
if creds != nil {
five_minutes_from_now := time.Now().UTC().Add(5 * time.Minute)
expiration, err := time.Parse(time.RFC3339, creds.Expiration)

// Invalid expiration?
if err != nil {
log.Printf("warning: %s: invalid Expiration time in credentials cache: %s", cacheKey, creds.Expiration)
creds = nil

// Expires in five minutes or less?
} else if five_minutes_from_now.After(expiration) {
creds = nil
}

// Clear the cache if the creds expired.
if creds == nil {
err = os.Remove(cacheFile)
if err != nil && !errors.Is(err, os.ErrNotExist) {
log.Printf("warning: %s: unable to remove from credentials cache", cacheKey)
}
}
}

return
}

var cacheDir string
var noCache *bool

func main() {

// Make sure we log to stderr - so we don't disturb the output to be collected by the AWS CLI
log.SetOutput(os.Stderr)

Expand Down Expand Up @@ -155,15 +92,9 @@ func main() {
dieIf(err, "invalid arguments")

// Prepare the cache directory
if noCache == nil || !*noCache {
cacheDir, err = os.UserCacheDir()
dieIf(err, "cannot find cache directory")
cacheDir = filepath.Join(cacheDir, "duplo-aws-credential-process")
err = os.MkdirAll(cacheDir, 0700)
dieIf(err, "cannot create cache directory")
}
mustInitCache()

// Gather credentials
// Get AWS credentials and output them
var creds *AwsConfigOutput
var cacheKey string
if *admin {
Expand All @@ -172,7 +103,7 @@ func main() {
cacheKey = strings.Join([]string{strings.TrimPrefix(*host, "https://"), "admin"}, ",")

// Try to find credentials from the cache.
creds = getCachedCredentials(cacheKey)
creds = cacheGetAwsConfigOutput(cacheKey)

// Otherwise, get the credentials from Duplo.
if creds == nil {
Expand All @@ -192,7 +123,7 @@ func main() {
cacheKey = strings.Join([]string{strings.TrimPrefix(*host, "https://"), "tenant", *tenantID}, ",")

// Try to find credentials from the cache.
creds = getCachedCredentials(cacheKey)
creds = cacheGetAwsConfigOutput(cacheKey)

// Otherwise, get the credentials from Duplo.
if creds == nil {
Expand Down
Loading

0 comments on commit 52a1c6b

Please sign in to comment.