Skip to content
This repository has been archived by the owner on Dec 13, 2022. It is now read-only.

Commit

Permalink
Merge pull request #5 from doughepi/v1
Browse files Browse the repository at this point in the history
Initial Release
  • Loading branch information
Piper Dougherty authored Dec 24, 2021
2 parents a0bbfdc + b003dbe commit fadddba
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 137 deletions.
16 changes: 11 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ on:
pull_request:
push:
branches:
- main
- 'releases/*'

jobs:
# unit tests
Expand All @@ -15,11 +13,19 @@ jobs:
- run: npm ci
- run: npm test

# test action works running from the graph
test:
simple-integration-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm ci
- uses: ./
with:
milliseconds: 1000
files: example-env/simple/env.yaml
- name: Check action returns correct value for environment variable
run: |
if [[ $WEBSERVER_URL =~ "www.example.com" ]]; then
echo "Pass"
else
echo "Test failed: output was not 'www.example.com'"
exit 1
fi
3 changes: 2 additions & 1 deletion CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
* @actions/actions-runtime
* @doughepi
* @actions/actions-runtime
61 changes: 39 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,38 @@ take multiple YAML files input that override eachother, allowing for multi-envir

## Usage

With configuration file in the root directory of your project
```yaml
# env.yaml
name: Example Config
webserver:
url: www.example.com
```
And the following added to your GitHub Workflow
```yaml
- name: Load environment from YAML
uses: doughepi/yaml-env-action
with:
files: env1.yaml env2.yaml # Pass a space-separated list of configuration files. Rightmost files take precedence.
files: env1.yaml # Pass a space-separated list of configuration files. Rightmost files take precedence.
```
Access the newly exported environment variable in the following steps of your GitHub Workflow.
```yaml
...
steps:
- uses: actions/checkout@v2
- name: Load environment from YAML
uses: doughepi/yaml-env-action
with:
files: env1.yaml # Pass a space-separated list of configuration files. Rightmost files take precedence.
- run: echo "${{ env.WEBSERVER_URL }}"
...
```

## Simple Example
## Another Example

A simple example...

Expand Down Expand Up @@ -195,42 +219,35 @@ You end up with the following environment variables.
* `API_SERVICE_DNS=my-d.apiservice.com`


### Releasing

GitHub Actions will run the entry point from the action.yml. Packaging assembles the code into one file that can be checked in to Git, enabling fast and reliable execution and preventing the need to check in node_modules.
### Contributing

Actions are run from GitHub repos. Packaging the action will create a packaged action in the dist folder.
All contributions are welcome. Create an issue for questions, bugs, and features. Feel free to submit pull requests, as well. The overall development process is detailed below.

Run prepare
#### Development Process

```bash
npm run prepare
```
Create a development branch to make your changes within.

Since the packaged index.js is run from the dist folder.
Get the `node_modules/`

```bash
git add dist
npm install
```

Users shouldn't consume the action from master since that would be latest code and actions can break compatibility between major versions.
On your branch, you can make changes and push. The `test.yml` GitHub Workflow on this repository will kick off on each push, running simple unit and integration tests. Take a look at `test.yml` for more info on how this works. Feel free to add additional integration tests to verify your changes result in correct operation of the `yaml-env-action`.

Checkin to the v1 release branch
You can also run the unit tests locally.

```bash
git checkout -b v1
git commit -a -m "v1 release"
npm test
```

Before you create a pull request, you'll need to make sure the `dist/` folder is fully up to date with your changes.

```bash
git push origin v1
npm run prepare
```

Note: We recommend using the `--license` option for ncc, which will create a license file for all of the production node modules used in your project.

Your action is now published! :rocket:

See the [versioning documentation](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md)
Releases will be handled by @doughepi using tags and releases on the `main` branch.

<p align="center">&mdash; ⭐️ &mdash;</p>
<p align="center"><i>yaml-env-action is <a href="https://github.com/doughepi/yaml-env-action/blob/main/LICENSE">MIT licensed</a> code. Designed & built in Minneapolis, MN. Used at General Mills.</i></p>
61 changes: 35 additions & 26 deletions dist/index.js

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

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions example-env/simple/env.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: Test
webserver:
url: www.example.com
61 changes: 35 additions & 26 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ const { env } = require('process');

