mirror of
https://github.com/actions/javascript-action.git
synced 2025-04-07 15:59:40 +00:00
Merge pull request #331 from actions/ncalteen-format
Format and add testing/CI
This commit is contained in:
@ -1 +1,4 @@
|
||||
lib/
|
||||
dist/
|
||||
node_modules/
|
||||
coverage/
|
||||
|
@ -1,18 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"commonjs": true,
|
||||
"es6": true,
|
||||
"jest": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018
|
||||
},
|
||||
"rules": {
|
||||
}
|
||||
}
|
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1 +1 @@
|
||||
dist/** -diff linguist-generated=true
|
||||
dist/** -diff linguist-generated=true
|
4
.github/codeql/codeql-config.yml
vendored
4
.github/codeql/codeql-config.yml
vendored
@ -1,5 +1,5 @@
|
||||
name: "javascript-action CodeQL config"
|
||||
name: JavaScript CodeQL Configuration
|
||||
|
||||
paths-ignore:
|
||||
paths-ignore:
|
||||
- node_modules
|
||||
- dist
|
||||
|
6
.github/dependabot.yml
vendored
6
.github/dependabot.yml
vendored
@ -2,10 +2,16 @@ version: 2
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
labels:
|
||||
- dependabot
|
||||
- actions
|
||||
schedule:
|
||||
interval: daily
|
||||
|
||||
- package-ecosystem: npm
|
||||
directory: /
|
||||
labels:
|
||||
- dependabot
|
||||
- npm
|
||||
schedule:
|
||||
interval: daily
|
||||
|
50
.github/linters/.eslintrc.yml
vendored
Normal file
50
.github/linters/.eslintrc.yml
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
env:
|
||||
commonjs: true
|
||||
es6: true
|
||||
jest: true
|
||||
node: true
|
||||
|
||||
globals:
|
||||
Atomics: readonly
|
||||
SharedArrayBuffer: readonly
|
||||
|
||||
ignorePatterns:
|
||||
- '!.*'
|
||||
- '**/node_modules/.*'
|
||||
- '**/dist/.*'
|
||||
- '**/coverage/.*'
|
||||
- '*.json'
|
||||
|
||||
parser: '@babel/eslint-parser'
|
||||
|
||||
parserOptions:
|
||||
ecmaVersion: 2023
|
||||
sourceType: module
|
||||
requireConfigFile: false
|
||||
babelOptions:
|
||||
babelrc: false
|
||||
configFile: false
|
||||
presets:
|
||||
- jest
|
||||
|
||||
plugins:
|
||||
- jest
|
||||
|
||||
extends:
|
||||
- eslint:recommended
|
||||
- plugin:github/recommended
|
||||
- plugin:jest/recommended
|
||||
|
||||
rules:
|
||||
{
|
||||
'camelcase': 'off',
|
||||
'eslint-comments/no-use': 'off',
|
||||
'eslint-comments/no-unused-disable': 'off',
|
||||
'i18n-text/no-en': 'off',
|
||||
'import/no-commonjs': 'off',
|
||||
'import/no-namespace': 'off',
|
||||
'no-console': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'prettier/prettier': 'error',
|
||||
'semi': 'off'
|
||||
}
|
7
.github/linters/.markdown-lint.yml
vendored
Normal file
7
.github/linters/.markdown-lint.yml
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# Unordered list style
|
||||
MD004:
|
||||
style: dash
|
||||
|
||||
# Ordered list item prefix
|
||||
MD029:
|
||||
style: one
|
10
.github/linters/.yaml-lint.yml
vendored
Normal file
10
.github/linters/.yaml-lint.yml
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
rules:
|
||||
document-end: disable
|
||||
document-start:
|
||||
level: warning
|
||||
present: false
|
||||
line-length:
|
||||
level: warning
|
||||
max: 80
|
||||
allow-non-breakable-words: true
|
||||
allow-non-breakable-inline-mappings: true
|
51
.github/workflows/check-dist.yml
vendored
51
.github/workflows/check-dist.yml
vendored
@ -1,8 +1,11 @@
|
||||
# `dist/index.js` is a special file in Actions.
|
||||
# When you reference an action with `uses:` in a workflow,
|
||||
# `index.js` is the code that will run.
|
||||
# For our project, we generate this file through a build process from other source files.
|
||||
# We need to make sure the checked-in `index.js` actually matches what we expect it to be.
|
||||
# In JavaScript actions, `dist/index.js` is a special file. When you reference
|
||||
# an action with `uses:`, `dist/index.js` is the code that will be run. For this
|
||||
# project, the `dist/index.js` file is generated from other source files through
|
||||
# the build process. We need to make sure that the checked-in `dist/index.js`
|
||||
# file matches what is expected from the build.
|
||||
#
|
||||
# This workflow will fail if the checked-in `dist/index.js` file does not match
|
||||
# what is expected from the build.
|
||||
name: Check dist/
|
||||
|
||||
on:
|
||||
@ -18,33 +21,43 @@ on:
|
||||
|
||||
jobs:
|
||||
check-dist:
|
||||
name: Check dist/
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
permissions:
|
||||
contents: read
|
||||
statuses: write
|
||||
|
||||
- name: Set Node.js 16.x
|
||||
uses: actions/setup-node@v3.6.0
|
||||
steps:
|
||||
- name: Checkout
|
||||
id: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
node-version: 20
|
||||
cache: npm
|
||||
|
||||
- name: Install dependencies
|
||||
- name: Install Dependencies
|
||||
id: install
|
||||
run: npm ci
|
||||
|
||||
- name: Rebuild the dist/ directory
|
||||
run: npm run prepare
|
||||
- name: Build dist/ Directory
|
||||
id: build
|
||||
run: npm run bundle
|
||||
|
||||
- name: Compare the expected and actual dist/ directories
|
||||
- name: Compare Expected and Actual Directories
|
||||
id: diff
|
||||
run: |
|
||||
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
|
||||
echo "Detected uncommitted changes after build. See status below:"
|
||||
git diff
|
||||
if [ "$(git diff --ignore-space-at-eol --text dist/ | wc -l)" -gt "0" ]; then
|
||||
echo "Detected uncommitted changes after build. See status below:"
|
||||
git diff --ignore-space-at-eol --text dist/
|
||||
exit 1
|
||||
fi
|
||||
id: diff
|
||||
|
||||
# If index.js was different than expected, upload the expected version as an artifact
|
||||
# If index.js was different than expected, upload the expected version as
|
||||
# a workflow artifact.
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
|
||||
with:
|
||||
|
60
.github/workflows/ci.yml
vendored
Normal file
60
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
name: Continuous Integration
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- "releases/*"
|
||||
|
||||
jobs:
|
||||
test-javascript:
|
||||
name: JavaScript Tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
id: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
id: setup-node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
|
||||
- name: Install Dependencies
|
||||
id: npm-ci
|
||||
run: npm ci
|
||||
|
||||
- name: Check Format
|
||||
id: npm-format-check
|
||||
run: npm run format:check
|
||||
|
||||
- name: Lint
|
||||
id: npm-lint
|
||||
run: npm run lint
|
||||
|
||||
- name: Test
|
||||
id: npm-ci-test
|
||||
run: npm run ci-test
|
||||
|
||||
test-action:
|
||||
name: GitHub Actions Test
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
id: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Test Local Action
|
||||
id: test-action
|
||||
uses: ./
|
||||
with:
|
||||
milliseconds: 1000
|
||||
|
||||
- name: Print Output
|
||||
id: output
|
||||
run: echo "${{ steps.test-action.outputs.time }}"
|
44
.github/workflows/linter.yml
vendored
Normal file
44
.github/workflows/linter.yml
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
name: Lint Code Base
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
push:
|
||||
branches-ignore:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint Code Base
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
statuses: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
id: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
id: setup-node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
|
||||
- name: Install Dependencies
|
||||
id: install
|
||||
run: npm ci
|
||||
|
||||
- name: Lint Code Base
|
||||
id: super-linter
|
||||
uses: super-linter/super-linter/slim@v5
|
||||
env:
|
||||
DEFAULT_BRANCH: main
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
JAVASCRIPT_DEFAULT_STYLE: prettier
|
||||
VALIDATE_JSCPD: false
|
25
.github/workflows/test.yml
vendored
25
.github/workflows/test.yml
vendored
@ -1,25 +0,0 @@
|
||||
name: "units-test"
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- 'releases/*'
|
||||
|
||||
jobs:
|
||||
# unit tests
|
||||
units:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
|
||||
# test action works running from the graph
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./
|
||||
with:
|
||||
milliseconds: 1000
|
52
.gitignore
vendored
52
.gitignore
vendored
@ -1,16 +1,17 @@
|
||||
node_modules/
|
||||
|
||||
# Editors
|
||||
.vscode/
|
||||
.idea/
|
||||
*.iml
|
||||
# Dependency directory
|
||||
node_modules
|
||||
|
||||
# Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
@ -23,11 +24,12 @@ lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
@ -39,12 +41,15 @@ bower_components
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Other Dependency directories
|
||||
# Dependency directories
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
@ -62,6 +67,37 @@ typings/
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# OS metadata
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Ignore built ts files
|
||||
__tests__/runner/*
|
||||
|
||||
# IDE files
|
||||
.idea
|
||||
.vscode
|
||||
*.code-workspace
|
||||
|
3
.prettierignore
Normal file
3
.prettierignore
Normal file
@ -0,0 +1,3 @@
|
||||
dist/
|
||||
node_modules/
|
||||
coverage/
|
16
.prettierrc.json
Normal file
16
.prettierrc.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"quoteProps": "as-needed",
|
||||
"jsxSingleQuote": false,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": true,
|
||||
"bracketSameLine": true,
|
||||
"arrowParens": "avoid",
|
||||
"proseWrap": "always",
|
||||
"htmlWhitespaceSensitivity": "css",
|
||||
"endOfLine": "lf"
|
||||
}
|
@ -1 +1,4 @@
|
||||
# Repository CODEOWNERS
|
||||
|
||||
* @actions/actions-runtime
|
||||
* @ncalteen
|
3
LICENSE
3
LICENSE
@ -1,4 +1,5 @@
|
||||
MIT License
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 GitHub Actions
|
||||
|
||||
|
229
README.md
229
README.md
@ -1,116 +1,199 @@
|
||||
# Create a JavaScript Action
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/actions/javascript-action/actions"><img alt="javscript-action status" src="https://github.com/actions/javascript-action/workflows/units-test/badge.svg"></a>
|
||||
</p>
|
||||
[](https://github.com/super-linter/super-linter)
|
||||

|
||||
|
||||
Use this template to bootstrap the creation of a JavaScript action.:rocket:
|
||||
Use this template to bootstrap the creation of a JavaScript action. :rocket:
|
||||
|
||||
This template includes tests, linting, a validation workflow, publishing, and versioning guidance.
|
||||
This template includes compilation support, tests, a validation workflow,
|
||||
publishing, and versioning guidance.
|
||||
|
||||
If you are new, there's also a simpler introduction. See the [Hello World JavaScript Action](https://github.com/actions/hello-world-javascript-action)
|
||||
If you are new, there's also a simpler introduction in the
|
||||
[Hello world JavaScript action repository](https://github.com/actions/hello-world-javascript-action).
|
||||
|
||||
## Create an action from this template
|
||||
## Create Your Own Action
|
||||
|
||||
Click the `Use this Template` and provide the new repo details for your action
|
||||
To create your own action, you can use this repository as a template! Just
|
||||
follow the below instructions:
|
||||
|
||||
## Code in Main
|
||||
1. Click the **Use this template** button at the top of the repository
|
||||
1. Select **Create a new repository**
|
||||
1. Select an owner and name for your new repository
|
||||
1. Click **Create repository**
|
||||
1. Clone your new repository
|
||||
|
||||
Install the dependencies
|
||||
## Initial Setup
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
After you've cloned the repository to your local machine or codespace, you'll
|
||||
need to perform some initial setup steps before you can develop your action.
|
||||
|
||||
Run the tests :heavy_check_mark:
|
||||
> [!NOTE]
|
||||
>
|
||||
> You'll need to have a reasonably modern version of
|
||||
> [Node.js](https://nodejs.org) handy. If you are using a version manager like
|
||||
> [`nodenv`](https://github.com/nodenv/nodenv) or
|
||||
> [`nvm`](https://github.com/nvm-sh/nvm), you can run `nodenv install` in the
|
||||
> root of your repository to install the version specified in
|
||||
> [`package.json`](./package.json). Otherwise, 20.x or later should work!
|
||||
|
||||
```bash
|
||||
$ npm test
|
||||
1. :hammer_and_wrench: Install the dependencies
|
||||
|
||||
PASS ./index.test.js
|
||||
✓ throws invalid number (3ms)
|
||||
✓ wait 500 ms (504ms)
|
||||
✓ test runs (95ms)
|
||||
...
|
||||
```
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
## Change action.yml
|
||||
1. :building_construction: Package the JavaScript for distribution
|
||||
|
||||
The action.yml defines the inputs and output for your action.
|
||||
```bash
|
||||
npm run bundle
|
||||
```
|
||||
|
||||
Update the action.yml with your name, description, inputs and outputs for your action.
|
||||
1. :white_check_mark: Run the tests
|
||||
|
||||
See the [documentation](https://help.github.com/en/articles/metadata-syntax-for-github-actions)
|
||||
```bash
|
||||
$ npm test
|
||||
|
||||
## Change the Code
|
||||
PASS ./index.test.js
|
||||
✓ throws invalid number (3ms)
|
||||
✓ wait 500 ms (504ms)
|
||||
✓ test runs (95ms)
|
||||
|
||||
Most toolkit and CI/CD operations involve async operations so the action is run in an async function.
|
||||
...
|
||||
```
|
||||
|
||||
```javascript
|
||||
const core = require('@actions/core');
|
||||
...
|
||||
## Update the Action Metadata
|
||||
|
||||
async function run() {
|
||||
try {
|
||||
...
|
||||
The [`action.yml`](action.yml) file defines metadata about your action, such as
|
||||
input(s) and output(s). For details about this file, see
|
||||
[Metadata syntax for GitHub Actions](https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions).
|
||||
|
||||
When you copy this repository, update `action.yml` with the name, description,
|
||||
inputs, and outputs for your action.
|
||||
|
||||
## Update the Action Code
|
||||
|
||||
The [`src/`](./src/) directory is the heart of your action! This contains the
|
||||
source code that will be run when your action is invoked. You can replace the
|
||||
contents of this directory with your own code.
|
||||
|
||||
There are a few things to keep in mind when writing your action code:
|
||||
|
||||
- Most GitHub Actions toolkit and CI/CD operations are processed asynchronously.
|
||||
In `main.js`, you will see that the action is run in an `async` function.
|
||||
|
||||
```javascript
|
||||
const core = require('@actions/core')
|
||||
//...
|
||||
|
||||
async function run() {
|
||||
try {
|
||||
//...
|
||||
} catch (error) {
|
||||
core.setFailed(error.message)
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
run()
|
||||
```
|
||||
For more information about the GitHub Actions toolkit, see the
|
||||
[documentation](https://github.com/actions/toolkit/blob/master/README.md).
|
||||
|
||||
See the [toolkit documentation](https://github.com/actions/toolkit/blob/master/README.md#packages) for the various packages.
|
||||
So, what are you waiting for? Go ahead and start customizing your action!
|
||||
|
||||
## Package for distribution
|
||||
1. Create a new branch
|
||||
|
||||
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.
|
||||
```bash
|
||||
git checkout -b releases/v1
|
||||
```
|
||||
|
||||
Actions are run from GitHub repos. Packaging the action will create a packaged action in the dist folder.
|
||||
1. Replace the contents of `src/` with your action code
|
||||
1. Add tests to `__tests__/` for your source code
|
||||
1. Format, test, and build the action
|
||||
|
||||
Run prepare
|
||||
```bash
|
||||
npm run all
|
||||
```
|
||||
|
||||
```bash
|
||||
npm run prepare
|
||||
```
|
||||
> [!WARNING]
|
||||
>
|
||||
> This step is important! It will run [`ncc`](https://github.com/vercel/ncc)
|
||||
> to build the final JavaScript action code with all dependencies included.
|
||||
> If you do not run this step, your action will not work correctly when it is
|
||||
> used in a workflow. This step also includes the `--license` option for
|
||||
> `ncc`, which will create a license file for all of the production node
|
||||
> modules used in your project.
|
||||
|
||||
Since the packaged index.js is run from the dist folder.
|
||||
1. Commit your changes
|
||||
|
||||
```bash
|
||||
git add dist
|
||||
```
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "My first action is ready!"
|
||||
```
|
||||
|
||||
## Create a release branch
|
||||
1. Push them to your repository
|
||||
|
||||
Users shouldn't consume the action from master since that would be latest code and actions can break compatibility between major versions.
|
||||
```bash
|
||||
git push -u origin releases/v1
|
||||
```
|
||||
|
||||
Checkin to the v1 release branch
|
||||
|
||||
```bash
|
||||
git checkout -b v1
|
||||
git commit -a -m "v1 release"
|
||||
```
|
||||
|
||||
```bash
|
||||
git push origin v1
|
||||
```
|
||||
|
||||
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.
|
||||
1. Create a pull request and get feedback on your action
|
||||
1. Merge the pull request into the `main` branch
|
||||
|
||||
Your action is now published! :rocket:
|
||||
|
||||
See the [versioning documentation](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md)
|
||||
For information about versioning your action, see
|
||||
[Versioning](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md)
|
||||
in the GitHub Actions toolkit.
|
||||
|
||||
## Validate the Action
|
||||
|
||||
You can now validate the action by referencing it in a workflow file. For
|
||||
example, [`ci.yml`](./.github/workflows/ci.yml) demonstrates how to reference an
|
||||
action in the same repository.
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- name: Checkout
|
||||
id: checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Test Local Action
|
||||
id: test-action
|
||||
uses: ./
|
||||
with:
|
||||
milliseconds: 1000
|
||||
|
||||
- name: Print Output
|
||||
id: output
|
||||
run: echo "${{ steps.test-action.outputs.time }}"
|
||||
```
|
||||
|
||||
For example workflow runs, check out the
|
||||
[Actions tab](https://github.com/actions/javascript-action/actions)! :rocket:
|
||||
|
||||
## Usage
|
||||
|
||||
You can now consume the action by referencing the v1 branch
|
||||
After testing, you can create version tag(s) that developers can use to
|
||||
reference different stable versions of your action. For more information, see
|
||||
[Versioning](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md)
|
||||
in the GitHub Actions toolkit.
|
||||
|
||||
To include the action in a workflow in another repository, you can use the
|
||||
`uses` syntax with the `@` symbol to reference a specific branch, tag, or commit
|
||||
hash.
|
||||
|
||||
```yaml
|
||||
uses: actions/javascript-action@v1
|
||||
with:
|
||||
milliseconds: 1000
|
||||
```
|
||||
steps:
|
||||
- name: Checkout
|
||||
id: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
See the [actions tab](https://github.com/actions/javascript-action/actions) for runs of this action! :rocket:
|
||||
- name: Run my Action
|
||||
id: run-action
|
||||
uses: actions/javascript-action@v1 # Commit with the `v1` tag
|
||||
with:
|
||||
milliseconds: 1000
|
||||
|
||||
- name: Print Output
|
||||
id: output
|
||||
run: echo "${{ steps.test-action.outputs.time }}"
|
||||
```
|
||||
|
18
__tests__/index.test.js
Normal file
18
__tests__/index.test.js
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Unit tests for the action's entrypoint, src/index.ts
|
||||
*/
|
||||
|
||||
const { run } = require('../src/main')
|
||||
|
||||
// Mock the action's entrypoint
|
||||
jest.mock('../src/main', () => ({
|
||||
run: jest.fn()
|
||||
}))
|
||||
|
||||
describe('index', () => {
|
||||
it('calls run when imported', async () => {
|
||||
require('../src/index')
|
||||
|
||||
expect(run).toHaveBeenCalled()
|
||||
})
|
||||
})
|
100
__tests__/main.test.js
Normal file
100
__tests__/main.test.js
Normal file
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Unit tests for the action's main functionality, src/main.ts
|
||||
*
|
||||
* These should be run as if the action was called from a workflow.
|
||||
* Specifically, the inputs listed in `action.yml` should be set as environment
|
||||
* variables following the pattern `INPUT_<INPUT_NAME>`.
|
||||
*/
|
||||
const core = require('@actions/core')
|
||||
const main = require('../src/main')
|
||||
|
||||
// Mock the GitHub Actions core library
|
||||
const debugMock = jest.spyOn(core, 'debug').mockImplementation()
|
||||
const getInputMock = jest.spyOn(core, 'getInput').mockImplementation()
|
||||
const setFailedMock = jest.spyOn(core, 'setFailed').mockImplementation()
|
||||
const setOutputMock = jest.spyOn(core, 'setOutput').mockImplementation()
|
||||
|
||||
// Mock the action's main function
|
||||
const runMock = jest.spyOn(main, 'run')
|
||||
|
||||
// Other utilities
|
||||
const timeRegex = /^\d{2}:\d{2}:\d{2}/
|
||||
|
||||
describe('action', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('sets the time output', async () => {
|
||||
// Set the action's inputs as return values from core.getInput()
|
||||
getInputMock.mockImplementation(name => {
|
||||
switch (name) {
|
||||
case 'milliseconds':
|
||||
return '500'
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
})
|
||||
|
||||
await main.run()
|
||||
expect(runMock).toHaveReturned()
|
||||
|
||||
// Verify that all of the core library functions were called correctly
|
||||
expect(debugMock).toHaveBeenNthCalledWith(1, 'Waiting 500 milliseconds ...')
|
||||
expect(debugMock).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
expect.stringMatching(timeRegex)
|
||||
)
|
||||
expect(debugMock).toHaveBeenNthCalledWith(
|
||||
3,
|
||||
expect.stringMatching(timeRegex)
|
||||
)
|
||||
expect(setOutputMock).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
'time',
|
||||
expect.stringMatching(timeRegex)
|
||||
)
|
||||
})
|
||||
|
||||
it('sets a failed status', async () => {
|
||||
// Set the action's inputs as return values from core.getInput()
|
||||
getInputMock.mockImplementation(name => {
|
||||
switch (name) {
|
||||
case 'milliseconds':
|
||||
return 'this is not a number'
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
})
|
||||
|
||||
await main.run()
|
||||
expect(runMock).toHaveReturned()
|
||||
|
||||
// Verify that all of the core library functions were called correctly
|
||||
expect(setFailedMock).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
'milliseconds not a number'
|
||||
)
|
||||
})
|
||||
|
||||
it('fails if no input is provided', async () => {
|
||||
// Set the action's inputs as return values from core.getInput()
|
||||
getInputMock.mockImplementation(name => {
|
||||
switch (name) {
|
||||
case 'milliseconds':
|
||||
throw new Error('Input required and not supplied: milliseconds')
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
})
|
||||
|
||||
await main.run()
|
||||
expect(runMock).toHaveReturned()
|
||||
|
||||
// Verify that all of the core library functions were called correctly
|
||||
expect(setFailedMock).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
'Input required and not supplied: milliseconds'
|
||||
)
|
||||
})
|
||||
})
|
24
__tests__/wait.test.js
Normal file
24
__tests__/wait.test.js
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Unit tests for src/wait.ts
|
||||
*/
|
||||
const { wait } = require('../src/wait')
|
||||
const { expect } = require('@jest/globals')
|
||||
|
||||
describe('wait.ts', () => {
|
||||
it('throws an invalid number', async () => {
|
||||
const input = parseInt('foo', 10)
|
||||
expect(isNaN(input)).toBe(true)
|
||||
|
||||
await expect(wait(input)).rejects.toThrow('milliseconds not a number')
|
||||
})
|
||||
|
||||
it('waits with a valid number', async () => {
|
||||
const start = new Date()
|
||||
await wait(500)
|
||||
const end = new Date()
|
||||
|
||||
const delta = Math.abs(end.getTime() - start.getTime())
|
||||
|
||||
expect(delta).toBeGreaterThan(450)
|
||||
})
|
||||
})
|
22
action.yml
22
action.yml
@ -1,13 +1,19 @@
|
||||
name: 'Wait'
|
||||
description: 'Wait a designated number of milliseconds'
|
||||
name: 'The name of your action here'
|
||||
description: 'Provide a description here'
|
||||
author: 'Your name or organization here'
|
||||
|
||||
# Define your inputs here.
|
||||
inputs:
|
||||
milliseconds: # id of input
|
||||
description: 'number of milliseconds to wait'
|
||||
milliseconds:
|
||||
description: 'Your input description here'
|
||||
required: true
|
||||
default: '1000'
|
||||
|
||||
# Define your outputs here.
|
||||
outputs:
|
||||
time: # output will be available to future steps
|
||||
description: 'The current time after waiting'
|
||||
time:
|
||||
description: 'Your output description here'
|
||||
|
||||
runs:
|
||||
using: 'node16'
|
||||
main: 'dist/index.js'
|
||||
using: node20
|
||||
main: dist/index.js
|
||||
|
1
badges/coverage.svg
Normal file
1
badges/coverage.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="106" height="20" role="img" aria-label="Coverage: 100%"><title>Coverage: 100%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="106" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="43" height="20" fill="#4c1"/><rect width="106" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="835" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="330">100%</text><text x="835" y="140" transform="scale(.1)" fill="#fff" textLength="330">100%</text></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
136
dist/index.js
generated
vendored
136
dist/index.js
generated
vendored
@ -1,7 +1,7 @@
|
||||
require('./sourcemap-register.js');/******/ (() => { // webpackBootstrap
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ 351:
|
||||
/***/ 241:
|
||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||
|
||||
"use strict";
|
||||
@ -135,7 +135,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0;
|
||||
const command_1 = __nccwpck_require__(351);
|
||||
const command_1 = __nccwpck_require__(241);
|
||||
const file_command_1 = __nccwpck_require__(717);
|
||||
const utils_1 = __nccwpck_require__(278);
|
||||
const os = __importStar(__nccwpck_require__(37));
|
||||
@ -558,7 +558,7 @@ class OidcClient {
|
||||
.catch(error => {
|
||||
throw new Error(`Failed to get ID Token. \n
|
||||
Error Code : ${error.statusCode}\n
|
||||
Error Message: ${error.result.message}`);
|
||||
Error Message: ${error.message}`);
|
||||
});
|
||||
const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value;
|
||||
if (!id_token) {
|
||||
@ -1211,6 +1211,19 @@ class HttpClientResponse {
|
||||
}));
|
||||
});
|
||||
}
|
||||
readBodyBuffer() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
|
||||
const chunks = [];
|
||||
this.message.on('data', (chunk) => {
|
||||
chunks.push(chunk);
|
||||
});
|
||||
this.message.on('end', () => {
|
||||
resolve(Buffer.concat(chunks));
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.HttpClientResponse = HttpClientResponse;
|
||||
function isHttps(requestUrl) {
|
||||
@ -1715,7 +1728,13 @@ function getProxyUrl(reqUrl) {
|
||||
}
|
||||
})();
|
||||
if (proxyVar) {
|
||||
return new URL(proxyVar);
|
||||
try {
|
||||
return new URL(proxyVar);
|
||||
}
|
||||
catch (_a) {
|
||||
if (!proxyVar.startsWith('http://') && !proxyVar.startsWith('https://'))
|
||||
return new URL(`http://${proxyVar}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
@ -1726,6 +1745,10 @@ function checkBypass(reqUrl) {
|
||||
if (!reqUrl.hostname) {
|
||||
return false;
|
||||
}
|
||||
const reqHost = reqUrl.hostname;
|
||||
if (isLoopbackAddress(reqHost)) {
|
||||
return true;
|
||||
}
|
||||
const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || '';
|
||||
if (!noProxy) {
|
||||
return false;
|
||||
@ -1751,13 +1774,24 @@ function checkBypass(reqUrl) {
|
||||
.split(',')
|
||||
.map(x => x.trim().toUpperCase())
|
||||
.filter(x => x)) {
|
||||
if (upperReqHosts.some(x => x === upperNoProxyItem)) {
|
||||
if (upperNoProxyItem === '*' ||
|
||||
upperReqHosts.some(x => x === upperNoProxyItem ||
|
||||
x.endsWith(`.${upperNoProxyItem}`) ||
|
||||
(upperNoProxyItem.startsWith('.') &&
|
||||
x.endsWith(`${upperNoProxyItem}`)))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
exports.checkBypass = checkBypass;
|
||||
function isLoopbackAddress(host) {
|
||||
const hostLower = host.toLowerCase();
|
||||
return (hostLower === 'localhost' ||
|
||||
hostLower.startsWith('127.') ||
|
||||
hostLower.startsWith('[::1]') ||
|
||||
hostLower.startsWith('[0:0:0:0:0:0:0:1]'));
|
||||
}
|
||||
//# sourceMappingURL=proxy.js.map
|
||||
|
||||
/***/ }),
|
||||
@ -2688,19 +2722,63 @@ exports["default"] = _default;
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 258:
|
||||
/***/ 713:
|
||||
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
||||
|
||||
const core = __nccwpck_require__(186)
|
||||
const { wait } = __nccwpck_require__(312)
|
||||
|
||||
/**
|
||||
* The main function for the action.
|
||||
* @returns {Promise<void>} Resolves when the action is complete.
|
||||
*/
|
||||
async function run() {
|
||||
try {
|
||||
const ms = core.getInput('milliseconds', { required: true })
|
||||
|
||||
// Debug logs are only output if the `ACTIONS_STEP_DEBUG` secret is true
|
||||
core.debug(`Waiting ${ms} milliseconds ...`)
|
||||
|
||||
// Log the current timestamp, wait, then log the new timestamp
|
||||
core.debug(new Date().toTimeString())
|
||||
await wait(parseInt(ms, 10))
|
||||
core.debug(new Date().toTimeString())
|
||||
|
||||
// Set outputs for other workflow steps to use
|
||||
core.setOutput('time', new Date().toTimeString())
|
||||
} catch (error) {
|
||||
// Fail the workflow run if an error occurs
|
||||
core.setFailed(error.message)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
run
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 312:
|
||||
/***/ ((module) => {
|
||||
|
||||
let wait = function (milliseconds) {
|
||||
return new Promise((resolve) => {
|
||||
if (typeof milliseconds !== 'number') {
|
||||
throw new Error('milliseconds not a number');
|
||||
/**
|
||||
* Wait for a number of milliseconds.
|
||||
*
|
||||
* @param {number} milliseconds The number of milliseconds to wait.
|
||||
* @returns {Promise<string>} Resolves with 'done!' after the wait is over.
|
||||
*/
|
||||
async function wait(milliseconds) {
|
||||
return new Promise(resolve => {
|
||||
if (isNaN(milliseconds)) {
|
||||
throw new Error('milliseconds not a number')
|
||||
}
|
||||
setTimeout(() => resolve("done!"), milliseconds)
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = wait;
|
||||
setTimeout(() => resolve('done!'), milliseconds)
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = { wait }
|
||||
|
||||
|
||||
/***/ }),
|
||||
@ -2834,31 +2912,15 @@ module.exports = require("util");
|
||||
var __webpack_exports__ = {};
|
||||
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
|
||||
(() => {
|
||||
const core = __nccwpck_require__(186);
|
||||
const wait = __nccwpck_require__(258);
|
||||
/**
|
||||
* The entrypoint for the action.
|
||||
*/
|
||||
const { run } = __nccwpck_require__(713)
|
||||
|
||||
|
||||
// most @actions toolkit packages have async methods
|
||||
async function run() {
|
||||
try {
|
||||
const ms = core.getInput('milliseconds');
|
||||
core.info(`Waiting ${ms} milliseconds ...`);
|
||||
|
||||
core.debug((new Date()).toTimeString()); // debug is only output if you set the secret `ACTIONS_RUNNER_DEBUG` to true
|
||||
await wait(parseInt(ms));
|
||||
core.info((new Date()).toTimeString());
|
||||
|
||||
core.setOutput('time', new Date().toTimeString());
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
run()
|
||||
|
||||
})();
|
||||
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
//# sourceMappingURL=index.js.map
|
||||
;
|
1
dist/index.js.map
generated
vendored
1
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
1
dist/sourcemap-register.js
generated
vendored
1
dist/sourcemap-register.js
generated
vendored
File diff suppressed because one or more lines are too long
21
index.js
21
index.js
@ -1,21 +0,0 @@
|
||||
const core = require('@actions/core');
|
||||
const wait = require('./wait');
|
||||
|
||||
|
||||
// most @actions toolkit packages have async methods
|
||||
async function run() {
|
||||
try {
|
||||
const ms = core.getInput('milliseconds');
|
||||
core.info(`Waiting ${ms} milliseconds ...`);
|
||||
|
||||
core.debug((new Date()).toTimeString()); // debug is only output if you set the secret `ACTIONS_RUNNER_DEBUG` to true
|
||||
await wait(parseInt(ms));
|
||||
core.info((new Date()).toTimeString());
|
||||
|
||||
core.setOutput('time', new Date().toTimeString());
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
@ -1,24 +0,0 @@
|
||||
const wait = require('./wait');
|
||||
const process = require('process');
|
||||
const cp = require('child_process');
|
||||
const path = require('path');
|
||||
|
||||
test('throws invalid number', async () => {
|
||||
await expect(wait('foo')).rejects.toThrow('milliseconds not a number');
|
||||
});
|
||||
|
||||
test('wait 500 ms', async () => {
|
||||
const start = new Date();
|
||||
await wait(500);
|
||||
const end = new Date();
|
||||
var delta = Math.abs(end - start);
|
||||
expect(delta).toBeGreaterThanOrEqual(500);
|
||||
});
|
||||
|
||||
// shows how the runner will run a javascript action with env / stdout protocol
|
||||
test('test runs', () => {
|
||||
process.env['INPUT_MILLISECONDS'] = 100;
|
||||
const ip = path.join(__dirname, 'index.js');
|
||||
const result = cp.execSync(`node ${ip}`, {env: process.env}).toString();
|
||||
console.log(result);
|
||||
})
|
9208
package-lock.json
generated
9208
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
82
package.json
82
package.json
@ -1,35 +1,81 @@
|
||||
{
|
||||
"name": "javascript-action",
|
||||
"version": "1.0.0",
|
||||
"description": "JavaScript Action Template",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"prepare": "ncc build index.js -o dist --source-map --license licenses.txt",
|
||||
"test": "jest",
|
||||
"all": "npm run lint && npm run test && npm run prepare"
|
||||
},
|
||||
"description": "GitHub Actions JavaScript Template",
|
||||
"version": "0.0.0",
|
||||
"author": "",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/actions/javascript-action#readme",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/actions/javascript-action.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/actions/javascript-action/issues"
|
||||
},
|
||||
"keywords": [
|
||||
"GitHub",
|
||||
"Actions",
|
||||
"JavaScript"
|
||||
],
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/actions/javascript-action/issues"
|
||||
"exports": {
|
||||
".": "./dist/index.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"scripts": {
|
||||
"bundle": "npm run format:write && npm run package",
|
||||
"ci-test": "jest",
|
||||
"format:write": "prettier --write **/*.js",
|
||||
"format:check": "prettier --check **/*.js",
|
||||
"lint": "npx eslint . -c ./.github/linters/.eslintrc.yml",
|
||||
"package": "ncc build src/index.js --license licenses.txt",
|
||||
"package:watch": "npm run package -- --watch",
|
||||
"test": "(jest && make-coverage-badge --output-path ./badges/coverage.svg) || make-coverage-badge --output-path ./badges/coverage.svg",
|
||||
"all": "npm run format:write && npm run lint && npm run test && npm run package"
|
||||
},
|
||||
"license": "MIT",
|
||||
"eslintConfig": {
|
||||
"extends": "./.github/linters/.eslintrc.yml"
|
||||
},
|
||||
"jest": {
|
||||
"verbose": true,
|
||||
"clearMocks": true,
|
||||
"testEnvironment": "node",
|
||||
"moduleFileExtensions": [
|
||||
"js"
|
||||
],
|
||||
"testMatch": [
|
||||
"**/*.test.js"
|
||||
],
|
||||
"testPathIgnorePatterns": [
|
||||
"/node_modules/",
|
||||
"/dist/"
|
||||
],
|
||||
"coverageReporters": [
|
||||
"json-summary",
|
||||
"text",
|
||||
"lcov"
|
||||
],
|
||||
"collectCoverage": true,
|
||||
"collectCoverageFrom": [
|
||||
"./src/**"
|
||||
]
|
||||
},
|
||||
"homepage": "https://github.com/actions/javascript-action#readme",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.0"
|
||||
"@actions/core": "^1.10.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vercel/ncc": "^0.36.1",
|
||||
"eslint": "^8.37.0",
|
||||
"jest": "^29.5.0"
|
||||
"@babel/core": "^7.22.17",
|
||||
"@babel/eslint-parser": "^7.22.15",
|
||||
"@babel/preset-env": "^7.22.15",
|
||||
"@vercel/ncc": "^0.38.0",
|
||||
"babel-preset-jest": "^29.6.3",
|
||||
"eslint": "^8.49.0",
|
||||
"eslint-plugin-github": "^4.10.0",
|
||||
"eslint-plugin-jest": "^27.2.3",
|
||||
"jest": "^29.7.0",
|
||||
"make-coverage-badge": "^1.2.0",
|
||||
"prettier": "^3.0.3"
|
||||
}
|
||||
}
|
||||
|
6
src/index.js
Normal file
6
src/index.js
Normal file
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* The entrypoint for the action.
|
||||
*/
|
||||
const { run } = require('./main')
|
||||
|
||||
run()
|
30
src/main.js
Normal file
30
src/main.js
Normal file
@ -0,0 +1,30 @@
|
||||
const core = require('@actions/core')
|
||||
const { wait } = require('./wait')
|
||||
|
||||
/**
|
||||
* The main function for the action.
|
||||
* @returns {Promise<void>} Resolves when the action is complete.
|
||||
*/
|
||||
async function run() {
|
||||
try {
|
||||
const ms = core.getInput('milliseconds', { required: true })
|
||||
|
||||
// Debug logs are only output if the `ACTIONS_STEP_DEBUG` secret is true
|
||||
core.debug(`Waiting ${ms} milliseconds ...`)
|
||||
|
||||
// Log the current timestamp, wait, then log the new timestamp
|
||||
core.debug(new Date().toTimeString())
|
||||
await wait(parseInt(ms, 10))
|
||||
core.debug(new Date().toTimeString())
|
||||
|
||||
// Set outputs for other workflow steps to use
|
||||
core.setOutput('time', new Date().toTimeString())
|
||||
} catch (error) {
|
||||
// Fail the workflow run if an error occurs
|
||||
core.setFailed(error.message)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
run
|
||||
}
|
17
src/wait.js
Normal file
17
src/wait.js
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Wait for a number of milliseconds.
|
||||
*
|
||||
* @param {number} milliseconds The number of milliseconds to wait.
|
||||
* @returns {Promise<string>} Resolves with 'done!' after the wait is over.
|
||||
*/
|
||||
async function wait(milliseconds) {
|
||||
return new Promise(resolve => {
|
||||
if (isNaN(milliseconds)) {
|
||||
throw new Error('milliseconds not a number')
|
||||
}
|
||||
|
||||
setTimeout(() => resolve('done!'), milliseconds)
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = { wait }
|
Reference in New Issue
Block a user