Compare commits

...

18 Commits

Author SHA1 Message Date
Sean Goedecke ba8a6b0374 Add security and support docs 2025-04-10 03:02:10 +00:00
Sean Goedecke e670dd5178 Set user agent 2025-04-10 02:53:54 +00:00
Sean Goedecke 84fee7a0e6 Use user-provided endpoint 2025-04-08 20:22:47 +00:00
Sean Goedecke 83d9668e82 Merge pull request #8 from actions/sgoedecke/use-models-dot-github
Use org-owned endpoint
2025-04-08 20:05:22 +10:00
Sean Goedecke 2de3b6e872 Merge pull request #2 from actions/dependabot/npm_and_yarn/rollup/rollup-linux-x64-gnu-4.39.0
Bump @rollup/rollup-linux-x64-gnu from 4.38.0 to 4.39.0
2025-04-08 15:37:38 +10:00
Sean Goedecke 40b430b284 Merge pull request #5 from actions/dependabot/npm_and_yarn/babel/helpers-7.27.0
Bump @babel/helpers from 7.26.9 to 7.27.0
2025-04-08 15:37:16 +10:00
Sean Goedecke e5b826567d rebuild 2025-04-08 05:18:48 +00:00
Sean Goedecke 4738a2d212 use org-owned endpoint 2025-04-08 04:55:27 +00:00
Sean Goedecke 606ea175ce Merge pull request #7 from actions/sgoedecke/use-models-dot-github
Use models dot github as the base endpoint
2025-04-08 14:33:32 +10:00
Sean Goedecke afaedf6677 use models dot github as the base endpoint 2025-04-08 04:30:16 +00:00
Sean Goedecke 78d6b91d0b Lint README.md 2025-04-08 02:10:27 +00:00
Sean Goedecke 1a66a5968c Update README.md 2025-04-08 12:00:25 +10:00
Sean Goedecke efbbaa2667 Use correct Azure inference endpoint 2025-04-07 23:52:33 +00:00
Sean Goedecke a57b52eccd Merge pull request #6 from actions/sgoedecke/configurable-token
Make token configurable
2025-04-07 15:21:27 +10:00
Sean Goedecke 32ebbe708a Make token configurable 2025-04-07 04:53:19 +00:00
dependabot[bot] 213eb60e28 Bump @babel/helpers from 7.26.9 to 7.27.0
Bumps [@babel/helpers](https://github.com/babel/babel/tree/HEAD/packages/babel-helpers) from 7.26.9 to 7.27.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.27.0/packages/babel-helpers)

---
updated-dependencies:
- dependency-name: "@babel/helpers"
  dependency-version: 7.27.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-07 03:13:11 +00:00
Sean Goedecke fbd6a39716 Merge pull request #3 from actions/sgoedecke/initial-setup
Setup initial inference flow and install packages
2025-04-07 13:11:52 +10:00
dependabot[bot] 7ae29e4a7c Bump @rollup/rollup-linux-x64-gnu from 4.38.0 to 4.39.0
Bumps [@rollup/rollup-linux-x64-gnu](https://github.com/rollup/rollup) from 4.38.0 to 4.39.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.38.0...v4.39.0)

---
updated-dependencies:
- dependency-name: "@rollup/rollup-linux-x64-gnu"
  dependency-version: 4.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-03 20:30:45 +00:00
9 changed files with 179 additions and 64 deletions
+25 -16
View File
@@ -14,16 +14,24 @@ your actions.
Create a workflow to use the AI inference action:
```yaml
steps:
- name: Test Local Action
id: inference
uses: actions/ai-inference@v1
with:
prompt: 'Hello!'
name: 'AI inference'
on: workflow_dispatch
- name: Print Output
id: output
run: echo "${{ steps.test-action.outputs.response }}"
jobs:
inference:
permissions:
models: read
runs-on: ubuntu-latest
steps:
- name: Test Local Action
id: inference
uses: actions/ai-inference@v1
with:
prompt: 'Hello!'
- name: Print Output
id: output
run: echo "${{ steps.inference.outputs.response }}"
```
## Inputs
@@ -31,13 +39,14 @@ steps:
Various inputs are defined in [`action.yml`](action.yml) to let you configure
the action:
| Name | Description | Default |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ |
| `token` | Token to use for inference. Typically the GITHUB_TOKEN secret | `github.token` |
| `prompt` | The prompt to send to the model | N/A |
| `model` | The model to use for inference. Must be available in the [GitHub Models](https://github.com/marketplace?type=models) catalog | `gpt-4o` |
| `endpoint` | The endpoint to use for inference. If you're running this as part of an org, you should probably use the org-specific Models endpoint | `https://models.github.ai/inference` |
| `max_tokens` | The max number of tokens to generate | 200 |
| Name | Description | Default |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ |
| `token` | Token to use for inference. Typically the GITHUB_TOKEN secret | `github.token` |
| `prompt` | The prompt to send to the model | N/A |
| `system-prompt` | The system prompt to send to the model | `""` |
| `model` | The model to use for inference. Must be available in the [GitHub Models](https://github.com/marketplace?type=models) catalog | `gpt-4o` |
| `endpoint` | The endpoint to use for inference. If you're running this as part of an org, you should probably use the org-specific Models endpoint | `https://models.github.ai/inference` |
| `max-tokens` | The max number of tokens to generate | 200 |
## Outputs
+39
View File
@@ -0,0 +1,39 @@
# Security
GitHub takes the security of our software products and services seriously,
including all of the open source code repositories managed through our GitHub
organizations, such as [GitHub](https://github.com/GitHub).
Even though
[open source repositories are outside of the scope of our bug bounty program](https://bounty.github.com/index.html#scope)
and therefore not eligible for bounty rewards, we will ensure that your finding
gets passed along to the appropriate maintainers for remediation.
## Reporting Security Issues
If you believe you have found a security vulnerability in any GitHub-owned
repository, please report it to us through coordinated disclosure.
**Please do not report security vulnerabilities through public GitHub issues,
discussions, or pull requests.**
Instead, please send an email to opensource-security[@]github.com.
Please include as much of the information listed below as you can to help us
better understand and resolve the issue:
- The type of issue (e.g., buffer overflow, SQL injection, or cross-site
scripting)
- Full paths of source file(s) related to the manifestation of the issue
- The location of the affected source code (tag/branch/commit or direct URL)
- Any special configuration required to reproduce the issue
- Step-by-step instructions to reproduce the issue
- Proof-of-concept or exploit code (if possible)
- Impact of the issue, including how an attacker might exploit the issue
This information will help us triage your report more quickly.
## Policy
See
[GitHub's Safe Harbor Policy](https://docs.github.com/en/site-policy/security-policies/github-bug-bounty-program-legal-safe-harbor#1-safe-harbor-terms)
+17
View File
@@ -0,0 +1,17 @@
# Support
## How to file issues and get help
This project uses GitHub issues to track bugs and feature requests. Please
search the existing issues before filing new issues to avoid duplicates. For new
issues, file your bug or feature request as a new issue.
For help or questions about using this project, please file an issue.
This project is under active development and maintained by GitHub staff and the
community. We will do our best to respond to support, feature requests, and
community questions in a timely manner.
## GitHub Support Policy
Support for this project is limited to the resources listed above.
+12 -4
View File
@@ -4,27 +4,35 @@ author: 'GitHub'
# Add your action's branding here. This will appear on the GitHub Marketplace.
branding:
icon: 'play-circle'
icon: 'message-square'
color: red
# Define your inputs here.
inputs:
prompt:
description: Your input description here
description: The prompt for the model
required: true
default: ''
model:
description: The model to use
required: false
default: 'gpt-4o'
default: 'openai/gpt-4o'
endpoint:
description: The endpoint to use
required: false
default: 'https://models.github.ai/inference'
max_tokens:
system-prompt:
description: The system prompt for the model
required: false
default: 'You are a helpful assistant'
max-tokens:
description: The maximum number of tokens to generate
required: false
default: '200'
token:
description: The token to use
required: false
default: ${{ github.token }}
# Define your outputs here.
outputs:
+1 -1
View File
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="116" height="20" role="img" aria-label="Coverage: 89.47%"><title>Coverage: 89.47%</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="116" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="53" height="20" fill="#dfb317"/><rect width="116" 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="885" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">89.47%</text><text x="885" y="140" transform="scale(.1)" fill="#fff" textLength="430">89.47%</text></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="116" height="20" role="img" aria-label="Coverage: 77.27%"><title>Coverage: 77.27%</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="116" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="53" height="20" fill="#e05d44"/><rect width="116" 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="885" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">77.27%</text><text x="885" y="140" transform="scale(.1)" fill="#fff" textLength="430">77.27%</text></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Generated Vendored
+19 -9
View File
@@ -33559,32 +33559,38 @@ async function run() {
if (prompt === undefined || prompt === '') {
throw new Error('prompt is not set');
}
const systemPrompt = coreExports.getInput('system_prompt');
const systemPrompt = coreExports.getInput('system-prompt');
const modelName = coreExports.getInput('model');
const maxTokens = parseInt(coreExports.getInput('max_tokens'), 10);
const token = process.env['GITHUB_TOKEN'];
const maxTokens = parseInt(coreExports.getInput('max-tokens'), 10);
const token = coreExports.getInput('token') || process.env['GITHUB_TOKEN'];
if (token === undefined) {
throw new Error('GITHUB_TOKEN is not set');
}
const endpoint = coreExports.getInput('endpoint');
const client = createClient(endpoint, new AzureKeyCredential(token));
const client = createClient(endpoint, new AzureKeyCredential(token), {
userAgentOptions: { userAgentPrefix: 'github-actions-ai-inference' }
});
const response = await client.path('/chat/completions').post({
body: {
messages: [
{
role: 'system',
content: systemPrompt || 'You are a helpful assistant.'
content: systemPrompt
},
{ role: 'user', content: prompt }
],
temperature: 1.0,
top_p: 1.0,
max_tokens: maxTokens,
model: modelName
}
});
if (isUnexpected(response)) {
throw response.body.error;
if (response.body.error) {
throw response.body.error;
}
throw new Error('An error occurred while fetching the response (' +
response.status +
'): ' +
response.body);
}
const modelResponse = response.body.choices[0].message.content;
// Set outputs for other workflow steps to use
@@ -33592,8 +33598,12 @@ async function run() {
}
catch (error) {
// Fail the workflow run if an error occurs
if (error instanceof Error)
if (error instanceof Error) {
coreExports.setFailed(error.message);
}
else {
coreExports.setFailed('An unexpected error occurred');
}
}
}
Generated Vendored
+1 -1
View File
File diff suppressed because one or more lines are too long
+43 -24
View File
@@ -9,12 +9,13 @@
"version": "0.0.0",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.11.1"
"@actions/core": "^1.11.1",
"@rollup/rollup-linux-x64-gnu": "*"
},
"devDependencies": {
"@azure-rest/ai-inference": "latest",
"@azure/core-auth": "latest",
"@azure/core-sse": "latest",
"@azure-rest/ai-inference": "*",
"@azure/core-auth": "*",
"@azure/core-sse": "*",
"@eslint/compat": "^1.2.7",
"@github/local-action": "^3.1.3",
"@jest/globals": "^29.7.0",
@@ -804,25 +805,27 @@
}
},
"node_modules/@babel/helpers": {
"version": "7.26.9",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz",
"integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==",
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz",
"integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/template": "^7.26.9",
"@babel/types": "^7.26.9"
"@babel/template": "^7.27.0",
"@babel/types": "^7.27.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
"version": "7.26.9",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz",
"integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==",
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz",
"integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.26.9"
"@babel/types": "^7.27.0"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -1054,14 +1057,15 @@
}
},
"node_modules/@babel/template": {
"version": "7.26.9",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz",
"integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==",
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz",
"integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.26.2",
"@babel/parser": "^7.26.9",
"@babel/types": "^7.26.9"
"@babel/parser": "^7.27.0",
"@babel/types": "^7.27.0"
},
"engines": {
"node": ">=6.9.0"
@@ -1095,10 +1099,11 @@
}
},
"node_modules/@babel/types": {
"version": "7.26.9",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz",
"integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==",
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz",
"integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.25.9",
"@babel/helper-validator-identifier": "^7.25.9"
@@ -3076,9 +3081,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.38.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.38.0.tgz",
"integrity": "sha512-vPvNgFlZRAgO7rwncMeE0+8c4Hmc+qixnp00/Uv3ht2x7KYrJ6ERVd3/R0nUtlE6/hu7/HiiNHJ/rP6knRFt1w==",
"version": "4.39.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.39.0.tgz",
"integrity": "sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==",
"cpu": [
"x64"
],
@@ -9693,6 +9698,20 @@
"fsevents": "~2.3.2"
}
},
"node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.38.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.38.0.tgz",
"integrity": "sha512-vPvNgFlZRAgO7rwncMeE0+8c4Hmc+qixnp00/Uv3ht2x7KYrJ6ERVd3/R0nUtlE6/hu7/HiiNHJ/rP6knRFt1w==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+22 -9
View File
@@ -14,36 +14,45 @@ export async function run(): Promise<void> {
throw new Error('prompt is not set')
}
const systemPrompt: string = core.getInput('system_prompt')
const systemPrompt: string = core.getInput('system-prompt')
const modelName: string = core.getInput('model')
const maxTokens: number = parseInt(core.getInput('max_tokens'), 10)
const maxTokens: number = parseInt(core.getInput('max-tokens'), 10)
const token = process.env['GITHUB_TOKEN']
const token = core.getInput('token') || process.env['GITHUB_TOKEN']
if (token === undefined) {
throw new Error('GITHUB_TOKEN is not set')
}
const endpoint = core.getInput('endpoint')
const client = ModelClient(endpoint, new AzureKeyCredential(token))
const client = ModelClient(endpoint, new AzureKeyCredential(token), {
userAgentOptions: { userAgentPrefix: 'github-actions-ai-inference' }
})
const response = await client.path('/chat/completions').post({
body: {
messages: [
{
role: 'system',
content: systemPrompt || 'You are a helpful assistant.'
content: systemPrompt
},
{ role: 'user', content: prompt }
],
temperature: 1.0,
top_p: 1.0,
max_tokens: maxTokens,
model: modelName
}
})
if (isUnexpected(response)) {
throw response.body.error
if (response.body.error) {
throw response.body.error
}
throw new Error(
'An error occurred while fetching the response (' +
response.status +
'): ' +
response.body
)
}
const modelResponse: string | null =
@@ -53,6 +62,10 @@ export async function run(): Promise<void> {
core.setOutput('response', modelResponse || '')
} catch (error) {
// Fail the workflow run if an error occurs
if (error instanceof Error) core.setFailed(error.message)
if (error instanceof Error) {
core.setFailed(error.message)
} else {
core.setFailed('An unexpected error occurred')
}
}
}