const FILES_INPUT_NAME = "files";
const SPLIT_CHARACTER = " ";
const VALID_EXTENSIONS = /(\.yml|\.yaml)$/i
const ENV_DELIMETER = '_';

/**
* Check for the existence of a file.
*
* @param {string} path
* @returns
* @param {string} path The path to the file.
* @returns True if the file exists, false otherwise.
*/
const fileExists = async path => !!(await fs.promises.stat(path).catch(e => false));

Expand All @@ -26,21 +26,14 @@ const fileExists = async path => !!(await fs.promises.stat(path).catch(e => fals
* @returns An array of strings that represent the indvidiual files.
*/
const splitFiles = async str => {

if (str === null || str === undefined || str === '') {
// Return empty array if null, undefined, or empty string.
if (!str || str === undefined || str === null) {
return [];
}

return str.split(SPLIT_CHARACTER);
}

/**
*
* @param {string} file
* @returns
*/
const verifyExtension = async file => VALID_EXTENSIONS.test(file);

/**
* Take a list of objects and merge them into a single object, taking the last value for each key. After merging,
* flatten the object and convert all keys to constant-case.
Expand All @@ -59,8 +52,8 @@ const verifyExtension = async file => VALID_EXTENSIONS.test(file);
* Result:
* - { NAME: 'application-dev', BUCKET: 'f46cc6e2-86e3-428d-b266-612d7913ef2d', WEB_SERVICE_DNS: 'my-d.webservice.com', API_SERVICE_DNS: 'my-d.apiservice.com' }
*
* @param {Object[]} objs
* @returns
* @param {Object[]} objs A list of objects to merge.
* @returns The merged object.
*/
const getEnvironment = async objs => {
if (!Array.isArray(objs)) {
Expand All @@ -69,7 +62,11 @@ const getEnvironment = async objs => {

let environment = {}
objs.forEach((obj) => {
environment = deepmerge(environment, obj, { arrayMerge: (_destinationArray, sourceArray) => sourceArray });
environment = deepmerge(environment, obj, {
arrayMerge: (_destinationArray, sourceArray) => {
return sourceArray
}
});
})

environment = flatten(environment, {
Expand All @@ -81,39 +78,51 @@ const getEnvironment = async objs => {
};

/**
*
* Run the action process by reading the files, merging them into a single environment, and then setting the environment variables.
*/
const run = async () => {
try {
const rawFileNames = core.getInput(FILES_INPUT_NAME);
core.debug(`Files: ${rawFileNames}`);

const environments = [];
const splitFileNames = await splitFiles(rawFileNames);
for (let fileName in splitFileNames) {
core.debug(`Split files: ${splitFileNames}`);

const environments = [];
for (let fileName of splitFileNames) {
core.debug(`Processing file: ${fileName}`);

let isValidExtension = verifyExtension(fileName);
let exists = await fileExists(fileName);
core.debug(`File ${fileName} exists: ${exists}`);

if (isValidExtension && exists) {
let fileEnvironment = yaml.parse(fs.readFileSync(fileName, 'utf8'));
environments.push(fileEnvironment);
if (!exists) {
throw Error(`File does not exist: ${fileName}`)
}

core.debug(`Loading file ${fileName}`);
let fileEnvironment = yaml.parse(fs.readFileSync(fileName, 'utf8'));
core.debug(`File content: ${JSON.stringify(fileEnvironment)}`);

environments.push(fileEnvironment);
}

const resultingEnvironment = getEnvironment(environments);

core.debug(`Successfuly loaded ${environments.length} files`);
core.debug(`Now merging ${environments.length} files`);

const resultingEnvironment = await getEnvironment(environments);

Object.keys(resultingEnvironment).forEach(key => {
core.exportVariable(key, resultingEnvironment[key]);
core.info(`export ${key}=${resultingEnvironment[key]}`);
});
} catch (error) {
core.setFailed(error.message);
core.setFailed(error);
}
};

run()

module.exports = {
splitFiles,
verifyExtension,
getEnvironment
}
Loading

0 comments on commit fadddba

Please sign in to comment.