Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial version #1

Merged
merged 23 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0996f55
initial action scaffold
keturiosakys Jan 29, 2024
cd0e362
add mock templates for testing
keturiosakys Jan 29, 2024
6ac3857
add basic deno entry point
keturiosakys Jan 29, 2024
4866e58
update action boilerplate with cpu and arch checks
keturiosakys Jan 29, 2024
c62a824
add workflow for testing the Action
keturiosakys Jan 29, 2024
877ad19
update for cleaner exits
keturiosakys Jan 29, 2024
14ca8c4
move env variable checks inside the main function
keturiosakys Feb 2, 2024
04d70c6
set correct permissions
keturiosakys Feb 2, 2024
abc305a
update CI to point to demo temporarily
keturiosakys Feb 2, 2024
1940934
actually simplify the main script since it's a script anyway
keturiosakys Feb 2, 2024
9f6ba81
move "api helpers" into a separate file for readability
keturiosakys Feb 2, 2024
3894a73
check against API for existing templates and fork the entries into se…
keturiosakys Feb 2, 2024
6b5909f
upd templates
keturiosakys Feb 2, 2024
c4637b0
rename templates
keturiosakys Feb 2, 2024
2304405
Point deno to main.ts in the action path not just in the current
keturiosakys Feb 5, 2024
1dbdf3f
remove comment
keturiosakys Feb 5, 2024
b12616c
add README
keturiosakys Feb 5, 2024
ca7cd21
add badge
keturiosakys Feb 5, 2024
0d668a5
Apply suggestions from code review
keturiosakys Feb 6, 2024
78ab330
Apply suggestions from code review
keturiosakys Feb 7, 2024
1b87a62
short circuit the action if shasums don't match
keturiosakys Feb 7, 2024
a9362cf
update CI
keturiosakys Feb 7, 2024
8aa5be7
update README
keturiosakys Feb 7, 2024
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
17 changes: 17 additions & 0 deletions .fiberplane/templates/p1.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// For documentation on Fiberplane Templates, see: https://docs.fiberplane.com/templates
local fp = import 'fiberplane.libsonnet';
local c = fp.cell;
local fmt = fp.format;

function(
title='WE GOT P1 PPL'
)
fp.notebook
.new(title)
.setTimeRangeRelative(minutes=60)
.addLabels({})
.addCells([
c.h1('This is a section'),
c.text('You can add any types of cells and pre-fill content'),
])

17 changes: 17 additions & 0 deletions .fiberplane/templates/p2.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// For documentation on Fiberplane Templates, see: https://docs.fiberplane.com/templates
local fp = import 'fiberplane.libsonnet';
local c = fp.cell;
local fmt = fp.format;

function(
title='AAAND IT P2'
)
fp.notebook
.new(title)
.setTimeRangeRelative(minutes=60)
.addLabels({})
.addCells([
c.h1('This is a section'),
c.text('You can add any types of cells and pre-fill content'),
])

1 change: 1 addition & 0 deletions .fiberplane/templates/random_json.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
17 changes: 17 additions & 0 deletions .fiberplane/templates/template3.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// For documentation on Fiberplane Templates, see: https://docs.fiberplane.com/templates
local fp = import 'fiberplane.libsonnet';
local c = fp.cell;
local fmt = fp.format;

function(
title='TEST 3'
)
fp.notebook
.new(title)
.setTimeRangeRelative(minutes=60)
.addLabels({})
.addCells([
c.h1('This is a section'),
c.text('You can add any types of cells and pre-fill content'),
])

22 changes: 22 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Test the GitHub Action

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
steps:

- uses: actions/checkout@v4

- name: Integration test
uses: ./ # fiberplane/sync-templates@v1
id: integration-test-1
with:
api-token: ${{ secrets.FP_TOKEN }}
workspace-id: wTTZcPV5Q8qqQ-340fAEWQ

28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,29 @@
# sync-templates

