hackety hack
This commit is contained in:
commit
d1f298a0c6
13 changed files with 673 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
/Cargo.lock
|
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "glomar-models"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.193", features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_yaml = "0.9.29"
|
12
README.md
Normal file
12
README.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
glomar-models
|
||||
=============
|
||||
|
||||
"Low level" data models for GitHub Actions workflows, actions, and related components.
|
||||
|
||||
## Why?
|
||||
|
||||
I need these for another tool, and generating them automatically from
|
||||
[their JSON Schemas] wasn't working both for expressiveness and tool deficiency
|
||||
reasons.
|
||||
|
||||
[their JSON Schemas]: https://www.schemastore.org/json/
|
137
src/action.rs
Normal file
137
src/action.rs
Normal file
|
@ -0,0 +1,137 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A GitHub Actions action definition.
|
||||
///
|
||||
/// See: <https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions>
|
||||
/// and <https://json.schemastore.org/github-action.json>
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct Action {
|
||||
pub name: String,
|
||||
pub author: Option<String>,
|
||||
pub description: Option<String>,
|
||||
#[serde(default)]
|
||||
pub inputs: HashMap<String, Input>,
|
||||
#[serde(default)]
|
||||
pub outputs: HashMap<String, Output>,
|
||||
pub runs: Runs,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct Input {
|
||||
pub description: String,
|
||||
pub required: Option<bool>,
|
||||
pub default: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct Output {
|
||||
pub description: String,
|
||||
// NOTE: not optional for composite actions, but this is not worth modeling.
|
||||
pub value: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case", untagged)]
|
||||
pub enum Runs {
|
||||
JavaScript(JavaScript),
|
||||
Composite(Composite),
|
||||
Docker(Docker),
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct JavaScript {
|
||||
// "node12" | "node16" | "node20"
|
||||
pub using: String,
|
||||
pub main: String,
|
||||
pub pre: Option<String>,
|
||||
// Defaults to `always()`
|
||||
pub pre_if: Option<String>,
|
||||
pub post: Option<String>,
|
||||
// Defaults to `always()`
|
||||
pub post_if: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct Composite {
|
||||
// "composite"
|
||||
pub using: String,
|
||||
pub steps: Vec<Step>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case", untagged)]
|
||||
pub enum Step {
|
||||
/// A step that runs a command in a shell.
|
||||
RunShell(RunShell),
|
||||
/// A step that uses another GitHub Action.
|
||||
UseAction(UseAction),
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct RunShell {
|
||||
pub run: String,
|
||||
pub shell: String,
|
||||
pub name: Option<String>,
|
||||
pub id: Option<String>,
|
||||
pub r#if: Option<String>,
|
||||
#[serde(default)]
|
||||
pub env: HashMap<String, EnvValue>,
|
||||
#[serde(default)]
|
||||
pub continue_on_error: bool,
|
||||
pub working_directory: Option<String>,
|
||||
}
|
||||
|
||||
/// Environment variable values are always strings, but GitHub Actions
|
||||
/// allows users to configure them as various native YAML types before
|
||||
/// internal stringification.
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case", untagged)]
|
||||
pub enum EnvValue {
|
||||
String(String),
|
||||
Number(f64),
|
||||
Boolean(bool),
|
||||
}
|
||||
|
||||
impl ToString for EnvValue {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
Self::String(s) => s.clone(),
|
||||
Self::Number(n) => n.to_string(),
|
||||
Self::Boolean(b) => b.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct UseAction {
|
||||
pub uses: String,
|
||||
#[serde(default)]
|
||||
pub with: HashMap<String, String>,
|
||||
pub r#if: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct Docker {
|
||||
// "docker"
|
||||
pub using: String,
|
||||
pub image: String,
|
||||
#[serde(default)]
|
||||
pub env: HashMap<String, EnvValue>,
|
||||
pub entrypoint: Option<String>,
|
||||
pub pre_entrypoint: Option<String>,
|
||||
// Defaults to `always()`
|
||||
pub pre_if: Option<String>,
|
||||
pub post_entrypoint: Option<String>,
|
||||
// Defaults to `always()`
|
||||
pub post_if: Option<String>,
|
||||
}
|
0
src/dependabot/mod.rs
Normal file
0
src/dependabot/mod.rs
Normal file
3
src/lib.rs
Normal file
3
src/lib.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub mod action;
|
||||
pub mod dependabot;
|
||||
pub mod workflow;
|
177
src/workflow.rs
Normal file
177
src/workflow.rs
Normal file
|
@ -0,0 +1,177 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A single GitHub Actions workflow.
|
||||
///
|
||||
/// See: <https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions>
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct Workflow {
|
||||
pub name: Option<String>,
|
||||
pub run_name: Option<String>,
|
||||
pub on: Trigger,
|
||||
#[serde(default)]
|
||||
pub permissions: Permissions,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case", untagged)]
|
||||
pub enum Trigger {
|
||||
// A single "bare" event, like `on: push`.
|
||||
BareEvent(BareEvent),
|
||||
// Multiple "bare" events, like `on: [push, pull_request]`
|
||||
BareEvents(Vec<BareEvent>),
|
||||
// `schedule:` events.
|
||||
Schedule { schedule: Vec<Cron> },
|
||||
WorkflowCall { workflow_call: Option<WorkflowCall> },
|
||||
// "Rich" events, i.e. each event with its optional filters.
|
||||
Events(HashMap<BareEvent, Option<RichEvent>>),
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, PartialEq, Eq, Hash)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum BareEvent {
|
||||
BranchProtectionRule,
|
||||
CheckRun,
|
||||
CheckSuite,
|
||||
Create,
|
||||
Delete,
|
||||
Deployment,
|
||||
DeploymentStatus,
|
||||
Discussion,
|
||||
DiscussionComment,
|
||||
Fork,
|
||||
Gollum,
|
||||
IssueComment,
|
||||
Issues,
|
||||
Label,
|
||||
MergeGroup,
|
||||
Milestone,
|
||||
PageBuild,
|
||||
Project,
|
||||
ProjectCard,
|
||||
ProjectColumn,
|
||||
Public,
|
||||
PullRequest,
|
||||
PullRequestComment,
|
||||
PullRequestReview,
|
||||
PullRequestReviewComment,
|
||||
PullRequestTarget,
|
||||
Push,
|
||||
RegistryPackage,
|
||||
Release,
|
||||
RepositoryDispatch,
|
||||
// NOTE: `schedule` is omitted, since it's never bare.
|
||||
Status,
|
||||
Watch,
|
||||
WorkflowCall,
|
||||
WorkflowDispatch,
|
||||
WorkflowRun,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct Cron {
|
||||
cron: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct WorkflowCall {
|
||||
inputs: HashMap<String, WorkflowCallInput>,
|
||||
outputs: HashMap<String, WorkflowCallOutput>,
|
||||
secrets: HashMap<String, WorkflowCallSecret>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct WorkflowCallInput {
|
||||
description: Option<String>,
|
||||
// TODO: model `default`?
|
||||
#[serde(default)]
|
||||
required: bool,
|
||||
r#type: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct WorkflowCallOutput {
|
||||
description: Option<String>,
|
||||
value: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct WorkflowCallSecret {
|
||||
description: Option<String>,
|
||||
required: bool,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct RichEvent {
|
||||
#[serde(default)]
|
||||
types: Vec<String>,
|
||||
|
||||
// `push | pull_request | pull_request_target` only.
|
||||
#[serde(default)]
|
||||
branches: Vec<String>,
|
||||
|
||||
// `push | pull_request | pull_request_target` only.
|
||||
#[serde(default)]
|
||||
branches_ignore: Vec<String>,
|
||||
|
||||
// `push` only.
|
||||
#[serde(default)]
|
||||
tags: Vec<String>,
|
||||
|
||||
// `push` only.
|
||||
#[serde(default)]
|
||||
tags_ignore: Vec<String>,
|
||||
|
||||
// `push | pull_request | pull_request_target` only.
|
||||
#[serde(default)]
|
||||
paths: Vec<String>,
|
||||
|
||||
// `push | pull_request | pull_request_target` only.
|
||||
#[serde(default)]
|
||||
paths_ignore: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Default)]
|
||||
#[serde(rename_all = "kebab-case", untagged)]
|
||||
pub enum Permissions {
|
||||
/// Whatever default permissions come from the workflow's `GITHUB_TOKEN`.
|
||||
#[default]
|
||||
Token,
|
||||
ReadAll,
|
||||
WriteAll,
|
||||
Explicit(ExplicitPermissions),
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct ExplicitPermissions {
|
||||
pub actions: Permission,
|
||||
pub checks: Permission,
|
||||
pub contents: Permission,
|
||||
pub deployments: Permission,
|
||||
pub id_token: Permission,
|
||||
pub issues: Permission,
|
||||
pub discussions: Permission,
|
||||
pub packages: Permission,
|
||||
pub pages: Permission,
|
||||
pub pull_requests: Permission,
|
||||
pub repository_projects: Permission,
|
||||
pub security_events: Permission,
|
||||
pub statuses: Permission,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case", untagged)]
|
||||
pub enum Permission {
|
||||
Read,
|
||||
Write,
|
||||
None,
|
||||
}
|
88
tests/sample-actions/gh-action-pip-audit.yml
Normal file
88
tests/sample-actions/gh-action-pip-audit.yml
Normal file
|
@ -0,0 +1,88 @@
|
|||
# https://github.com/pypa/gh-action-pip-audit/blob/530374b67a3e8b3972d2caae7ee9a1d3dd486329/action.yml
|
||||
name: "gh-action-pip-audit"
|
||||
author: "William Woodruff <william@trailofbits.com>"
|
||||
description: "Use pip-audit to scan Python dependencies for known vulnerabilities"
|
||||
inputs:
|
||||
summary:
|
||||
description: "render a Markdown summary of the audit (default true)"
|
||||
required: false
|
||||
default: true
|
||||
no-deps:
|
||||
description: "don't do any dependency resolution (requires fully pinned requirements) (default false)"
|
||||
required: false
|
||||
default: false
|
||||
require-hashes:
|
||||
description: "enforce hashes (requirements-style inputs only) (default false)"
|
||||
required: false
|
||||
default: false
|
||||
vulnerability-service:
|
||||
description: "the vulnerability service to use (PyPI or OSV, defaults to PyPI)"
|
||||
required: false
|
||||
default: "PyPI"
|
||||
inputs:
|
||||
description: "the inputs to audit, whitespace separated (defaults to current path)"
|
||||
required: false
|
||||
default: ""
|
||||
virtual-environment:
|
||||
description: "the virtual environment to audit within (default none)"
|
||||
required: false
|
||||
default: ""
|
||||
local:
|
||||
description: "for environmental audits, consider only packages marked local (default false)"
|
||||
required: false
|
||||
default: false
|
||||
index-url:
|
||||
description: "the base URL for the PEP 503-compatible package index to use"
|
||||
required: false
|
||||
default: ""
|
||||
extra-index-urls:
|
||||
description: "extra PEP 503-compatible indexes to use, whitespace separated"
|
||||
required: false
|
||||
default: ""
|
||||
ignore-vulns:
|
||||
description: "vulnerabilities to explicitly exclude, if present (whitespace separated)"
|
||||
required: false
|
||||
default: ""
|
||||
internal-be-careful-allow-failure:
|
||||
description: "don't fail the job if the audit fails (default false)"
|
||||
required: false
|
||||
default: false
|
||||
internal-be-careful-extra-flags:
|
||||
description: "extra flags to be passed in to pip-audit"
|
||||
required: false
|
||||
default: ""
|
||||
outputs:
|
||||
internal-be-careful-output:
|
||||
description: "the column-formatted output from pip-audit, wrapped as base64"
|
||||
value: "${{ steps.pip-audit.outputs.output }}"
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Set up pip-audit
|
||||
run: |
|
||||
# NOTE: Sourced, not executed as a script.
|
||||
source "${{ github.action_path }}/setup/setup.bash"
|
||||
env:
|
||||
GHA_PIP_AUDIT_VIRTUAL_ENVIRONMENT: "${{ inputs.virtual-environment }}"
|
||||
shell: bash
|
||||
|
||||
- name: Run pip-audit
|
||||
id: pip-audit
|
||||
run: |
|
||||
# NOTE: Sourced, not executed as a script.
|
||||
source "${{ github.action_path }}/setup/venv.bash"
|
||||
|
||||
python "${{ github.action_path }}/action.py" "${{ inputs.inputs }}"
|
||||
env:
|
||||
GHA_PIP_AUDIT_SUMMARY: "${{ inputs.summary }}"
|
||||
GHA_PIP_AUDIT_NO_DEPS: "${{ inputs.no-deps }}"
|
||||
GHA_PIP_AUDIT_REQUIRE_HASHES: "${{ inputs.require-hashes }}"
|
||||
GHA_PIP_AUDIT_VULNERABILITY_SERVICE: "${{ inputs.vulnerability-service }}"
|
||||
GHA_PIP_AUDIT_VIRTUAL_ENVIRONMENT: "${{ inputs.virtual-environment }}"
|
||||
GHA_PIP_AUDIT_LOCAL: "${{ inputs.local }}"
|
||||
GHA_PIP_AUDIT_INDEX_URL: "${{ inputs.index-url }}"
|
||||
GHA_PIP_AUDIT_EXTRA_INDEX_URLS: "${{ inputs.extra-index-urls }}"
|
||||
GHA_PIP_AUDIT_IGNORE_VULNS: "${{ inputs.ignore-vulns }}"
|
||||
GHA_PIP_AUDIT_INTERNAL_BE_CAREFUL_ALLOW_FAILURE: "${{ inputs.internal-be-careful-allow-failure }}"
|
||||
GHA_PIP_AUDIT_INTERNAL_BE_CAREFUL_EXTRA_FLAGS: "${{ inputs.internal-be-careful-extra-flags }}"
|
||||
shell: bash
|
98
tests/sample-actions/gh-action-pypi-publish.yml
Normal file
98
tests/sample-actions/gh-action-pypi-publish.yml
Normal file
|
@ -0,0 +1,98 @@
|
|||
# https://github.com/pypa/gh-action-pypi-publish/blob/2f6f737ca5f74c637829c0f5c3acd0e29ea5e8bf/action.yml
|
||||
---
|
||||
name: pypi-publish
|
||||
description: Upload Python distribution packages to PyPI
|
||||
inputs:
|
||||
user:
|
||||
description: PyPI user
|
||||
required: false
|
||||
default: __token__
|
||||
password:
|
||||
description: Password for your PyPI user or an access token
|
||||
required: false
|
||||
repository-url: # Canonical alias for `repository_url`
|
||||
description: The repository URL to use
|
||||
required: false
|
||||
repository_url: # DEPRECATED ALIAS; TODO: Remove in v3+
|
||||
description: >-
|
||||
[DEPRECATED]
|
||||
The repository URL to use
|
||||
deprecationMessage: >-
|
||||
The inputs have been normalized to use kebab-case.
|
||||
Use `repository-url` instead.
|
||||
required: false
|
||||
default: https://upload.pypi.org/legacy/
|
||||
packages-dir: # Canonical alias for `packages_dir`
|
||||
description: The target directory for distribution
|
||||
required: false
|
||||
# default: dist # TODO: uncomment once alias removed
|
||||
packages_dir: # DEPRECATED ALIAS; TODO: Remove in v3+
|
||||
description: >-
|
||||
[DEPRECATED]
|
||||
The target directory for distribution
|
||||
deprecationMessage: >-
|
||||
The inputs have been normalized to use kebab-case.
|
||||
Use `packages-dir` instead.
|
||||
required: false
|
||||
default: dist
|
||||
verify-metadata: # Canonical alias for `verify_metadata`
|
||||
description: Check metadata before uploading
|
||||
required: false
|
||||
# default: 'true' # TODO: uncomment once alias removed
|
||||
verify_metadata: # DEPRECATED ALIAS; TODO: Remove in v3+
|
||||
description: >-
|
||||
[DEPRECATED]
|
||||
Check metadata before uploading
|
||||
deprecationMessage: >-
|
||||
The inputs have been normalized to use kebab-case.
|
||||
Use `verify-metadata` instead.
|
||||
required: false
|
||||
default: "true"
|
||||
skip-existing: # Canonical alias for `skip_existing`
|
||||
description: >-
|
||||
Do not fail if a Python package distribution
|
||||
exists in the target package index
|
||||
required: false
|
||||
# default: 'false' # TODO: uncomment once alias removed
|
||||
skip_existing: # DEPRECATED ALIAS; TODO: Remove in v3+
|
||||
description: >-
|
||||
[DEPRECATED]
|
||||
Do not fail if a Python package distribution
|
||||
exists in the target package index
|
||||
deprecationMessage: >-
|
||||
The inputs have been normalized to use kebab-case.
|
||||
Use `skip-existing` instead.
|
||||
required: false
|
||||
default: "false"
|
||||
verbose:
|
||||
description: Show verbose output.
|
||||
required: false
|
||||
default: "false"
|
||||
print-hash: # Canonical alias for `print_hash`
|
||||
description: Show hash values of files to be uploaded
|
||||
required: false
|
||||
# default: 'false' # TODO: uncomment once alias removed
|
||||
print_hash: # DEPRECATED ALIAS; TODO: Remove in v3+
|
||||
description: >-
|
||||
[DEPRECATED]
|
||||
Show hash values of files to be uploaded
|
||||
deprecationMessage: >-
|
||||
The inputs have been normalized to use kebab-case.
|
||||
Use `print-hash` instead.
|
||||
required: false
|
||||
default: "false"
|
||||
branding:
|
||||
color: yellow
|
||||
icon: upload-cloud
|
||||
runs:
|
||||
using: docker
|
||||
image: Dockerfile
|
||||
args:
|
||||
- ${{ inputs.user }}
|
||||
- ${{ inputs.password }}
|
||||
- ${{ inputs.repository-url }}
|
||||
- ${{ inputs.packages-dir }}
|
||||
- ${{ inputs.verify-metadata }}
|
||||
- ${{ inputs.skip-existing }}
|
||||
- ${{ inputs.verbose }}
|
||||
- ${{ inputs.print-hash }}
|
44
tests/sample-actions/setup-python.yml
Normal file
44
tests/sample-actions/setup-python.yml
Normal file
|
@ -0,0 +1,44 @@
|
|||
# https://github.com/actions/setup-python/blob/e9d6f990972a57673cdb72ec29e19d42ba28880f/action.yml
|
||||
---
|
||||
name: "Setup Python"
|
||||
description: "Set up a specific version of Python and add the command-line tools to the PATH."
|
||||
author: "GitHub"
|
||||
inputs:
|
||||
python-version:
|
||||
description: "Version range or exact version of Python or PyPy to use, using SemVer's version range syntax. Reads from .python-version if unset."
|
||||
python-version-file:
|
||||
description: "File containing the Python version to use. Example: .python-version"
|
||||
cache:
|
||||
description: "Used to specify a package manager for caching in the default directory. Supported values: pip, pipenv, poetry."
|
||||
required: false
|
||||
architecture:
|
||||
description: "The target architecture (x86, x64) of the Python or PyPy interpreter."
|
||||
check-latest:
|
||||
description: "Set this option if you want the action to check for the latest available version that satisfies the version spec."
|
||||
default: false
|
||||
token:
|
||||
description: "The token used to authenticate when fetching Python distributions from https://github.com/actions/python-versions. When running this action on github.com, the default value is sufficient. When running on GHES, you can pass a personal access token for github.com if you are experiencing rate limiting."
|
||||
default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
|
||||
cache-dependency-path:
|
||||
description: "Used to specify the path to dependency files. Supports wildcards or a list of file names for caching multiple dependencies."
|
||||
update-environment:
|
||||
description: "Set this option if you want the action to update environment variables."
|
||||
default: true
|
||||
allow-prereleases:
|
||||
description: "When 'true', a version range passed to 'python-version' input will match prerelease versions if no GA versions are found. Only 'x.y' version range is supported for CPython."
|
||||
default: false
|
||||
outputs:
|
||||
python-version:
|
||||
description: "The installed Python or PyPy version. Useful when given a version range as input."
|
||||
cache-hit:
|
||||
description: "A boolean value to indicate a cache entry was found"
|
||||
python-path:
|
||||
description: "The absolute path to the Python or PyPy executable."
|
||||
runs:
|
||||
using: "node20"
|
||||
main: "dist/setup/index.js"
|
||||
post: "dist/cache-save/index.js"
|
||||
post-if: success()
|
||||
branding:
|
||||
icon: "code"
|
||||
color: "yellow"
|
33
tests/sample-workflows/pip-audit-ci.yml
Normal file
33
tests/sample-workflows/pip-audit-ci.yml
Normal file
|
@ -0,0 +1,33 @@
|
|||
# https://github.com/pypa/pip-audit/blob/1fd67af0653a8e66b9470adab2e408a435632f19/.github/workflows/ci.yml
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: "0 12 * * *"
|
||||
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
python:
|
||||
- "3.8"
|
||||
- "3.9"
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.1
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
cache: "pip"
|
||||
cache-dependency-path: pyproject.toml
|
||||
|
||||
- name: test
|
||||
run: make test PIP_AUDIT_EXTRA=test
|
45
tests/test_action.rs
Normal file
45
tests/test_action.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
use std::{env, path::Path};
|
||||
|
||||
use glomar_models::action::{Action, Runs};
|
||||
|
||||
fn load_action(name: &str) -> Action {
|
||||
let action_path = Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("tests/sample-actions")
|
||||
.join(name);
|
||||
let action_contents = std::fs::read_to_string(action_path).unwrap();
|
||||
serde_yaml::from_str(&action_contents).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_load_all() {
|
||||
let sample_actions = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/sample-actions");
|
||||
|
||||
for sample_action in std::fs::read_dir(&sample_actions).unwrap() {
|
||||
let sample_action = sample_action.unwrap().path();
|
||||
let action_contents = std::fs::read_to_string(sample_action).unwrap();
|
||||
serde_yaml::from_str::<Action>(&action_contents).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_setup_python() {
|
||||
let setup_python = load_action("setup-python.yml");
|
||||
|
||||
assert_eq!(setup_python.name, "Setup Python");
|
||||
assert_eq!(
|
||||
setup_python.description.unwrap(),
|
||||
"Set up a specific version of Python and add the command-line tools to the PATH."
|
||||
);
|
||||
assert_eq!(setup_python.author.unwrap(), "GitHub");
|
||||
|
||||
assert_eq!(setup_python.inputs.len(), 9);
|
||||
assert_eq!(setup_python.outputs.len(), 3);
|
||||
|
||||
let Runs::JavaScript(runs) = setup_python.runs else {
|
||||
unreachable!();
|
||||
};
|
||||
assert_eq!(runs.using, "node20");
|
||||
assert_eq!(runs.main, "dist/setup/index.js");
|
||||
assert_eq!(runs.post.unwrap(), "dist/cache-save/index.js");
|
||||
assert_eq!(runs.post_if.unwrap(), "success()");
|
||||
}
|
22
tests/test_workflow.rs
Normal file
22
tests/test_workflow.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
use std::{env, path::Path};
|
||||
|
||||
use glomar_models::workflow::Workflow;
|
||||
|
||||
fn load_workflow(name: &str) -> Workflow {
|
||||
let workflow_path = Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("tests/sample-workflows")
|
||||
.join(name);
|
||||
let workflow_contents = std::fs::read_to_string(workflow_path).unwrap();
|
||||
serde_yaml::from_str(&workflow_contents).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_load_all() {
|
||||
let sample_workflows = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/sample-workflows");
|
||||
|
||||
for sample_action in std::fs::read_dir(&sample_workflows).unwrap() {
|
||||
let sample_workflow = sample_action.unwrap().path();
|
||||
let workflow_contents = std::fs::read_to_string(sample_workflow).unwrap();
|
||||
serde_yaml::from_str::<Workflow>(&workflow_contents).unwrap();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue