Skip to content

Commit

Permalink
Merge pull request #1 from fg-j/initial-implementation
Browse files Browse the repository at this point in the history
Initial implementation
  • Loading branch information
Frankie G-J committed Mar 12, 2021
2 parents 83d6e26 + 197c6c7 commit cc4a8a6
Show file tree
Hide file tree
Showing 155 changed files with 6,673 additions and 1 deletion.
4 changes: 4 additions & 0 deletions .github/.syncignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dependabot.yml
workflows/push-buildpackage.yml
workflows/auto-merge.yml
workflows/create-draft-release.yml
8 changes: 8 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
version: 2
updates:
- package-ecosystem: gomod
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
20 changes: 20 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Lint

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: golangci-lint
uses: golangci/golangci-lint-action@v2.3.0
with:
version: v1.32.2
77 changes: 77 additions & 0 deletions .github/workflows/test-pull-request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: Test Pull Request

on:
pull_request:
branches:
- main

jobs:
unit:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- name: Setup Go
uses: actions/setup-go@v1
with:
go-version: 1.16

- name: Checkout
uses: actions/checkout@v2

- name: Run Unit Tests
run: ./scripts/unit.sh

integration:
name: Integration Tests
runs-on: ubuntu-latest
needs: unit
steps:
- name: Setup Go
uses: actions/setup-go@v1
with:
go-version: 1.16

- name: Checkout
uses: actions/checkout@v2

- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* || true

- name: Run Integration Tests
run: ./scripts/integration.sh --use-token
env:
GIT_TOKEN: ${{ github.token }}

approve:
name: Approve Bot PRs
if: ${{ github.event.pull_request.user.login == 'paketo-bot' || github.event.pull_request.user.login == 'dependabot[bot]' }}
runs-on: ubuntu-latest
needs: integration
steps:
- name: Check Commit Verification
id: unverified-commits
uses: paketo-buildpacks/github-config/actions/pull-request/check-unverified-commits@main
with:
token: ${{ secrets.PAKETO_BOT_REVIEWER_GITHUB_TOKEN }}
repo: ${{ github.repository }}
number: ${{ github.event.number }}

- name: Check for Human Commits
id: human-commits
uses: paketo-buildpacks/github-config/actions/pull-request/check-human-commits@main
with:
token: ${{ secrets.PAKETO_BOT_REVIEWER_GITHUB_TOKEN }}
repo: ${{ github.repository }}
number: ${{ github.event.number }}

- name: Checkout
if: steps.human-commits.outputs.human_commits == 'false' && steps.unverified-commits.outputs.unverified_commits == 'false'
uses: actions/checkout@v2

- name: Auto Approve
if: steps.human-commits.outputs.human_commits == 'false' && steps.unverified-commits.outputs.unverified_commits == 'false'
uses: paketo-buildpacks/github-config/actions/pull-request/approve@main
with:
user: paketo-bot-reviewer
token: ${{ secrets.PAKETO_BOT_REVIEWER_GITHUB_TOKEN }}
author: ${{ github.event.pull_request.user.login }}
number: ${{ github.event.number }}
60 changes: 60 additions & 0 deletions .github/workflows/update-github-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Update shared github-config

on:
schedule:
- cron: '*/15 * * * *'
workflow_dispatch: {}

jobs:
build:
name: Create PR to update shared files
runs-on: ubuntu-latest
steps:

- name: Checkout
uses: actions/checkout@v2
with:
token: ${{ secrets.PAKETO_BOT_GITHUB_TOKEN }}

- name: Checkout github-config
uses: actions/checkout@v2
with:
repository: paketo-buildpacks/github-config
path: github-config

- name: Checkout Branch
uses: paketo-buildpacks/github-config/actions/pull-request/checkout-branch@main
with:
branch: automation/github-config/update

- name: Run the sync action
uses: paketo-buildpacks/github-config/actions/sync@sync-action
with:
workspace: /github/workspace
config: /github/workspace/github-config/implementation

- name: Cleanup
run: rm -rf github-config

- name: Commit
id: commit
uses: paketo-buildpacks/github-config/actions/pull-request/create-commit@main
with:
message: "Updating github-config"
pathspec: "."
keyid: ${{ secrets.PAKETO_BOT_GPG_SIGNING_KEY_ID }}
key: ${{ secrets.PAKETO_BOT_GPG_SIGNING_KEY }}

- name: Push Branch
if: ${{ steps.commit.outputs.commit_sha != '' }}
uses: paketo-buildpacks/github-config/actions/pull-request/push-branch@main
with:
branch: automation/github-config/update

- name: Open Pull Request
if: ${{ steps.commit.outputs.commit_sha != '' }}
uses: paketo-buildpacks/github-config/actions/pull-request/open@main
with:
token: ${{ secrets.PAKETO_BOT_GITHUB_TOKEN }}
title: "Updates github-config"
branch: automation/github-config/update
Empty file added .packit
Empty file.
70 changes: 69 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,69 @@
# hugo-buildpack
# Hugo Cloud Native Buildpack

