commit 74f31b5990e2a766147fa7bf10e453053374df5b Author: Benjamin Grandfond Date: Tue Jan 17 09:49:45 2023 +0100 Add submission issue form and validation workflows diff --git a/.github/ISSUE_TEMPLATE/1_automatic_review.yaml b/.github/ISSUE_TEMPLATE/1_automatic_review.yaml new file mode 100644 index 0000000..816db66 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1_automatic_review.yaml @@ -0,0 +1,35 @@ +name: Submit an extension without review +description: Submit your extension to be automatically validated and published on the marketplace without Docker review. +title: "[Submission]: " +assignees: [] +body: + - type: markdown + attributes: + value: | + Hi :wave:, + + Speaking for the whole @docker/extensions, thank you for creating an extension and submitting it! + + Once you have filled the following form and submitted this issue, some automatic validations will run. + + :+1: If everything goes well, a new label `validation/succeeded` will be added and the @docker/extensions will be pinged. Later, someone from the team will add the `publish/ready` which will trigger an automatic job to publish the extension on the marketplace. + + :confused: If there are some issues, we will add the problems as comment and close the issue. Once you have fixed all the problems, re-open the issue and the process will start over. + - type: input + attributes: + label: Docker Hub repository name + description: Provide the Docker Hub repository name for your extension so that we can install it. + placeholder: docker/resource-usage-extension + validations: + required: true + - type: markdown + attributes: + value: | + :warning: We automatically validate the greatest [semver](https://semver.org/) tag available on Docker Hub. See [the documentation](https://docs.docker.com/desktop/extensions-sdk/extensions/DISTRIBUTION/#release-your-extension) for more details. + - type: checkboxes + attributes: + label: Terms of services + options: + - label: I accept the [term of services](https://www.docker.com/legal/extensions_marketplace_developer_agreement/) + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..1cd5aee --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Share an extension idea + url: https://github.com/docker/extension-ideas/discussions + about: Have an idea for an extension? Share it with us! + - name: Extension SDK issues + url: https://github.com/docker/extensions-sdk + about: For issues related to the extension SDK, please use the docker/extensions-sdk repository. + - name: Extension SDK documentation issues + url: https://github.com/docker/docs + about: For issues related to the documentation, please use the docker/docs repository. \ No newline at end of file diff --git a/.github/workflows/templates/tos-accepted.md b/.github/workflows/templates/tos-accepted.md new file mode 100644 index 0000000..0f91d2f --- /dev/null +++ b/.github/workflows/templates/tos-accepted.md @@ -0,0 +1,6 @@ +:white_check_mark: @{{ .user }} has accepted the terms of service. + +The automatic validation for publishing your extension has started, you will see the result in ~10 minutes :hourglass_flowing_sand:. + +--- +See [action]({{ .workflow_url }}) for more details. diff --git a/.github/workflows/templates/tos-not-accepted.md b/.github/workflows/templates/tos-not-accepted.md new file mode 100644 index 0000000..6fe1453 --- /dev/null +++ b/.github/workflows/templates/tos-not-accepted.md @@ -0,0 +1,6 @@ +:x: Terms of Service not accepted yet. + +@{{ .user }} to proceed with the submission of your extension you must accept the [term of services](https://www.docker.com/legal/extensions_marketplace_developer_agreement/). + +--- +See [action]({{ .workflow_url }}) for more details. diff --git a/.github/workflows/templates/tos-not-found.md b/.github/workflows/templates/tos-not-found.md new file mode 100644 index 0000000..c488116 --- /dev/null +++ b/.github/workflows/templates/tos-not-found.md @@ -0,0 +1,6 @@ +:no_entry_sign: Checkbox for the terms of service not found. + +@docker/extensions, can you add it back to the issue body? + +--- +See [action]({{ .workflow_url }}) for more details. diff --git a/.github/workflows/tos.yaml b/.github/workflows/tos.yaml new file mode 100644 index 0000000..0636f66 --- /dev/null +++ b/.github/workflows/tos.yaml @@ -0,0 +1,117 @@ +name: TOS Check + +on: + issues: + types: + - opened + - reopened + - edited + issue_comment: + types: + - created + - edited + +env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + +jobs: + check: + if: github.event.issue.closed == false + name: Ensure Terms of Service are accepted + runs-on: ubuntu-latest + permissions: + issues: write + outputs: + accepted: ${{ steps.are_tos_accepted.outputs.accepted }} + steps: + - name: Run /validate command + if: github.event_name == 'issue_comment' + run: | + command=$(echo "${{ github.event.comment.body }}" | head -1) + if [[ $command != "/validate"* ]]; then + echo "No /validate command found in first line of the comment \"${command}\", skipping" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + + - name: Parse issue body + id: parse + uses: zentered/issue-forms-body-parser@v1.5.1 + + - name: Find TOS checkbox state + id: are_tos_accepted + run: | + echo "accepted=$(echo '${{ steps.parse.outputs.data }}' | jq -r '.["terms-of-services"].list[0].checked' )" >> $GITHUB_OUTPUT + + - name: Remove 'tos/accepted' label + if: steps.are_tos_accepted.outputs.accepted == 'false' + run: | + gh issue edit ${{ github.event.issue.number }} --remove-label tos/accepted + gh issue edit ${{ github.event.issue.number }} --add-label tos/not-accepted + + - name: Add 'tos/accepted' label + if: steps.are_tos_accepted.outputs.accepted == 'true' + run: | + gh issue edit ${{ github.event.issue.number }} --add-label tos/accepted + gh issue edit ${{ github.event.issue.number }} --remove-label tos/not-accepted + + - uses: actions/checkout@v3 + + - name: Render template when tos are not accepted + id: template_tos_not_accepted + if: steps.are_tos_accepted.outputs.accepted == 'false' + uses: chuhlomin/render-template@v1.6 + with: + template: .github/workflows/templates/tos-not-accepted.md + vars: | + workflow_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + user: ${{ github.event.issue.user.login}} + + - name: Add Comment if tos not accepted + if: steps.are_tos_accepted.outputs.accepted == 'false' + uses: peter-evans/create-or-update-comment@v2 + with: + edit-mode: replace + issue-number: ${{ github.event.issue.number }} + body: ${{ steps.template_tos_not_accepted.outputs.result }} + + - name: Render template when tos are accepted + id: template_tos_accepted + if: steps.are_tos_accepted.outputs.accepted == 'true' + uses: chuhlomin/render-template@v1.6 + with: + template: .github/workflows/templates/tos-accepted.md + vars: | + workflow_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + user: ${{ github.event.issue.user.login}} + + - name: Add Comment if tos accepted + if: steps.are_tos_accepted.outputs.accepted == 'true' + uses: peter-evans/create-or-update-comment@v2 + with: + edit-mode: replace + issue-number: ${{ github.event.issue.number }} + body: ${{ steps.template_tos_accepted.outputs.result }} + + - name: Render template when tos are not found + id: template_tos_not_found + if: steps.are_tos_accepted.outputs.accepted == 'null' + uses: chuhlomin/render-template@v1.6 + with: + template: .github/workflows/templates/tos-not-found.md + vars: | + workflow_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + + - name: Add comment if tos not found + if: steps.are_tos_accepted.outputs.accepted == 'null' + uses: peter-evans/create-or-update-comment@v2 + with: + edit-mode: replace + issue-number: ${{ github.event.issue.number }} + body: ${{ steps.template_tos_not_found.outputs.result }} + + validate: + name: Extension validation + needs: check + if: needs.check.outputs.accepted == 'true' + uses: ./.github/workflows/validation.yaml diff --git a/.github/workflows/tos.yml b/.github/workflows/tos.yml new file mode 100644 index 0000000..3554fe5 --- /dev/null +++ b/.github/workflows/tos.yml @@ -0,0 +1,10 @@ +name: TOS Assistant +on: + issue_comment: + types: [created] + +jobs: + TOSAssistant: + runs-on: ubuntu-latest + steps: + - name: \ No newline at end of file diff --git a/.github/workflows/validation.yaml b/.github/workflows/validation.yaml new file mode 100644 index 0000000..e1423ea --- /dev/null +++ b/.github/workflows/validation.yaml @@ -0,0 +1,229 @@ +name: Extension validation + +on: + issues: + types: + - labeled + - unlabeled + workflow_call: + +env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + +jobs: + pre: + if: github.event.issue.closed == false + name: Prepare validation + runs-on: ubuntu-latest + outputs: + tos_accepted: ${{ steps.checks.outputs.tos_accepted }} + already_validated: ${{ steps.checks.outputs.already_validated }} + steps: + - id: checks + run: | + labels=$(gh issue view ${{ github.event.issue.number }} --json labels --jq '[.labels[].name]') + echo "tos_accepted=$(echo $labels | jq '. | index("tos/accepted") != null' )" >> $GITHUB_OUTPUT + echo "already_validated=$(echo $labels | jq '. | index("validation/succeeded") != null' )" >> $GITHUB_OUTPUT + + validate: + name: Validate extension + runs-on: macOS-latest + needs: pre + if: | + needs.pre.outputs.tos_accepted == 'true' + && needs.pre.outputs.already_validated == 'false' + steps: + - name: Find eventual initial comment + uses: peter-evans/find-comment@v2.1.0 + id: fc + continue-on-error: true + with: + issue-number: ${{ github.event.issue.number }} + comment-author: 'github-actions[bot]' + body-includes: ${{ github.workflow}} workflow has started + direction: last + + - name: Get Date + id: get-date + run: | + echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT + shell: bash + + - name: Redirect api.segment.io to localhost + id: redirect-segment + run: | + echo '127.0.0.2 api.segment.io' | sudo tee -a /etc/hosts + cat /etc/hosts + + - name: Get Docker app cache + id: cache-docker-desktop-app + uses: actions/cache@v3 + env: + cache-name: cache-docker-desktop-app + with: + path: /Applications/Docker.app + key: docker-desktop-app-mac-amd64-${{ steps.get-date.outputs.date }} + + - name: Get Docker install settings cache + id: cache-docker-desktop-install-settings + uses: actions/cache@v3 + env: + cache-name: cache-docker-desktop-install-settings + with: + path: ./cache/desktopInstallSettings/ + key: docker-desktop-install-settings-mac-${{ steps.get-date.outputs.date }} + + - name: Copy Desktop install settings in /Library + if: steps.cache-docker-desktop-install-settings.outputs.cache-hit == 'true' + run: | + echo "ls ./cache/desktopInstallSettings/" + ls ./cache/desktopInstallSettings/ + sudo mkdir -p "/Library/Application Support/com.docker.docker" + sudo cp ./cache/desktopInstallSettings/* "/Library/Application Support/com.docker.docker/" + echo "/Library/Application Support/com.docker.docker/" + ls "/Library/Application Support/com.docker.docker/" + + - name: Fetch and install Docker Desktop dmg + if: steps.cache-docker-desktop-install-settings.outputs.cache-hit != 'true' + run: | + sw_vers + mkdir ./temp + mkdir ./mount + wget -q -O ./temp/DockerDesktop.dmg https://desktop.docker.com/mac/main/amd64/Docker.dmg + /usr/bin/hdiutil attach -noverify ./temp/DockerDesktop.dmg -mountpoint ./mount/desktop -nobrowse + echo "dmg mounted" + sudo ./mount/desktop/Docker.app/Contents/MacOS/install --accept-license + echo "dmg installed" + echo "ls /Library/Application Support/com.docker.docker" + ls "/Library/Application Support/com.docker.docker" || true + mkdir -p ./cache/desktopInstallSettings + cp "/Library/Application Support/com.docker.docker/"* ./cache/desktopInstallSettings/ + echo "ls ./cache/desktopInstallSettings/" + ls ./cache/desktopInstallSettings/ || true + /usr/bin/hdiutil detach ./mount/desktop + echo "dmg unmounted" + + - name: Start Docker Desktop + timeout-minutes: 5 + run: | + sudo mkdir /Library/PrivilegedHelperTools + sudo /Applications/Docker.app/Contents/MacOS/install config --user runner + sudo /Applications/Docker.app/Contents/MacOS/install vmnetd + echo "app installed" + /usr/bin/open /Applications/Docker.app --args --unattended --add-host-docker-internal-registry + echo "Docker starting..." + + - name: Wait for Docker to be up and running + timeout-minutes: 10 + run: | + until docker ps; do echo "ps failed, sleep 10 s and try again"; sleep 10; done + echo "Docker started and ready" + + - name: Parse issue body + id: parse + uses: zentered/issue-forms-body-parser@v1.5.1 + + - name: Find extension repository + id: parse-repository + run: | + echo "repository=$(echo '${{ steps.parse.outputs.data }}' | jq -r '.["docker-hub-repository-name"].text' )" >> $GITHUB_OUTPUT + + - name: Validate extension + id: validate + continue-on-error: true + run: | + touch output.txt + docker extension validate -a -s -i ${{ steps.parse-repository.outputs.repository }} &> output.txt + + - name: Read validation output + run: | + delimiter=$(uuidgen) + + echo "VALIDATION_OUTPUT<<$delimiter" >> $GITHUB_ENV + cat output.txt >> $GITHUB_ENV + echo "$delimiter" >> $GITHUB_ENV + + - uses: actions/checkout@v3 + + - name: Add Comment if validation succeeded + if: steps.validate.outcome == 'success' + uses: peter-evans/create-or-update-comment@v2 + with: + edit-mode: replace + issue-number: ${{ github.event.issue.number }} + comment-id: ${{ steps.fc.outputs.comment-id }} + body: | + :white_check_mark: Validation ended successfully + + Yay! The extension [${{ steps.parse-repository.outputs.repository }}](https://open.docker.com/extensions/marketplace?extensionId=${{ steps.parse-repository.outputs.repository }}) is valid :tada:. + + Now, @docker/extensions will add the `publish/ready` label to the issue which will start the publishing of the extension on the marketplace. + Once published, this issue will be closed :smile:. + + In the meantime, you can answer a couple of questions to tell us how your experience building a Docker Desktop extension was :smiley:: https://forms.gle/88SLHsn2Xb1BgMQ49. + + +
+ Click to see the validation output + + > ${{ env.VALIDATION_OUTPUT }} +
+ + --- + See [action](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details. + + - name: Add 'validation/succeeded' label + if: steps.validate.outcome == 'success' + run: | + gh issue edit ${{ github.event.issue.number }} --remove-label "validation/failed" + gh issue edit ${{ github.event.issue.number }} --add-label "validation/succeeded" + + - name: Remove 'validation/succeeded' label + if: steps.validate.outcome != 'success' + run: | + gh issue edit ${{ github.event.issue.number }} --remove-label "validation/succeeded" + gh issue edit ${{ github.event.issue.number }} --add-label "validation/failed" + + - name: Add Comment if validation failed + if: steps.validate.outcome != 'success' + uses: peter-evans/create-or-update-comment@v2 + with: + edit-mode: replace + issue-number: ${{ github.event.issue.number }} + comment-id: ${{ steps.fc.outputs.comment-id }} + body: | + :x: Validation failed with the following errors + + > ${{ env.VALIDATION_OUTPUT }} + + Please fix the issues and comment with `/validate` to re-run the validation when you are ready. + + --- + See [action](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details. + + - name: Add Comment if job failed + if: failure() + uses: peter-evans/create-or-update-comment@v2 + with: + edit-mode: replace + issue-number: ${{ github.event.issue.number }} + comment-id: ${{ steps.fc.outputs.comment-id }} + body: | + :x: There was a problem during the validation job. + + Someone from the @docker/extensions will have to take a look at this issue. + We will let you know in this issue when it is fixed. + + --- + See [action](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details. + + + - name: Add 'docker/validation-errored' label if job failed + if: failure() + run: | + gh issue edit ${{ github.event.issue.number }} --add-label "docker/validation-errored" + + - name: Mark job as failed + if: steps.validate.outcome != 'success' + run: exit 1 \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..4522b0c --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# Docker Extensions Submissions + +## 👋 Welcome! + +You have created a Docker Extension and now want to make it available to every Docker Desktop users? Great! This is the right place to submit your extension. + +Maybe you are not ready yet but still are seeking feedback? Feel free to use the Show and tell category to share it with the community. + +If you haven't created an extension yet, you can find more information on how to do it [here](https://docs.docker.com/desktop/extensions-sdk/). + +## How to submit your extension + +To submit your extension you need to create a new issue in this repository. Once the issue submitted, the extension +will be automatically validated. If the validation is successful, someone from the @docker/extensions team will add +a label and, some time later, your extension will be published and available in the Marketplace to all Docker Desktop +users. + +Under the hood, the validation is done by a GitHub Action. Essentially, it runs the `docker extension validate` +command. To speed up the process and avoid failures, we recommend you to run this command locally before submitting your extension. + +## How my extension can be reviewed + +If you want your extension to be listed as reviewed in the Marketplace, you need to fill the form [here](https://www.docker.com/products/extensions/submissions/). +Note that the review process is significantly longer. + +## My extension is marked as published but not yet visible on the marketplace + +The Marketplace in Docker Desktop is updated when starting and every 12 hours. To force the update, you can restart Docker Desktop. + +## My extension is marked as `validation/succeeded` but not published yet? + +For the moment, a member of the @docker/extensions team needs to manually add the `publish/ready` label to your +issue in order to be published automatically. \ No newline at end of file