v0.0.52: fetch CR URL

This commit is contained in:
Edwin Sirko
2024-01-23 15:24:45 -05:00
parent 1fbd6bde21
commit c41316d7a8
7 changed files with 64 additions and 270 deletions
-197
View File
@@ -1,197 +0,0 @@
# Initial Setup
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.
> [!NOTE]
>
> You'll need to have a reasonably modern version of
> [Node.js](https://nodejs.org) handy (20.x or later should work!). If you are
> using a version manager like [`nodenv`](https://github.com/nodenv/nodenv) or
> [`nvm`](https://github.com/nvm-sh/nvm), this template has a `.node-version`
> file at the root of the repository that will be used to automatically switch
> to the correct version when you `cd` into the repository. Additionally, this
> `.node-version` file is used by GitHub Actions in any `actions/setup-node`
> actions.
1. :hammer_and_wrench: Install the dependencies
```bash
npm install
```
1. :building_construction: Package the TypeScript for distribution
```bash
npm run bundle
```
1. :white_check_mark: Run the tests
```bash
$ npm test
PASS ./index.test.js
✓ throws invalid number (3ms)
✓ wait 500 ms (504ms)
✓ test runs (95ms)
...
```
## Update the Action Metadata
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.ts`, you will see that the action is run in an `async` function.
```javascript
import * as core from '@actions/core'
//...
async function run() {
try {
//...
} catch (error) {
core.setFailed(error.message)
}
}
```
For more information about the GitHub Actions toolkit, see the
[documentation](https://github.com/actions/toolkit/blob/master/README.md).
So, what are you waiting for? Go ahead and start customizing your action!
1. Create a new branch
```bash
git checkout -b releases/v1
```
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
```bash
npm run all
```
> [!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.
1. Commit your changes
```bash
git add .
git commit -m "My first action is ready!"
```
1. Push them to your repository
```bash
git push -u origin releases/v1
```
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:
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@v4
- 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/typescript-action/actions)! :rocket:
## Usage
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
steps:
- name: Checkout
id: checkout
uses: actions/checkout@v4
- name: Test Local Action
id: test-action
uses: actions/typescript-action@v1 # Commit with the `v1` tag
with:
milliseconds: 1000
- name: Print Output
id: output
run: echo "${{ steps.test-action.outputs.time }}"
```
## Publishing a new release
This project includes a helper script designed to streamline the process of
tagging and pushing new releases for GitHub Actions.
GitHub Actions allows users to select a specific version of the action to use,
based on release tags. Our script simplifies this process by performing the
following steps:
1. **Retrieving the latest release tag:** The script starts by fetching the most
recent release tag by looking at the local data available in your repository.
1. **Prompting for a new release tag:** The user is then prompted to enter a new
release tag. To assist with this, the script displays the latest release tag
and provides a regular expression to validate the format of the new tag.
1. **Tagging the new release:** Once a valid new tag is entered, the script tags
the new release.
1. **Pushing the new tag to the remote:** Finally, the script pushes the new tag
to the remote repository. From here, you will need to create a new release in
GitHub and users can easily reference the new tag in their workflows.
+5 -48
View File
@@ -1,13 +1,10 @@
# Publish Action Package
This action packages your action repository as OCI artifacts and publishes it to [GHCR](ghcr.io).
_This action_ packages _your action_ as OCI artifacts and publishes it to the [GitHub Container registry](ghcr.io).
This allows your action to be consumed as an immutable package to make the actions ecosystem more secure.
This allows your action to be consumed as an _immutable_ package even if a [semver](https://semver.org/) is specified in the consumer's workflow file.
The whole action repository is packaged by default. Set `path` input to specify which path you want to package.
Make sure you use the [Starter Workflow](https://github.com/actions-on-packages/.github) (TODO) to run the action.
Please also ensure you have the release trigger in the workflow where you use this action.
Your action workflow must be triggered on `release` as in the following example. The release's title must follow [semantic versioning](https://semver.org/). Then consumers of your action will then be able to specify the version, e.g., `- uses: your-name/your-action@v1.2.3` or even `- uses: your-name/your-action@v1`.
## Usage
@@ -16,19 +13,8 @@ Please also ensure you have the release trigger in the workflow where you use th
on:
release:
- uses: immutable-actions/publish-action-package@1.0.1
- uses: immutable-actions/publish-action-package@v1
with:
# Personal access token (PAT) or GITHUB_TOKEN with write:package scope used to upload the package to GHCR. The GITHUB_TOKEN is taken by default.
#
# We recommend using a service account with the least permissions necessary. Also
# when generating a new PAT, select the least scopes necessary.
#
# [Learn more about creating and using encrypted secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets)
#
# Default: ${{ github.token }}
token: ''
# Relative path of the working directory of the repository to be tar archived
# and uploaded as OCI Artifact layer. You can mention multiple files/folders
# by mentioning relative paths as space separated values.
@@ -36,38 +22,9 @@ on:
# This defaults to the entire action repository contents if not explicitly defined.
# Default: '.'
path: 'src/ action.yml dist/'
```
<!-- end usage -->
## License
The scripts and documentation in this project are released under the [MIT License](LICENSE)
## [Internal] Differences from previous implementation
This is a new implementation of an Action which publishes a given release to ghcr.io (GitHub Packages).
It will eventually be moved to our `actions`` org.
The key differences are:
- This Action goes directly to GitHub Packages rather than using an API endpoint to pass a bundle to.
- This Action uses Node.js libraries to create both a `zip` and `tar.gz` of the content as layers.
- This Action creates and publishes the OCI manifest which houses those archives, which was previously done on the backend.
- This Action has the goal of generating provenance attestations for any release that is created.
- This Action parses and validates that the release tag which triggered it is in a valid SemVer format, either `1.0.3-prerelease` or `v1.0.0-prerelease`.
## [Internal] Features to consider adding to this Action
These are some features which should likely be part of this implementation.
- [ ] Parsing SemVer more strictly, based on what formats we decide to support (e.g. we might not support prerelease tags)
- [ ] Checking that there is a valid `action.yml` file in the repository running the action, failing if it is not an Action repository
- Could be as simple as just checking for the file, or could be validating it is yml with expected actions components
- [ ] Sanitising and validating relative paths passed into the `path` arg
- For example, checking that they're inside the repository of the action and not other places on the filsystem
- [ ] Integration with Attestations API (speak to `phillmv` about this)
- [ ] A way to dynamically work out the Container Registry's URL rather than relying on the user to provide it
- Options seem to be an API endpoint or an environment variable in the runner, but this might be difficult for backwards compatibility
The scripts and documentation in this project are released under the [MIT License](LICENSE).
+3 -10
View File
@@ -7,19 +7,10 @@ branding:
color: 'red'
inputs:
token:
required: true
description: >
GITHUB_TOKEN having the write:package scope to publish an action package to GHCR.
default: ${{ github.token }}
path:
required: false
description: The work directory or path to be tar archived and uploaded as OCI Artifact layer.
default: '.'
registry:
required: false
description: The registry to publish the action package to.
default: https://ghcr.io/ # TODO: this should perhaps be fetched from GitHub API.
outputs:
package-url:
@@ -33,8 +24,10 @@ runs:
shell: bash
# - run: node ./dist/index.js
# shell: bash
- uses: ddivad195/publish-action-package/package-and-publish@v0.0.51
- uses: ddivad195/publish-action-package/package-and-publish@v0.0.67
id: publish
env:
TOKEN: ${{ github.token }}
- name: Output variables
shell: bash
run: |
Generated Vendored
+14 -5
View File
@@ -74762,11 +74762,20 @@ async function run() {
core.setFailed(`${releaseTag} is not a valid semantic version, and so cannot be uploaded as an Immutable Action.`);
return;
}
// Gather & validate user inputs
const token = core.getInput('token');
const registryURL = new URL('https://ghcr.io/'); // TODO: Should this be dynamic? Maybe an API endpoint to grab the registry for GHES/proxima purposes.
console.log(core.getInput('registry'));
console.log(`registryURL: ${registryURL}`);
const token = process.env.TOKEN;
// TODO: once https://github.com/github/github/pull/309384 goes in, we can switch to the actual endpoint
//const response = await fetch(
// process.env.GITHUB_API_URL + '/packages/container-registry-url'
//)
const response = await fetch('http://echo.jsontest.com/url/https:ghcr.io' // for testing locally. Remove the slashes, they will be reintroduced when forming the URL object below
);
if (!response.ok) {
throw new Error(`Failed to fetch status page: ${response.statusText}`);
}
const data = await response.json();
const registryURL = new URL(data.url);
console.log(`Container registry URL: ${registryURL}`);
// Gather & validate user input
// Paths to be included in the OCI image
const paths = core.getInput('path').split(' ');
let path = '';
+25
View File
@@ -0,0 +1,25 @@
#!/bin/bash
VERSION=$1
MESSAGE=$2
if [ -z "$VERSION" ]
then
echo "No version supplied"
exit 1
fi
if [ -z "$MESSAGE" ]
then
echo "No message supplied"
exit 1
fi
echo "Generating new version $VERSION with message $MESSAGE"
sed -i '' -E 's/ddivad195\/publish-action-package\/package-and-publish.*$/ddivad195\/publish-action-package\/package-and-publish@'$VERSION'/g' action.yml
npm run bundle
git add .
git commit -m "$VERSION: $MESSAGE"
git push
gh release create --repo ddivad195/publish-action-package --title $VERSION --notes $VERSION $VERSION
-5
View File
@@ -7,11 +7,6 @@ branding:
color: 'red'
inputs:
token:
required: true
description: >
GITHUB_TOKEN having the write:package scope to publish an action package to GHCR.
default: ${{ github.token }}
path:
required: false
description: The work directory or path to be tar archived and uploaded as OCI Artifact layer.
+17 -5
View File
@@ -37,11 +37,23 @@ export async function run(): Promise<void> {
return
}
// Gather & validate user inputs
const token: string = core.getInput('token')
const registryURL: URL = new URL('https://ghcr.io/') // TODO: Should this be dynamic? Maybe an API endpoint to grab the registry for GHES/proxima purposes.
console.log(core.getInput('registry'))
console.log(`registryURL: ${registryURL}`)
const token: string = process.env.TOKEN!
// TODO: once https://github.com/github/github/pull/309384 goes in, we can switch to the actual endpoint
//const response = await fetch(
// process.env.GITHUB_API_URL + '/packages/container-registry-url'
//)
const response = await fetch(
'http://echo.jsontest.com/url/https:ghcr.io' // for testing locally. Remove the slashes, they will be reintroduced when forming the URL object below
)
if (!response.ok) {
throw new Error(`Failed to fetch status page: ${response.statusText}`)
}
const data = await response.json()
const registryURL: URL = new URL(data.url)
console.log(`Container registry URL: ${registryURL}`)
// Gather & validate user input
// Paths to be included in the OCI image
const paths: string[] = core.getInput('path').split(' ')
let path = ''