The Hugo CNB provides [Hugo](https://gohugo.io) and uses it to generate static
assets. These static assets can be served with a server like HTTPD. The
buildpack does *not* install any server for the assets.

The buildpack detects true if the app contains a `content` directory that
contains at least one Markdown or HTML file.

The buildpack places generated static files in `<app root>/output`.

## Integration

The Hugo CNB provides the `hugo` dependency (it puts the Hugo CLI on the
`$PATH`). Downstream buildpacks can require the `hugo` dependency by generating
a [Build Plan
TOML](https://github.com/buildpacks/spec/blob/master/buildpack.md#build-plan-toml)
file that looks like the following:

```toml
[[requires]]

# The name of the dependency is "hugo".
name = "hugo"

# The Hugo buildpack supports some non-required metadata options.
[requires.metadata]

# Setting the build flag to true will ensure that the Hugo
# depdendency is available on the $PATH for subsequent buildpacks during
# their build phase. If you are writing a buildpack that needs to run Hugo
# during its build process, this flag should be set to true.
build = true

# Setting the launch flag to true will ensure that the Hugo
# dependency is available on the $PATH for the running application. If you are
# writing an application that needs to run Hugo at runtime, this flag should
# be set to true.
launch = true
```

## Usage

To package this buildpack for consumption:

```
$ ./scripts/package.sh --version <x.y.z>
```

This builds the buildpack's Go source using `GOOS=linux` by default. You can
supply another value as the first argument to `package.sh`.

Once you have packaged the buildpack, you can build a site with it using the
[pack CLI](https://github.com/buildpacks/pack):
```bash
cd my-hugo-site-directory
pack build hugo-site /
--buildpack paketobuildpacks/httpd:latest
--buildpack /path/to/hugo-buildpack/build/buildpack.tgz
--buildpack gcr.io/paketo-community/build-plan:latest
--builder paketobuildpacks/builder:full
```

Note: The above example assumes that you'll use
[HTTPD](https://httpd.apache.org/) to serve the static assets. The [Paketo
HTTPD CNB](https://github.com/paketo-buildpacks/httpd) can install the server
in your app container. See the sample app in
[`integration/testdata/default_site`](integration/testdata/default_site) for a
complete working example app.
101 changes: 101 additions & 0 deletions build.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package hugobuildpack

import (
"bytes"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/paketo-buildpacks/packit"
"github.com/paketo-buildpacks/packit/pexec"
"github.com/paketo-buildpacks/packit/postal"
"github.com/paketo-buildpacks/packit/scribe"
)

//go:generate faux --interface EntryResolver --output fakes/entry_resolver.go
type EntryResolver interface {
Resolve(name string, entries []packit.BuildpackPlanEntry, priorities []interface{}) (packit.BuildpackPlanEntry, []packit.BuildpackPlanEntry)
MergeLayerTypes(name string, entries []packit.BuildpackPlanEntry) (bool, bool)
}

//go:generate faux --interface DependencyManager --output fakes/dependency_manager.go
type DependencyManager interface {
Resolve(path, id, version, stack string) (postal.Dependency, error)
Install(dependency postal.Dependency, cnbPath, layerPath string) error
}

//go:generate faux --interface Executable --output fakes/executable.go
type Executable interface {
Execute(pexec.Execution) error
}

func Build(entryResolver EntryResolver, dependencyManager DependencyManager, hugo Executable, logs scribe.Emitter) packit.BuildFunc {
return func(context packit.BuildContext) (packit.BuildResult, error) {
logs.Title("%s %s", context.BuildpackInfo.Name, context.BuildpackInfo.Version)

entry, _ := entryResolver.Resolve("hugo", context.Plan.Entries, nil)
entryVersion, _ := entry.Metadata["version"].(string)

dependency, err := dependencyManager.Resolve(
filepath.Join(context.CNBPath, "buildpack.toml"),
entry.Name,
entryVersion,
context.Stack)
if err != nil {
return packit.BuildResult{}, err
}

// install hugo
hugoLayer, err := context.Layers.Get("hugo")
if err != nil {
return packit.BuildResult{}, err
}

hugoLayer, err = hugoLayer.Reset()
if err != nil {
return packit.BuildResult{}, err
}

launch, build := entryResolver.MergeLayerTypes("hugo", context.Plan.Entries)
hugoLayer.Build = build
hugoLayer.Cache = build
hugoLayer.Launch = launch

logs.Process("Installing Hugo")

err = dependencyManager.Install(dependency, context.CNBPath, hugoLayer.Path)
if err != nil {
return packit.BuildResult{}, err
}

logs.Break()

// build static assets
logs.Process("Executing build process")
buffer := bytes.NewBuffer(nil)
args := []string{
"-D",
"--destination", "output",
}

logs.Subprocess("Running 'hugo %s'", strings.Join(args, " "))

err = hugo.Execute(pexec.Execution{
Args: args,
Dir: context.WorkingDir,
Stdout: buffer,
Stderr: buffer,
Env: append(os.Environ(), fmt.Sprintf("PATH=%s:%s", filepath.Join(hugoLayer.Path, "bin"), os.Getenv("PATH"))),
})

if err != nil {
return packit.BuildResult{}, err
}

return packit.BuildResult{
Plan: packit.BuildpackPlan{},
Layers: []packit.Layer{hugoLayer},
}, nil
}
}

0 comments on commit cc4a8a6

Please sign in to comment.