diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b15fff70..d2e9e4a2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -175,53 +175,6 @@ jobs: pytest tests/test_main_system_caches.py pytest -m 'vetiver' - test-jupyter: - runs-on: ubuntu-latest - env: - CONNECT_LICENSE: ${{ secrets.RSC_LICENSE }} - ADMIN_API_KEY: ${{ secrets.ADMIN_API_KEY }} - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: extractions/setup-just@v2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Build Containers - run: | - cd integration-testing - docker compose build client - docker compose build cypress - - name: Start Connect + rsconnect-jupyter - run: | - just integration-testing/up - - - name: Run Cypress Tests - run: | - just integration-testing/up-cypress - - # Videos are captured whether the suite fails or passes - - name: Save videos - uses: actions/upload-artifact@v4 - if: success() || failure() - with: - name: cypress-videos - path: integration-testing/cypress/videos - if-no-files-found: ignore - retention-days: 1 - - # Screenshots are only captured on failure - - name: Save screenshots - uses: actions/upload-artifact@v4 - if: failure() - with: - name: cypress-screenshots - path: integration-testing/cypress/screenshots - if-no-files-found: ignore - retention-days: 1 - test-connect: needs: distributions runs-on: ubuntu-latest diff --git a/README.md b/README.md index 8596cf20..19dcdcc5 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,7 @@ # The rsconnect-python CLI This package provides a CLI (command-line interface) for interacting -with and deploying to Posit Connect. This is also used by the -[`rsconnect-jupyter`](https://github.com/rstudio/rsconnect-jupyter) package to deploy -Jupyter notebooks via the Jupyter web console. Many types of content supported by Posit +with and deploying to Posit Connect. Many types of content supported by Posit Connect may be deployed by this package, including WSGI-style APIs, Dash, Streamlit, Gradio, and Bokeh applications. @@ -649,7 +647,7 @@ Generated from rsconnect-python {{ rsconnect_python.version }} ### Hide Jupyter Notebook Input Code Cells -The user can render a Jupyter notebook without its corresponding input code cells by passing the '--hide-all-input' flag through the cli: +You can render a Jupyter notebook without its corresponding input code cells by passing the '--hide-all-input' flag through the cli: ```bash rsconnect deploy notebook \ @@ -659,7 +657,8 @@ rsconnect deploy notebook \ my-notebook.ipynb ``` -To selectively hide input cells in a Jupyter notebook, the user needs to follow a two step process: +To selectively hide input cells in a Jupyter notebook, you need to do two things: + 1. tag cells with the 'hide_input' tag, 2. then pass the ' --hide-tagged-input' flag through the cli: @@ -671,7 +670,8 @@ rsconnect deploy notebook \ my-notebook.ipynb ``` -By default, rsconnect-python does not install Jupyter notebook related depenencies. These dependencies are installed via rsconnect-jupyter. When the user is using the hide input features in rsconnect-python by itself without rsconnect-jupyter, he/she needs to install the following package depenecies: +By default, rsconnect-python does not install Jupyter notebook-related depenencies. +To use these hide input features in rsconnect-python you need to install these extra dependencies: ``` notebook diff --git a/integration-testing/content/notebook/README.md b/integration-testing/content/notebook/README.md deleted file mode 100644 index ad2e4b8d..00000000 --- a/integration-testing/content/notebook/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Stock Report - -## About this example - -This stock report is generated using Python and Jupyter Notebook. Stock prices are populated from Quandl to generate a stock performance summary intended to run daily after market close. - - -## Learn more - -* [Jupyter Homepage](https://jupyter.org/) -* [Jupyter Documentation](https://jupyter.org/documentation) -* [Using Jupyter Notebooks in {systemDisplayName}](https://docs.posit.co/connect/user/jupyter-notebook/) -* [User Guide for rsconnect_jupyter](https://docs.posit.co/rsconnect-jupyter/) - -## Requirements - -* Python version 3.7 or higher - - diff --git a/integration-testing/content/notebook/quandl-wiki-tsla.json.gz b/integration-testing/content/notebook/quandl-wiki-tsla.json.gz deleted file mode 100644 index 168a29c7..00000000 Binary files a/integration-testing/content/notebook/quandl-wiki-tsla.json.gz and /dev/null differ diff --git a/integration-testing/content/notebook/requirements.txt b/integration-testing/content/notebook/requirements.txt deleted file mode 100644 index 8b5b507a..00000000 --- a/integration-testing/content/notebook/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -jupyter -matplotlib -pandas diff --git a/integration-testing/content/notebook/stock-report-jupyter.ipynb b/integration-testing/content/notebook/stock-report-jupyter.ipynb deleted file mode 100644 index 94977bc5..00000000 --- a/integration-testing/content/notebook/stock-report-jupyter.ipynb +++ /dev/null @@ -1,464 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Stock Report: TSLA" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Summary\n", - "\n", - "\n", - "

