├── Dockerfile ├── src ├── main.sh ├── install_dependencies.wls └── check_paclet.wls ├── action.yml ├── LICENSE └── README.md /Dockerfile: -------------------------------------------------------------------------------- 1 | # Container image that runs your code 2 | FROM wolframresearch/wolframengine:latest 3 | 4 | COPY ["src", "/src/"] 5 | 6 | USER root 7 | RUN chmod +x /src/main.sh 8 | 9 | ENTRYPOINT ["/src/main.sh"] -------------------------------------------------------------------------------- /src/main.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export SCRIPT_DIR=$(dirname ${0}) 4 | 5 | wolfram_script () { 6 | wolframscript -file "${1}" 7 | WS_EXIT_CODE=$(echo $?) 8 | case $WS_EXIT_CODE in 9 | 0) 10 | ;; 11 | 139) 12 | echo "::warning::Warning: wolframscript did not exit cleanly" 13 | ;; 14 | *) 15 | exit $WS_EXIT_CODE 16 | ;; 17 | esac 18 | } 19 | 20 | echo "::group::Installing dependencies..." 21 | wolfram_script "${SCRIPT_DIR}/install_dependencies.wls" 22 | echo "::endgroup::" 23 | 24 | echo "::group::Checking Paclet..." 25 | wolfram_script "${SCRIPT_DIR}/check_paclet.wls" 26 | echo "::endgroup::" -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'Check Paclet' 2 | description: 'Check a paclet using its definition notebook file' 3 | branding: 4 | icon: 'check-circle' 5 | color: 'orange' 6 | inputs: 7 | target: # id of input 8 | description: 'The target' 9 | required: false 10 | default: 'Submit' 11 | definition_notebook: 12 | description: 'Path to the definition notebook' 13 | required: false 14 | default: './ResourceDefinition.nb' 15 | debug: 16 | description: 'Whether to enable additional debug output' 17 | required: false 18 | default: 'false' 19 | paclet_cicd_version: 20 | description: 'Version of PacletCICD to use' 21 | required: false 22 | default: 'latest' 23 | resource_system_base: 24 | description: 'Specifies the location of the resource system' 25 | required: false 26 | default: 'https://www.wolframcloud.com/obj/resourcesystem/api/1.0' 27 | runs: 28 | using: 'docker' 29 | image: 'Dockerfile' 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Rick Hennigan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/install_dependencies.wls: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env wolframscript 2 | (* ::Package:: *) 3 | 4 | (* :!CodeAnalysis::BeginBlock:: *) 5 | (* :!CodeAnalysis::Disable::SuspiciousSessionSymbol:: *) 6 | 7 | print[ a___ ] := WriteString[ "stdout", a, "\n" ]; 8 | 9 | getInput[ name_String ] := 10 | Module[ { val }, 11 | val = Environment[ "INPUT_" <> name ]; 12 | print[ name, "=", val ]; 13 | val 14 | ]; 15 | 16 | 17 | pacletInstall[ url_String? urlQ ] := Enclose[ 18 | Module[ { installed }, 19 | print[ "Installing paclet from: ", url ]; 20 | installed = PacletInstall[ url, ForceVersionInstall -> True ]; 21 | If[ PacletObjectQ @ installed, 22 | print[ "Paclet installed to: ", installed[ "Location" ] ], 23 | print[ "::error:: Paclet installation failed: ", installed ]; 24 | Exit[ 1 ] 25 | ] 26 | ], 27 | Function[ 28 | print[ "::error:: Paclet installation failed: ", url ]; 29 | Exit[ 1 ] 30 | ] 31 | ]; 32 | 33 | 34 | urlQ[ url_String ] := StringQ @ URLParse[ url, "Scheme" ]; 35 | urlQ[ ___ ] := False; 36 | 37 | 38 | toPacletCICDURL[ "latest" ] := 39 | Part[ 40 | URLExecute[ 41 | "https://api.github.com/repos/WolframResearch/PacletCICD/releases/latest", 42 | "RawJSON" 43 | ], 44 | "assets", 45 | 1, 46 | "browser_download_url" 47 | ]; 48 | 49 | toPacletCICDURL[ vers_String ] := 50 | If[ StringMatchQ[ vers, (DigitCharacter..~~".")...~~(DigitCharacter..) ], 51 | TemplateApply[ 52 | "https://github.com/WolframResearch/PacletCICD/releases/download/v`1`/Wolfram__PacletCICD-`1`.paclet", 53 | { vers } 54 | ], 55 | TemplateApply[ 56 | "https://github.com/WolframResearch/PacletCICD/archive/refs/heads/`1`.zip", 57 | vers 58 | ] 59 | ]; 60 | 61 | 62 | pacVer = getInput[ "PACLET_CICD_VERSION" ]; 63 | pacURL = toPacletCICDURL @ pacVer; 64 | 65 | If[ ! StringQ @ pacURL, 66 | Print[ "Could not determine URL for specified version" ]; 67 | Exit[ 1 ] 68 | ]; 69 | 70 | pacletInstall @ pacURL; 71 | 72 | (* :!CodeAnalysis::EndBlock:: *) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Check Paclet for the [Wolfram Language Paclet Repository](https://resources.wolframcloud.com/PacletRepository/) 2 | 3 | The Check Paclet action is an interface to the 4 | [`CheckPaclet`](https://resources.wolframcloud.com/PacletRepository/resources/Wolfram/PacletCICD/ref/CheckPaclet.html) 5 | function from 6 | [Wolfram/PacletCICD](https://resources.wolframcloud.com/PacletRepository/resources/Wolfram/PacletCICD/) 7 | and can be used to check your Wolfram Language paclet for potential issues within GitHub Actions. 8 | This is roughly equivalent to using the **Check > All** menu item from the resource definition notebook within 9 | Wolfram Desktop or Mathematica. 10 | 11 | ## Usage 12 | 13 | A YAML file that uses this action can be automatically generated for your paclet using 14 | [`WorkflowExport`](https://resources.wolframcloud.com/PacletRepository/resources/Wolfram/PacletCICD/ref/WorkflowExport.html): 15 | 16 | ```Mathematica 17 | PacletSymbol["Wolfram/PacletCICD", "WorkflowExport"]["path/to/paclet", "Check"] 18 | ``` 19 | 20 | Alternatively, using GitHub actions YAML syntax directly: 21 | ```yaml 22 | name: Check Paclet 23 | on: [push] 24 | jobs: 25 | Check: 26 | name: Check Paclet 27 | runs-on: ubuntu-latest 28 | container: 29 | image: wolframresearch/wolframengine:latest 30 | options: --user root 31 | env: 32 | WOLFRAMSCRIPT_ENTITLEMENTID: ${{ secrets.WOLFRAMSCRIPT_ENTITLEMENTID }} 33 | steps: 34 | - name: Checkout repository 35 | uses: actions/checkout@v2 36 | - name: Check paclet 37 | uses: WolframResearch/check-paclet@v1 38 | ``` 39 | 40 | ## Parameters 41 | 42 | Input | Default | Description 43 | ------------------------- | --------------------------- | --------------- 44 | `target` | `"Submit"` | The named configuration to use for error checking. Some possible values are `"Build"`, `"Check"`, `"Deploy"`, and `"Submit"`. 45 | `definition_notebook` | `"./ResourceDefinition.nb"` | The relative path to the paclet's resource definition notebook 46 | `paclet_cicd_version` | `"latest"` | The version of [PacletCICD](https://resources.wolframcloud.com/PacletRepository/resources/Wolfram/PacletCICD/) to use 47 | 48 | ## Notes 49 | For this action to work, your repository needs to have a license entitlement ID defined as a repository secret. See [this tutorial](https://resources.wolframcloud.com/PacletRepository/resources/Wolfram/PacletCICD/tutorial/GitHubActionsQuickStart.html) for details. 50 | 51 | 52 | ## See Also 53 | 54 | - [Action for building your paclet](https://github.com/WolframResearch/build-paclet) 55 | - [Action for submitting your paclet to the Wolfram Language Paclet Repository](https://github.com/WolframResearch/submit-paclet) 56 | - [Action for running your paclet test files](https://github.com/WolframResearch/test-paclet) 57 | - [Continuous Integration and Deployment for Wolfram Language Paclets](https://resources.wolframcloud.com/PacletRepository/resources/Wolfram/PacletCICD/) -------------------------------------------------------------------------------- /src/check_paclet.wls: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env wolframscript 2 | (* ::Package:: *) 3 | 4 | (* :!CodeAnalysis::BeginBlock:: *) 5 | (* :!CodeAnalysis::Disable::SuspiciousSessionSymbol:: *) 6 | 7 | (* ::**********************************************************************:: *) 8 | (* ::Section::Closed:: *) 9 | (*Initialization*) 10 | print[ a___ ] := WriteString[ "stdout", a, "\n" ]; 11 | 12 | print[ "Loading Wolfram`PacletCICD` from ", FindFile[ "Wolfram`PacletCICD`" ] ]; 13 | 14 | Needs[ "Wolfram`PacletCICD`" ]; 15 | 16 | getInput[ name_String ] := 17 | Module[ { val }, 18 | val = Environment[ "INPUT_" <> name ]; 19 | print[ name, "=", val ]; 20 | val 21 | ]; 22 | 23 | print[ "Checking paclet..." ]; 24 | 25 | (* ::**********************************************************************:: *) 26 | (* ::Section::Closed:: *) 27 | (*Inputs*) 28 | 29 | (* ::**********************************************************************:: *) 30 | (* ::Subsection::Closed:: *) 31 | (*Debug*) 32 | debug = Interpreter[ "Boolean" ][ getInput[ "DEBUG" ] ]; 33 | If[ ! BooleanQ @ debug, 34 | print[ "::error::Expected a boolean value for input 'debug' instead of ", 35 | getInput[ "DEBUG" ] 36 | ]; 37 | Exit[ 1 ] 38 | ]; 39 | 40 | (* ::**********************************************************************:: *) 41 | (* ::Subsection::Closed:: *) 42 | (*Definition Notebook*) 43 | defNB = getInput[ "DEFINITION_NOTEBOOK" ]; 44 | If[ ! FileExistsQ @ ExpandFileName @ defNB, 45 | print[ "::error::Definition notebook not found: ", defNB ]; 46 | Exit[ 1 ] 47 | ]; 48 | 49 | (* ::**********************************************************************:: *) 50 | (* ::Subsection::Closed:: *) 51 | (*ResourceSystemBase*) 52 | rsBase = getInput[ "RESOURCE_SYSTEM_BASE" ]; 53 | rsTestURL = URLBuild @ { rsBase, "TestSystem" }; 54 | rsBaseTest = URLFetch[ rsTestURL, { "StatusCode", "Content" } ]; 55 | If[ ! MatchQ[ rsBaseTest, { 200, _String } ], 56 | print[ "::error::Invalid ResourceSystemBase: ", rsBase ]; 57 | print[ "::error::ResourceSystemBase test output: ", rsBaseTest ]; 58 | Exit[ 1 ] 59 | ]; 60 | 61 | Needs[ "ResourceSystemClient`" -> None ]; 62 | $ResourceSystemBase = rsBase; 63 | 64 | (* ::**********************************************************************:: *) 65 | (* ::Subsection::Closed:: *) 66 | (*Target*) 67 | target = getInput[ "TARGET" ]; 68 | 69 | (* ::**********************************************************************:: *) 70 | (* ::Section::Closed:: *) 71 | (*Run*) 72 | result = 73 | Block[ 74 | { 75 | Print = print, 76 | DefinitionNotebookClient`BeginConsoleGroup, 77 | DefinitionNotebookClient`EndConsoleGroup 78 | }, 79 | Wolfram`PacletCICD`CheckPaclet[ 80 | File @ defNB, 81 | "Target" -> target, 82 | "Debug" -> debug, 83 | "ConsoleType" -> "GitHub" 84 | ] 85 | ]; 86 | 87 | print @ result; 88 | 89 | If[ MatchQ[ result, _Wolfram`PacletCICD`CheckPaclet ], 90 | print[ "::error::Wolfram`PacletCICD`CheckPaclet not defined" ]; 91 | Exit[ 1 ] 92 | ]; 93 | 94 | (* :!CodeAnalysis::EndBlock:: *) --------------------------------------------------------------------------------