├── Dockerfile ├── src ├── main.sh ├── install_dependencies.wls └── submit_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::Submitting Paclet..." 25 | wolfram_script "${SCRIPT_DIR}/submit_paclet.wls" 26 | echo "::endgroup::" -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'Submit Paclet' 2 | description: 'Submit a paclet using its definition notebook file' 3 | branding: 4 | icon: 'upload-cloud' 5 | color: 'orange' 6 | inputs: 7 | definition_notebook: 8 | description: 'Path to the definition notebook' 9 | required: false 10 | default: './ResourceDefinition.nb' 11 | paclet_cicd_version: 12 | description: 'Version of PacletCICD to use' 13 | required: false 14 | default: 'latest' 15 | resource_system_base: 16 | description: 'Specifies the location of the resource system' 17 | required: false 18 | default: 'https://www.wolframcloud.com/obj/resourcesystem/api/1.0' 19 | runs: 20 | using: 'docker' 21 | image: 'Dockerfile' 22 | -------------------------------------------------------------------------------- /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:: *) -------------------------------------------------------------------------------- /src/submit_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[ "Submitting paclet..." ]; 24 | 25 | (* ::**********************************************************************:: *) 26 | (* ::Section::Closed:: *) 27 | (*Inputs*) 28 | 29 | (* ::**********************************************************************:: *) 30 | (* ::Subsection::Closed:: *) 31 | (*Definition Notebook*) 32 | defNB = getInput[ "DEFINITION_NOTEBOOK" ]; 33 | If[ ! FileExistsQ @ ExpandFileName @ defNB, 34 | print[ "::error::Definition notebook not found: ", defNB ]; 35 | Exit[ 1 ] 36 | ]; 37 | 38 | (* ::**********************************************************************:: *) 39 | (* ::Subsection::Closed:: *) 40 | (*ResourceSystemBase*) 41 | rsBase = getInput[ "RESOURCE_SYSTEM_BASE" ]; 42 | rsTestURL = URLBuild @ { rsBase, "TestSystem" }; 43 | rsBaseTest = URLFetch[ rsTestURL, { "StatusCode", "Content" } ]; 44 | If[ ! MatchQ[ rsBaseTest, { 200, _String } ], 45 | print[ "::error::Invalid ResourceSystemBase: ", rsBase ]; 46 | print[ "::error::ResourceSystemBase test output: ", rsBaseTest ]; 47 | Exit[ 1 ] 48 | ]; 49 | 50 | Needs[ "ResourceSystemClient`" -> None ]; 51 | $ResourceSystemBase = rsBase; 52 | 53 | (* ::**********************************************************************:: *) 54 | (* ::Section::Closed:: *) 55 | (*Run*) 56 | result = 57 | Block[ 58 | { 59 | Print = print, 60 | DefinitionNotebookClient`BeginConsoleGroup, 61 | DefinitionNotebookClient`EndConsoleGroup 62 | }, 63 | Wolfram`PacletCICD`SubmitPaclet[ 64 | File @ defNB, 65 | "ConsoleType" -> "GitHub" 66 | ] 67 | ]; 68 | 69 | print @ result; 70 | 71 | If[ MatchQ[ result, _Wolfram`PacletCICD`SubmitPaclet ], 72 | print[ "::error::Wolfram`PacletCICD`SubmitPaclet not defined" ]; 73 | Exit[ 1 ] 74 | ]; 75 | 76 | (* :!CodeAnalysis::EndBlock:: *) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Submit Paclet to the [Wolfram Language Paclet Repository](https://resources.wolframcloud.com/PacletRepository/) 2 | 3 | The Submit Paclet action is an interface to the 4 | [`SubmitPaclet`](https://resources.wolframcloud.com/PacletRepository/resources/Wolfram/PacletCICD/ref/SubmitPaclet.html) 5 | function from 6 | [Wolfram/PacletCICD](https://resources.wolframcloud.com/PacletRepository/resources/Wolfram/PacletCICD/) 7 | and can be used to publish your Wolfram Language paclet from within GitHub Actions. 8 | This is roughly equivalent to using the **Submit to Repository** button 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", "Submit"] 18 | ``` 19 | 20 | Alternatively, using GitHub actions YAML syntax directly: 21 | ```yaml 22 | name: Submit Paclet 23 | on: [workflow_dispatch] 24 | jobs: 25 | Submit: 26 | name: Submit 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 | RESOURCE_PUBLISHER_TOKEN: ${{ secrets.RESOURCE_PUBLISHER_TOKEN }} 34 | steps: 35 | - name: Checkout repository 36 | uses: actions/checkout@v2 37 | - name: Submit paclet 38 | uses: WolframResearch/submit-paclet@v1 39 | ``` 40 | 41 | ## Parameters 42 | 43 | Input | Default | Description 44 | ------------------------- | --------------------------- | --------------- 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 and a resource publisher token defined as repository secrets. 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 checking your paclet for potential issues](https://github.com/WolframResearch/check-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/) --------------------------------------------------------------------------------