\n", - " NOTE: This example requires quandl-wiki-tsla.json.gz to be included as an Additional File when publishing to Posit Connect as a notebook with source code.\n", - "

" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
HighLowAvg Volume
Most Recent Trading Day304.27277.1813696168.0
52-Week389.61275.546407795.0
\n", - "
" - ], - "text/plain": [ - " High Low Avg Volume\n", - "Most Recent Trading Day 304.27 277.18 13696168.0\n", - "52-Week 389.61 275.54 6407795.0" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import datetime\n", - "import gzip\n", - "\n", - "import pandas as pd\n", - "import matplotlib.pyplot as plt\n", - "\n", - "%matplotlib inline\n", - "\n", - "prices = pd.read_json(gzip.open('quandl-wiki-tsla.json.gz'), orient='split')\n", - "\n", - "data=[\n", - " [\n", - " prices.last('1d')['High'].values[0],\n", - " prices.last('1d')['Low'].values[0],\n", - " prices.last('1d')['Volume'].values[0].round(),\n", - " ],\n", - " [\n", - " prices.asfreq('D').rolling(window=52*7, min_periods=1).max().last('1d')['High'].values[0],\n", - " prices.asfreq('D').rolling(window=52*7, min_periods=1).min().last('1d')['Low'].values[0],\n", - " prices.asfreq('D').rolling(window=52*7, min_periods=1).mean().last('1d')['Volume'].values[0].round(),\n", - " ]\n", - "]\n", - "\n", - "pd.DataFrame(data, columns=['High', 'Low', 'Avg Volume'], index=['Most Recent Trading Day', '52-Week'])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## History" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plt.rcParams['figure.figsize'] = [15, 10]\n", - "prices['Adj. Close'].plot(grid=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Raw Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
OpenHighLowCloseVolumeEx-DividendSplit RatioAdj. OpenAdj. HighAdj. LowAdj. CloseAdj. Volume
2010-06-2919.0025.000017.5423.89187663000119.0025.000017.5423.8918766300
2010-06-3025.7930.419223.3023.83171871000125.7930.419223.3023.8317187100
2010-07-0125.0025.920020.2721.9682188000125.0025.920020.2721.968218800
2010-07-0223.0023.100018.7119.2051398000123.0023.100018.7119.205139800
2010-07-0620.0020.000015.8316.1168669000120.0020.000015.8316.116866900
.......................................
2018-03-21310.25322.4400310.19316.53592788101310.25322.4400310.19316.535927881
2018-03-22313.89318.8200308.18309.10491430701313.89318.8200308.18309.104914307
2018-03-23311.25311.6100300.45301.54660053801311.25311.6100300.45301.546600538
2018-03-26307.34307.5900291.36304.18832463901307.34307.5900291.36304.188324639
2018-03-27304.00304.2700277.18279.181369616801304.00304.2700277.18279.1813696168
\n", - "

1949 rows × 12 columns

\n", - "
" - ], - "text/plain": [ - " Open High Low Close Volume Ex-Dividend \\\n", - "2010-06-29 19.00 25.0000 17.54 23.89 18766300 0 \n", - "2010-06-30 25.79 30.4192 23.30 23.83 17187100 0 \n", - "2010-07-01 25.00 25.9200 20.27 21.96 8218800 0 \n", - "2010-07-02 23.00 23.1000 18.71 19.20 5139800 0 \n", - "2010-07-06 20.00 20.0000 15.83 16.11 6866900 0 \n", - "... ... ... ... ... ... ... \n", - "2018-03-21 310.25 322.4400 310.19 316.53 5927881 0 \n", - "2018-03-22 313.89 318.8200 308.18 309.10 4914307 0 \n", - "2018-03-23 311.25 311.6100 300.45 301.54 6600538 0 \n", - "2018-03-26 307.34 307.5900 291.36 304.18 8324639 0 \n", - "2018-03-27 304.00 304.2700 277.18 279.18 13696168 0 \n", - "\n", - " Split Ratio Adj. Open Adj. High Adj. Low Adj. Close \\\n", - "2010-06-29 1 19.00 25.0000 17.54 23.89 \n", - "2010-06-30 1 25.79 30.4192 23.30 23.83 \n", - "2010-07-01 1 25.00 25.9200 20.27 21.96 \n", - "2010-07-02 1 23.00 23.1000 18.71 19.20 \n", - "2010-07-06 1 20.00 20.0000 15.83 16.11 \n", - "... ... ... ... ... ... \n", - "2018-03-21 1 310.25 322.4400 310.19 316.53 \n", - "2018-03-22 1 313.89 318.8200 308.18 309.10 \n", - "2018-03-23 1 311.25 311.6100 300.45 301.54 \n", - "2018-03-26 1 307.34 307.5900 291.36 304.18 \n", - "2018-03-27 1 304.00 304.2700 277.18 279.18 \n", - "\n", - " Adj. Volume \n", - "2010-06-29 18766300 \n", - "2010-06-30 17187100 \n", - "2010-07-01 8218800 \n", - "2010-07-02 5139800 \n", - "2010-07-06 6866900 \n", - "... ... \n", - "2018-03-21 5927881 \n", - "2018-03-22 4914307 \n", - "2018-03-23 6600538 \n", - "2018-03-26 8324639 \n", - "2018-03-27 13696168 \n", - "\n", - "[1949 rows x 12 columns]" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "prices" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "

\n", - " NOTE: This report uses Quandl's WIKI price dataset for US publicly traded companies. As of April 11, 2018 this data feed is no longer actively supported by Quandl.\n", - "

" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.16" - }, - "rsconnect": { - "previousServerId": "103c3a7d1bc73804ae13812f7e334afb", - "servers": { - "103c3a7d1bc73804ae13812f7e334afb": { - "appId": 1, - "appMode": "jupyter-static", - "configUrl": "http://connect:3939/connect/#/apps/2e7db7ef-7b25-4e36-b5d6-806a3138654c", - "disableTLSCheck": false, - "notebookTitle": "stock-report-jupyter", - "server": "http://connect:3939/", - "serverName": "localhost" - } - }, - "version": 1 - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/integration-testing/content/notebook/thumbnail.jpg b/integration-testing/content/notebook/thumbnail.jpg deleted file mode 100644 index 4a64568a..00000000 Binary files a/integration-testing/content/notebook/thumbnail.jpg and /dev/null differ diff --git a/integration-testing/content/voila/index.ipynb b/integration-testing/content/voila/index.ipynb deleted file mode 100644 index ebb5d680..00000000 --- a/integration-testing/content/voila/index.ipynb +++ /dev/null @@ -1,119 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this app we:\n", - "* Plot the gaussian density for a specific $\\mu$ and $\\sigma$\n", - "* Use the FloatSlider widget in ipywidgets to represent $\\mu$ and $\\sigma$ values\n", - "* Stack the density plot along with the sliders into a nice layout using HBox and VBox layout objects available in ipywidgets\n", - "* Link the sliders to the plot so that the plot gets updated when the values of $\\mu$ and $\\sigma$ change\n", - "\n", - "Find the code [here](https://github.com/pbugnion/voila-gallery/blob/master/gaussian-density/index.ipynb).\n", - "\n", - "This example is taken from [ChakriCherukuri/mlviz](https://github.com/ChakriCherukuri/mlviz)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "from scipy.stats import norm\n", - "\n", - "from ipywidgets import FloatSlider, HBox, VBox\n", - "import bqplot.pyplot as plt" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x = np.linspace(-10, 10, 200)\n", - "y = norm.pdf(x)\n", - "\n", - "# plot the gaussian density\n", - "title_tmpl = 'Gaussian Density (mu = {} and sigma = {})'\n", - "pdf_fig = plt.figure(title=title_tmpl.format(0, 1))\n", - "pdf_line = plt.plot(x, y, 'm', stroke_width=3)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# use two sliders to represent mu and sigma\n", - "mu_slider = FloatSlider(description='mu', value=0, min=-5, max=5, step=.1)\n", - "sigma_slider = FloatSlider(description='sigma', value=1, min=0.1, max=5, step=.1)\n", - "\n", - "slider_layout = HBox([mu_slider, sigma_slider])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def update_density(change):\n", - " new_mu = mu_slider.value\n", - " new_sigma = sigma_slider.value\n", - " # update the y attribute of the plot with the new pdf\n", - " # computed using new mu and sigma values\n", - " pdf_line.y = norm.pdf(x, new_mu, new_sigma)\n", - " \n", - " # also update the fig title\n", - " pdf_fig.title = title_tmpl.format(new_mu, new_sigma)\n", - "\n", - "# register the above callback with the 'value' trait of the sliders\n", - "mu_slider.observe(update_density, 'value')\n", - "sigma_slider.observe(update_density, 'value')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# now put all the widgets together into a simple dashboard\n", - "# the plot should update now when the slider values are updated!\n", - "final_layout = VBox([pdf_fig, slider_layout])\n", - "final_layout" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.16" - }, - "rsconnect": { - "previousServerId": null, - "servers": {}, - "version": 1 - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/integration-testing/content/voila/requirements.txt b/integration-testing/content/voila/requirements.txt deleted file mode 100644 index 2facda1c..00000000 --- a/integration-testing/content/voila/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ - -bqplot -scipy -voila diff --git a/integration-testing/cypress.config.js b/integration-testing/cypress.config.js deleted file mode 100644 index fa906be8..00000000 --- a/integration-testing/cypress.config.js +++ /dev/null @@ -1,22 +0,0 @@ -// { -// "testFiles": "**/*.spec.js", -// "defaultCommandTimeout": 10000, -// "responseTimeout": 60000, -// "integrationFolder": "./cypress/integration/", -// "viewportHeight": 800 -// } - -const { defineConfig } = require('cypress') - -module.exports = defineConfig({ - defaultCommandTimeout: 10000, - responseTimeout: 60000, - component: { - viewportHeight: 800 - }, - e2e: { - defaultCommandTimeout: 10000, - specPattern: "cypress/e2e/**/*.cy.js", - }, - "retries": 2 -}) diff --git a/integration-testing/cypress/e2e/jupyter.cy.js b/integration-testing/cypress/e2e/jupyter.cy.js deleted file mode 100644 index 7b7a2853..00000000 --- a/integration-testing/cypress/e2e/jupyter.cy.js +++ /dev/null @@ -1,54 +0,0 @@ -describe('Publishing Jupyter Notebook', () => { - - it('Publish button loads', () => { - cy.visit('http://client:9999/tree/integration-testing/content/notebook/stock-report-jupyter.ipynb'); - cy.get('button[data-jupyter-action="rsconnect_jupyter:publish"]').click(); - cy.get('a[id="publish-to-connect"]').should('be.visible') - }); - // wait is required after every action, cypress is too fast for jupyter - // https://github.com/cypress-io/cypress/issues/249 - // it('Add Server', () => { - - it('Add Server', () => { - cy.visit('http://client:9999/tree/integration-testing/content/notebook/stock-report-jupyter.ipynb'); - cy.addServer(); - }); - - // }); - it('Publish Jupyter Notebook', () => { - cy.visit('http://client:9999/tree/integration-testing/content/notebook/stock-report-jupyter.ipynb'); - cy.wait(1000); - cy.get('button[data-jupyter-action="rsconnect_jupyter:publish"]').click(); - cy.get('a[id="publish-to-connect"]').click(); - cy.wait(1000); - cy.get('button[id="rsc-add-files"]').click(); - cy.wait(1000); - cy.get('input[name="quandl-wiki-tsla.json.gz"]').click(); - cy.wait(1000); - cy.get('button[id="add-files-dialog-accept"]').click(); - cy.wait(1000); - cy.get('li[class="list-group-item"]').first().should('have.text'," quandl-wiki-tsla.json.gz"); - cy.wait(1000); - cy.get('a[class="btn btn-primary"]').last().should('have.text',"Publish").click({ force: true }); - cy.wait(1000); - cy.get('input[name="location"]').first().click(); - cy.wait(1000); - cy.get('a[class="btn btn-primary"]').last().should('have.text',"Next").click(); - cy.wait(1000); - cy.get('a[class="btn btn-primary"]').last().should('have.text',"Publish").click(); - cy.wait(1000); - // allow for 5 minutes to deploy content - cy.get('span[class="fa fa-link"]', { timeout: 300000 }).last().should('have.text'," Successfully published content").click(); - }); - it('Vist Content in Connect', () => { - cy.connectLogin(); - cy.visit('http://connect:3939'); - cy.get('div[class="content-table__display-name"]').first().contains('stock-report-jupyter').click(); - cy.contentiFrame().contains('Stock Report: TSLA'); - }); - - it('Remove Server', () => { - cy.visit('http://client:9999/tree/integration-testing/content/notebook/stock-report-jupyter.ipynb'); - cy.removeServer(); - }); -}); diff --git a/integration-testing/cypress/e2e/voila.cy.js b/integration-testing/cypress/e2e/voila.cy.js deleted file mode 100644 index e6082acb..00000000 --- a/integration-testing/cypress/e2e/voila.cy.js +++ /dev/null @@ -1,44 +0,0 @@ -describe('Publishing Voila Notebook', () => { - - it('Publish button loads', () => { - cy.visit('http://client:9999/tree/integration-testing/content/voila/index.ipynb'); - cy.get('button[data-jupyter-action="rsconnect_jupyter:publish"]').click(); - cy.get('a[id="publish-to-connect"]').should('be.visible') - }); - - it('Add Server Voila', () => { - cy.visit('http://client:9999/tree/integration-testing/content/voila/index.ipynb'); - cy.addServer(); - }); - - it('Publish Content', () => { - cy.visit('http://client:9999/tree/integration-testing/content/voila/index.ipynb'); - cy.wait(1000); - cy.get('button[data-jupyter-action="rsconnect_jupyter:publish"]').click(); - cy.get('a[id="publish-to-connect"]').click({ force: true }); - cy.wait(1000); - cy.get('a[id="rsc-publish-voila"]').click(); - cy.get('a[class="btn btn-primary"]').last().should('have.text',"Publish").click({ force: true }); - cy.wait(1000); - cy.get('input[name="location"]').first().click(); - cy.wait(1000); - cy.get('a[class="btn btn-primary"]').last().should('have.text',"Next").click(); - cy.wait(1000); - cy.get('a[class="btn btn-primary"]').last().should('have.text',"Publish").click(); - cy.wait(1000); - // allow for 5 minutes to deploy content - cy.get('span[class="fa fa-link"]', { timeout: 300000 }).last().should('have.text'," Successfully published content").click(); - }); - it('Vist Content in Connect', () => { - cy.connectLogin(); - cy.visit('http://connect:3939'); - cy.get('div[class="content-table__display-name"]').first().contains('index').click(); - cy.contentiFrame().contains('Plot the gaussian density'); - }); - - it('Remove Server', () => { - cy.visit('http://client:9999/tree/integration-testing/content/voila/index.ipynb'); - cy.removeServer(); - }); - -}); \ No newline at end of file diff --git a/integration-testing/cypress/plugins/index.js b/integration-testing/cypress/plugins/index.js deleted file mode 100644 index fd170fba..00000000 --- a/integration-testing/cypress/plugins/index.js +++ /dev/null @@ -1,17 +0,0 @@ -// *********************************************************** -// This example plugins/index.js can be used to load plugins -// -// You can change the location of this file or turn off loading -// the plugins file with the 'pluginsFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/plugins-guide -// *********************************************************** - -// This function is called when a project is opened or re-opened (e.g. due to -// the project's config changing) - -module.exports = (on, config) => { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config -} diff --git a/integration-testing/cypress/support/commands.js b/integration-testing/cypress/support/commands.js deleted file mode 100644 index 54575265..00000000 --- a/integration-testing/cypress/support/commands.js +++ /dev/null @@ -1,79 +0,0 @@ -// *********************************************** -// This example commands.js shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -// -// -// -- This is a parent command -- -// Cypress.Commands.add('login', (email, password) => { ... }) -// -// -// -- This is a child command -- -// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) - -// https://www.cypress.io/blog/2020/02/12/working-with-iframes-in-cypress/ -Cypress.Commands.add('contentiFrame', (iframe) => { - // get the iframe > document > body - // and retry until the body element is not empty - cy.log('contentiFrame'); - - return cy - .get('iframe.appFrame', { log: false }) - .its('0.contentDocument.body') - .should('not.be.empty') - // wraps "body" DOM element to allow - // chaining more Cypress commands, like ".find(...)" - // https://on.cypress.io/wrap - .then((body) => cy.wrap(body, { log: false })); -}); - -Cypress.Commands.add('connectLogin', (user) => { - cy.request('POST', 'http://connect:3939/__login__', { - username: 'admin', - password: 'password', - }); -}); - -Cypress.Commands.add('addServer', () => { - cy.get('button[data-jupyter-action="rsconnect_jupyter:publish"]') - .click(); - cy.get('a[id="publish-to-connect"]').click({ force: true }); - cy.wait(1000); - cy.get('input[id="rsc-server"]').clear().type('http://connect:3939'); - cy.get('input[id="rsc-api-key"]').clear().type(Cypress.env('api_key')); - cy.get('input[id="rsc-servername"]').clear().type('http://connect:3939'); - cy.get('a[class="btn btn-primary"]').contains(' Add Server') - .click(); - cy.wait(1000); - cy.get('span[class="help-block"]').should('not.have.text',"Unable to verify"); -}); - -Cypress.Commands.add('removeServer', () => { - cy.get('button[data-jupyter-action="rsconnect_jupyter:publish"]') - .click(); - cy.get('a[id="publish-to-connect"]').click({ force: true }); - cy.wait(1000); - cy.get('div[id="rsc-select-server"]') - .contains('http://connect:3939') - .get('button[class="pull-right btn btn-danger btn-xs"]') - .click(); -}); - -// Cypress.Commands.add('setSessionStorage', (key, value) => { -// cy.window().then((window) => { -// window.sessionStorage.setItem(key, value) -// }) -// }) \ No newline at end of file diff --git a/integration-testing/cypress/support/e2e.js b/integration-testing/cypress/support/e2e.js deleted file mode 100644 index d68db96d..00000000 --- a/integration-testing/cypress/support/e2e.js +++ /dev/null @@ -1,20 +0,0 @@ -// *********************************************************** -// This example support/index.js is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.js using ES2015 syntax: -import './commands' - -// Alternatively you can use CommonJS syntax: -// require('./commands') diff --git a/integration-testing/docker-compose.yml b/integration-testing/docker-compose.yml index 2ca1db0a..6cf6c5ac 100644 --- a/integration-testing/docker-compose.yml +++ b/integration-testing/docker-compose.yml @@ -1,33 +1,15 @@ version: '3' services: - client: - image: client - hostname: client - healthcheck: - test: ["CMD", "curl", "-f", "http://client:9999/tree"] - interval: 40s - timeout: 3s - retries: 30 - ports: - - 9999:9999 - build: - context: ./docker - dockerfile: client.Dockerfile - volumes: - - ../:/rsconnect-python - working_dir: /rsconnect-python/integration-testing - entrypoint: '' - client-cli: - build: + build: context: ./docker dockerfile: cli.Dockerfile - args: + args: QUARTO_VERSION: ${QUARTO_VERSION} PY_VERSION: ${PY_VERSION} volumes: - - ../:/rsconnect-python + - ../:/rsconnect-python working_dir: /rsconnect-python/integration-testing network_mode: host entrypoint: '' @@ -42,10 +24,10 @@ services: connect-cli: hostname: connect-cli image: rstudio/rstudio-connect:jammy - build: + build: context: ./docker dockerfile: connect.Dockerfile - args: + args: QUARTO_VERSION: ${QUARTO_VERSION} PY_VERSION: ${PY_VERSION} restart: always @@ -60,7 +42,7 @@ services: QUARTO_VERSION: ${QUARTO_VERSION} PY_VERSION: ${PY_VERSION} - # connect from public docker hub + # connect from public docker hub # used jupyter-notebook and deploy tests in CI, main.yml connect: hostname: connect @@ -74,19 +56,3 @@ services: environment: RSTUDIO_CONNECT_HASTE: "enabled" RSC_LICENSE: ${CONNECT_LICENSE} - - - cypress: - image: cypress/included:12.7.0 - depends_on: - client: - condition: service_healthy - build: - context: ./docker - dockerfile: cypress.Dockerfile - volumes: - - ../:/rsconnect-python - working_dir: /rsconnect-python/integration-testing/ - environment: - ADMIN_API_KEY: ${ADMIN_API_KEY} - entrypoint: '' diff --git a/integration-testing/docker/cli.Dockerfile b/integration-testing/docker/cli.Dockerfile index 7913e6b0..e5040141 100644 --- a/integration-testing/docker/cli.Dockerfile +++ b/integration-testing/docker/cli.Dockerfile @@ -1,6 +1,5 @@ ARG PY_VERSION=${PY_VERSION} FROM python:${PY_VERSION} -COPY ./requirements.txt . EXPOSE 9999 VOLUME ../../:/rsconnect-python/ @@ -35,11 +34,7 @@ RUN curl -fsSL -o miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-py && ./miniconda.sh -b -p /opt/miniconda \ && rm -rf miniconda.sh -RUN pip install rsconnect-jupyter --pre && \ - pip install pipenv && \ - jupyter-nbextension install --sys-prefix --py rsconnect_jupyter - RUN curl -fsSLO https://github.com/quarto-dev/quarto-cli/releases/download/v${QUARTO_VERSION}/quarto-${QUARTO_VERSION}-linux-amd64.tar.gz && \ mkdir /opt/quarto && tar xf quarto-${QUARTO_VERSION}-linux-amd64.tar.gz -C /opt/quarto --strip-components 1 && \ ( echo ""; echo 'export PATH=$PATH:/opt/quarto/bin' ; echo "" ) >> ~/.profile && \ - . ~/.profile \ No newline at end of file + . ~/.profile diff --git a/integration-testing/docker/client.Dockerfile b/integration-testing/docker/client.Dockerfile deleted file mode 100644 index 71a81125..00000000 --- a/integration-testing/docker/client.Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -FROM python:3.12 -COPY ./requirements.txt . -EXPOSE 9999 -VOLUME ../../:/rsconnect-python/ - -WORKDIR /rsconnect-python/integration-testing - -RUN apt-get update && \ - apt-get -y install sudo - -RUN mkdir -p /libs-client && \ - curl -fsSL https://github.com/casey/just/releases/download/1.1.2/just-1.1.2-x86_64-unknown-linux-musl.tar.gz \ - | tar -C /libs-client -xz just - -ENV PATH=$PATH:/libs-client - -RUN pip install rsconnect-jupyter --pre && \ - pip install pipenv && \ - jupyter-nbextension install --sys-prefix --py rsconnect_jupyter - -CMD cd ../ && \ - rm -rf ~/.jupyter/ && \ - pip install . && \ - jupyter-nbextension enable --sys-prefix --py rsconnect_jupyter && \ - jupyter-serverextension enable --sys-prefix --py rsconnect_jupyter && \ - jupyter-notebook \ - -y --ip='0.0.0.0' --port=9999 --no-browser --NotebookApp.token='' --allow-root diff --git a/integration-testing/docker/cypress.Dockerfile b/integration-testing/docker/cypress.Dockerfile deleted file mode 100644 index 24495820..00000000 --- a/integration-testing/docker/cypress.Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM cypress/included:13.6.4 - -RUN apt-get update -y && apt-get install -y --no-install-recommends \ - jq \ - curl - -RUN mkdir -p /libs-cypress && \ - curl -fsSL https://github.com/casey/just/releases/download/1.1.2/just-1.1.2-x86_64-unknown-linux-musl.tar.gz \ - | tar -C /libs-cypress -xz just - -ENV ADMIN_API_KEY=${ADMIN_API_KEY} -ENV PATH=$PATH:/libs-cypress -CMD cypress run --browser chrome --env api_key=${ADMIN_API_KEY} -# CMD run cypress:open --env api_key=${ADMIN_API_KEY} diff --git a/integration-testing/docker/requirements.txt b/integration-testing/docker/requirements.txt deleted file mode 100644 index d54fbe44..00000000 --- a/integration-testing/docker/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -rsconnect-jupyter diff --git a/integration-testing/justfile b/integration-testing/justfile deleted file mode 100644 index 5e654997..00000000 --- a/integration-testing/justfile +++ /dev/null @@ -1,77 +0,0 @@ -export RSC_LICENSE := env_var_or_default("RSC_LICENSE", "$CONNECT_LICENSE") -export ADMIN_API_KEY := env_var_or_default('ADMIN_API_KEY', "${ADMIN_API_KEY}") -export QUARTO_VERSION := env_var_or_default('QUARTO_VERSION', '1.4.546') - - -all: - just up && just up-cypress - -build: - ADMIN_API_KEY=${ADMIN_API_KEY} \ - docker compose build - -up: - docker compose pull connect && \ - docker compose up -d client && docker compose up -d connect - -up-cypress: - docker compose up cypress --exit-code-from cypress - -# use this target if you want to run Cypress -# without shutting down all containers after each run -up-cypress-local: - docker compose up cypress - -run-client: - docker compose exec -it \ - client \ - just setup-client - -setup-client: - #!/bin/bash - python -m venv ./client-python/ && \ - . ./client-python/bin/activate && \ - cd ../ && \ - pip install . && \ - jupyter-nbextension enable --sys-prefix --py rsconnect_jupyter && \ - jupyter-serverextension enable --sys-prefix --py rsconnect_jupyter && \ - jupyter-notebook \ - -y --ip='0.0.0.0' --port=9999 --no-browser --NotebookApp.token='' --allow-root - -run-connect: - docker compose exec -it \ - connect - -run-cypress: - docker compose exec --rm \ - cypress \ - cypress run --browser chrome - -bash-cypress: - docker compose run --rm cypress \ - /bin/bash - -bash-client: - docker compose run --rm client \ - /bin/bash - -bash-connect: - docker compose run --rm connect \ - /bin/bash - -inspect-client: - docker compose exec -it client /bin/bash - -inspect-cypress: - docker compose exec -it cypress /bin/bash - -inspect-connect: - docker compose exec -it connect /bin/bash - -stop: - docker compose down --volumes --remove-orphans && \ - rm -rf ../dist/rsconnect_python-*.whl - -rm-config: - docker compose exec -it client \ - rm -rf /root/.jupyter