[![Continuous Integration](https://github.com/fiberplane/sync-templates/actions/workflows/ci.yml/badge.svg)](https://github.com/fiberplane/sync-templates/actions/workflows/ci.yml)

The `fiberplane/sync-templates` action is a utility that syncs your Fiberplane Templates from a designated directory in your repository with your Fiberplane Workspace.

## Usage
This action can be run on `ubuntu-latest` and `macos-latest` GitHub Actions runners.

A minimum working example of the action:
```yaml
steps:
- uses: fiberplane/sync-templates@v1
with:
api-token: ${{ secrets.FP_TOKEN }} # it is best practice to keep your secrets in GitHub Secrets
workspace-id: <your_workspace_id> # you can look it up with: fp workspaces list
```

The `sync-templates` action accepts the following inputs:
- `api-token` (**required**) - the Fiberplane API token used to access the workspace
- `workspace-id` (**required**) - the ID of the workspace where the Templates should be sync'ed to
- `templates-directory` (optional) - directory where valid Templates `*.jsonnet` files are located, default: `.fiberplane/templates/`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking, maybe we should make the default without a . prefix. So something like fiberplane/templates/

To me a hidden directory is something that is secondary to the repo. For example having your own code is the primary use case of a application repo, but it might also contain a .github directory containing workflows. In the case of this action it will be run on a infrastructure like repo, where its main purpose is to store the templates.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't entirely agree here. I was actually thinking that the primary way this would be used would be per team / per project basis (kinda like hooks or workflows). Teams and/or projects might want to have project-specific templates attached in which case they become like a workflow associated with the repository code. Hence the .fiberplane/ prefix

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't entirely agree here. I was actually thinking that the primary way this would be used would be per team / per project basis (kinda like hooks or workflows). Teams and/or projects might want to have project-specific templates attached in which case they become like a workflow associated with the repository code. Hence the .fiberplane/ prefix

This kinda goes against what is planned and what you mentioned earlier, that if a template is not defined in the directory then it should be deleted. Ie. the directory should match the templates that are created 1to1. If the idea is to have this in multiple directories than that workflow is not possible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah that's a good point. I'm personally not yet entirely settled how the delete workflow should work but this is a good gotcha to keep in mind when we're discussing it

- `fp-version` (optional) - explicit version of the `fp` CLI that should be used in the action, default: `latest`
- `fp-base-url`(optional) - the base URL of the Fiberplane API, default `studio.fiberplane.com`

When run the action will:
1. Download, setup, and cache the Deno runtime and the Fiberplane CLI (`fp`).
2. Validate that the intended Templates are syntactically correct.
3. Create and/or upload the intended Templates to a Fiberplane Workspace
99 changes: 99 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: Sync Templates
description: Synchronizes Templates between your repository and Fiberplane
branding:
icon: tag
color: gray-dark

inputs:
api-token:
description: API token used to access the Fiberplane API with
required: true
workspace-id:
description: ID of the workspace to which the templates should be uploaded to
required: true
fp-base-url:
description: Base URL of the Fiberplane API
default: https://studio.fiberplane.com
templates-directory:
description: "Custom directory that should be monitored for Template JSONNET files (default: .fiberplane/templates/)"
default: .fiberplane/templates/
keturiosakys marked this conversation as resolved.
Show resolved Hide resolved
fp-version:
description: Version of the Fiberplane CLI to use (latest by default)
default: latest

runs:
using: composite
steps:

- uses: denoland/setup-deno@v1
with:
deno-version: v1.x

- name: Set up Fiberplane CLI
shell: bash
id: download
env:
FP_VERSION: ${{ inputs.fp-version }}
run: |
echo "== Setting up Fiberplane CLI =="

echo "Running on ${{ runner.arch }}"

if [ ${{ runner.arch }} = "ARM64" ]; then
FP_ARCH="aarch64"
elif [ ${{ runner.arch }} = "X86" ] || [ ${{ runner.arch }} = "X64" ]; then
FP_ARCH="x86_64"
else
echo "Fiberplane CLI supports only x86_64 and ARM64 CPU architectures"
exit 1
fi

echo "Running on ${{ runner.os }}"

if [ ${{ runner.os }} = "Linux" ]; then
FP_OS="unknown-linux-gnu"
elif [ ${{ runner.os }} = "macOS" ]; then
FP_OS="apple-darwin"
else
echo "Fiberplane CLI supports only Linux and macOS"
exit 1
fi

if [ "$FP_VERSION" != "latest" ]; then
FP_VERSION="v${FP_VERSION}"
fi

echo "Going to install: $FP_VERSION version of fp"

URL="https://fp.dev/fp/${FP_VERSION}/${FP_ARCH}-${FP_OS}"

EXPECTED_SHA256SUM="$(curl -H user-agent:fiberplane-github-action -s -L "${URL}/checksum.sha256" | grep fp | awk '{print $1;}')"

curl -H user-agent:fiberplane-github-action -L "${URL}/fp" -o fp

ACTUAL_SHA256SUM=$(sha256sum fp | awk '{print $1;}')

echo "Expected sha256: $EXPECTED_SHA256SUM"
echo "Actual sha256: $ACTUAL_SHA256SUM"

if [ "$ACTUAL_SHA256SUM" != "$EXPECTED_SHA256SUM" ]; then
exit 1
fi

chmod +x fp
sudo mv fp /usr/local/bin
keturiosakys marked this conversation as resolved.
Show resolved Hide resolved

- name: Run template validate and sync
shell: bash
env:
API_TOKEN: ${{ inputs.api-token }}
WORKSPACE_ID: ${{ inputs.workspace-id }}
FP_BASE_URL: ${{ inputs.fp-base-url }}
TEMPLATES_DIRECTORY: ${{ inputs.templates-directory }}
run: |
deno run \
--allow-read \
--allow-env \
--allow-run=/usr/local/bin/fp \
--allow-net=${{ inputs.fp-base-url }} \
${{ github.action_path }}/main.ts
157 changes: 157 additions & 0 deletions api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// functions for interacting with the fp-cli, should be replaced with a proper
// API client when we get around to it

const FP = "/usr/local/bin/fp";
const decoder = new TextDecoder();

type Template = {
id: string;
name: string;
description: string;
created_at: string;
updated_at: string;
};

export async function createTemplate(
templateFile: string,
templatesDirectory: string,
apiToken: string,
workspaceId: string,
fpBaseUrl: string,
) {
console.log(`Creating template ${templatesDirectory + templateFile}`);

const command = new Deno.Command(FP, {
cwd: templatesDirectory,
args: [
"templates",
"create",
templateFile,
"--template-name",
templateFile.replace(".jsonnet", ""),
"--description",
templateFile.replace(".jsonnet", ""),
"--create-trigger",
"false",
],
clearEnv: true,
env: {
FP_TOKEN: apiToken,
API_BASE: fpBaseUrl,
WORKSPACE_ID: workspaceId,
},
});

const { code, stdout: stdoutBuf, stderr: stderrBuf } = await command.output();

const stderr = decoder.decode(stderrBuf);
const stdout = decoder.decode(stdoutBuf);

if (code !== 0) {
console.log(stdout + stderr);
throw new Error(stderr);
}

console.log(stdout + stderr);
}

export async function listTemplates(
apiToken: string,
workspaceId: string,
fpBaseUrl: string,
): Promise<Template[]> {
const command = new Deno.Command(FP, {
args: ["templates", "list", "--output", "json"],
clearEnv: true,
env: {
FP_TOKEN: apiToken,
API_BASE: fpBaseUrl,
WORKSPACE_ID: workspaceId,
},
});

const { code, stdout: stdoutBuf, stderr: stderrBuf } = await command.output();

const stderr = decoder.decode(stderrBuf);
const stdout = decoder.decode(stdoutBuf);

if (code !== 0) {
console.log(stdout + stderr);
throw new Error(stderr);
}

let out;

try {
out = JSON.parse(stdout);
} catch (err) {
console.log(stdout + stderr);
throw new Error(err);
}

return out;
}

export async function updateTemplate(
templateFile: string,
templatesDirectory: string,
apiToken: string,
workspaceId: string,
fpBaseUrl: string,
) {
console.log(`Updating template ${templatesDirectory + templateFile}`);

const command = new Deno.Command(FP, {
cwd: templatesDirectory,
args: [
"templates",
"update",
templateFile.replace(".jsonnet", ""),
"--template-path",
templateFile,
],
clearEnv: true,
env: {
FP_TOKEN: apiToken,
API_BASE: fpBaseUrl,
WORKSPACE_ID: workspaceId,
},
});

const { code, stdout: stdoutBuf, stderr: stderrBuf } = await command.output();

const stderr = decoder.decode(stderrBuf);
const stdout = decoder.decode(stdoutBuf);

if (code !== 0) {
console.log(stdout + stderr);
throw new Error(stderr);
}

console.log(stdout + stderr);
}

export async function validateTemplate(
templateFile: string,
templatesDirectory: string,
) {
console.log(`Validating template ${templatesDirectory + templateFile}`);

const command = new Deno.Command(FP, {
cwd: templatesDirectory,
args: ["templates", "validate", templateFile],
clearEnv: true,
});

const { code, stdout: stdoutBuf, stderr: stderrBuf } = await command.output();

const stderr = decoder.decode(stderrBuf);
const stdout = decoder.decode(stdoutBuf);

if (code !== 0) {
console.log(stdout + stderr);
throw new Error(stderr);
}

console.log(stdout + stderr);
}
1 change: 1 addition & 0 deletions deno.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
7 changes: 7 additions & 0 deletions deno.lock

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

Loading