mirror of
https://github.com/astral-sh/ruff
synced 2026-01-21 21:40:51 -05:00
## Summary Add a release's version number to the names of archives containing binaries that are attached to that GitHub release. This makes it possible for users to easily tell archives from different downloaded releases apart. See also: #8961 ## Test Plan The workflow was tested in my fork. The example release can be found at: [https://github.com/tobbez/ruff/releases/tag/v0.1.7](https://github.com/tobbez/ruff/releases/tag/v0.1.7). To allow the workflow run to succeed in the fork while testing, I had to use a small commit to prevent interaction with external services (ghcr, PyPI, and the ruff-pre-commit repository): ```diff diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 86eac6ebc..56b9fa908 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -463,10 +463,12 @@ jobs: id-token: write steps: - uses: actions/download-artifact@v3 + if: false with: name: wheels path: wheels - name: Publish to PyPi + if: false uses: pypa/gh-action-pypi-publish@release/v1 with: skip-existing: true @@ -517,6 +519,7 @@ jobs: tag_name: v${{ inputs.tag }} docker-publish: + if: false # This action doesn't need to wait on any other task, it's easy to re-tag if something failed and we're validating # the tag here also name: Push Docker image ghcr.io/astral-sh/ruff @@ -575,6 +578,7 @@ jobs: # After the release has been published, we update downstream repositories # This is separate because if this fails the release is still fine, we just need to do some manual workflow triggers update-dependents: + if: false name: Update dependents runs-on: ubuntu-latest needs: publish-release ``` Those workflow jobs are however not modified by this PR, so they should not be affected.
593 lines
18 KiB
YAML
593 lines
18 KiB
YAML
name: "[ruff] Release"
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag:
|
|
description: "The version to tag, without the leading 'v'. If omitted, will initiate a dry run (no uploads)."
|
|
type: string
|
|
sha:
|
|
description: "The full sha of the commit to be released. If omitted, the latest commit on the default branch will be used."
|
|
default: ""
|
|
type: string
|
|
pull_request:
|
|
paths:
|
|
# When we change pyproject.toml, we want to ensure that the maturin builds still work
|
|
- pyproject.toml
|
|
# And when we change this workflow itself...
|
|
- .github/workflows/release.yaml
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
env:
|
|
PACKAGE_NAME: ruff
|
|
PYTHON_VERSION: "3.11"
|
|
CARGO_INCREMENTAL: 0
|
|
CARGO_NET_RETRY: 10
|
|
CARGO_TERM_COLOR: always
|
|
RUSTUP_MAX_RETRIES: 10
|
|
|
|
jobs:
|
|
sdist:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.sha }}
|
|
- uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
- name: "Prep README.md"
|
|
run: python scripts/transform_readme.py --target pypi
|
|
- name: "Build sdist"
|
|
uses: PyO3/maturin-action@v1
|
|
with:
|
|
command: sdist
|
|
args: --out dist
|
|
- name: "Test sdist"
|
|
run: |
|
|
pip install dist/${{ env.PACKAGE_NAME }}-*.tar.gz --force-reinstall
|
|
ruff --help
|
|
python -m ruff --help
|
|
- name: "Upload sdist"
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: wheels
|
|
path: dist
|
|
|
|
macos-x86_64:
|
|
runs-on: macos-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.sha }}
|
|
- uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
architecture: x64
|
|
- name: "Prep README.md"
|
|
run: python scripts/transform_readme.py --target pypi
|
|
- name: "Build wheels - x86_64"
|
|
uses: PyO3/maturin-action@v1
|
|
with:
|
|
target: x86_64
|
|
args: --release --out dist
|
|
- name: "Test wheel - x86_64"
|
|
run: |
|
|
pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
|
|
ruff --help
|
|
python -m ruff --help
|
|
- name: "Upload wheels"
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: wheels
|
|
path: dist
|
|
- name: "Archive binary"
|
|
run: |
|
|
ARCHIVE_FILE=ruff-${{ inputs.tag }}-x86_64-apple-darwin.tar.gz
|
|
tar czvf $ARCHIVE_FILE -C target/x86_64-apple-darwin/release ruff
|
|
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
|
- name: "Upload binary"
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: binaries
|
|
path: |
|
|
*.tar.gz
|
|
*.sha256
|
|
|
|
macos-universal:
|
|
runs-on: macos-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.sha }}
|
|
- uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
architecture: x64
|
|
- name: "Prep README.md"
|
|
run: python scripts/transform_readme.py --target pypi
|
|
- name: "Build wheels - universal2"
|
|
uses: PyO3/maturin-action@v1
|
|
with:
|
|
args: --release --target universal2-apple-darwin --out dist
|
|
- name: "Test wheel - universal2"
|
|
run: |
|
|
pip install dist/${{ env.PACKAGE_NAME }}-*universal2.whl --force-reinstall
|
|
ruff --help
|
|
python -m ruff --help
|
|
- name: "Upload wheels"
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: wheels
|
|
path: dist
|
|
- name: "Archive binary"
|
|
run: |
|
|
ARCHIVE_FILE=ruff-${{ inputs.tag }}-aarch64-apple-darwin.tar.gz
|
|
tar czvf $ARCHIVE_FILE -C target/aarch64-apple-darwin/release ruff
|
|
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
|
- name: "Upload binary"
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: binaries
|
|
path: |
|
|
*.tar.gz
|
|
*.sha256
|
|
|
|
windows:
|
|
runs-on: windows-latest
|
|
strategy:
|
|
matrix:
|
|
platform:
|
|
- target: x86_64-pc-windows-msvc
|
|
arch: x64
|
|
- target: i686-pc-windows-msvc
|
|
arch: x86
|
|
- target: aarch64-pc-windows-msvc
|
|
arch: x64
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.sha }}
|
|
- uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
architecture: ${{ matrix.platform.arch }}
|
|
- name: "Prep README.md"
|
|
run: python scripts/transform_readme.py --target pypi
|
|
- name: "Build wheels"
|
|
uses: PyO3/maturin-action@v1
|
|
with:
|
|
target: ${{ matrix.platform.target }}
|
|
args: --release --out dist
|
|
- name: "Test wheel"
|
|
if: ${{ !startsWith(matrix.platform.target, 'aarch64') }}
|
|
shell: bash
|
|
run: |
|
|
python -m pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
|
|
ruff --help
|
|
python -m ruff --help
|
|
- name: "Upload wheels"
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: wheels
|
|
path: dist
|
|
- name: "Archive binary"
|
|
shell: bash
|
|
run: |
|
|
ARCHIVE_FILE=ruff-${{ inputs.tag }}-${{ matrix.platform.target }}.zip
|
|
7z a $ARCHIVE_FILE ./target/${{ matrix.platform.target }}/release/ruff.exe
|
|
sha256sum $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
|
- name: "Upload binary"
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: binaries
|
|
path: |
|
|
*.zip
|
|
*.sha256
|
|
|
|
linux:
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
matrix:
|
|
target:
|
|
- x86_64-unknown-linux-gnu
|
|
- i686-unknown-linux-gnu
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.sha }}
|
|
- uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
architecture: x64
|
|
- name: "Prep README.md"
|
|
run: python scripts/transform_readme.py --target pypi
|
|
- name: "Build wheels"
|
|
uses: PyO3/maturin-action@v1
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
manylinux: auto
|
|
args: --release --out dist
|
|
- name: "Test wheel"
|
|
if: ${{ startsWith(matrix.target, 'x86_64') }}
|
|
run: |
|
|
pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
|
|
ruff --help
|
|
python -m ruff --help
|
|
- name: "Upload wheels"
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: wheels
|
|
path: dist
|
|
- name: "Archive binary"
|
|
run: |
|
|
ARCHIVE_FILE=ruff-${{ inputs.tag }}-${{ matrix.target }}.tar.gz
|
|
tar czvf $ARCHIVE_FILE -C target/${{ matrix.target }}/release ruff
|
|
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
|
- name: "Upload binary"
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: binaries
|
|
path: |
|
|
*.tar.gz
|
|
*.sha256
|
|
|
|
linux-cross:
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
matrix:
|
|
platform:
|
|
- target: aarch64-unknown-linux-gnu
|
|
arch: aarch64
|
|
# see https://github.com/astral-sh/ruff/issues/3791
|
|
# and https://github.com/gnzlbg/jemallocator/issues/170#issuecomment-1503228963
|
|
maturin_docker_options: -e JEMALLOC_SYS_WITH_LG_PAGE=16
|
|
- target: armv7-unknown-linux-gnueabihf
|
|
arch: armv7
|
|
- target: s390x-unknown-linux-gnu
|
|
arch: s390x
|
|
- target: powerpc64le-unknown-linux-gnu
|
|
arch: ppc64le
|
|
- target: powerpc64-unknown-linux-gnu
|
|
arch: ppc64
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.sha }}
|
|
- uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
- name: "Prep README.md"
|
|
run: python scripts/transform_readme.py --target pypi
|
|
- name: "Build wheels"
|
|
uses: PyO3/maturin-action@v1
|
|
with:
|
|
target: ${{ matrix.platform.target }}
|
|
manylinux: auto
|
|
docker-options: ${{ matrix.platform.maturin_docker_options }}
|
|
args: --release --out dist
|
|
- uses: uraimo/run-on-arch-action@v2
|
|
if: matrix.platform.arch != 'ppc64'
|
|
name: Test wheel
|
|
with:
|
|
arch: ${{ matrix.platform.arch }}
|
|
distro: ubuntu20.04
|
|
githubToken: ${{ github.token }}
|
|
install: |
|
|
apt-get update
|
|
apt-get install -y --no-install-recommends python3 python3-pip
|
|
pip3 install -U pip
|
|
run: |
|
|
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
|
|
ruff --help
|
|
- name: "Upload wheels"
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: wheels
|
|
path: dist
|
|
- name: "Archive binary"
|
|
run: |
|
|
ARCHIVE_FILE=ruff-${{ inputs.tag }}-${{ matrix.platform.target }}.tar.gz
|
|
tar czvf $ARCHIVE_FILE -C target/${{ matrix.platform.target }}/release ruff
|
|
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
|
- name: "Upload binary"
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: binaries
|
|
path: |
|
|
*.tar.gz
|
|
*.sha256
|
|
|
|
musllinux:
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
matrix:
|
|
target:
|
|
- x86_64-unknown-linux-musl
|
|
- i686-unknown-linux-musl
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.sha }}
|
|
- uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
architecture: x64
|
|
- name: "Prep README.md"
|
|
run: python scripts/transform_readme.py --target pypi
|
|
- name: "Build wheels"
|
|
uses: PyO3/maturin-action@v1
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
manylinux: musllinux_1_2
|
|
args: --release --out dist
|
|
- name: "Test wheel"
|
|
if: matrix.target == 'x86_64-unknown-linux-musl'
|
|
uses: addnab/docker-run-action@v3
|
|
with:
|
|
image: alpine:latest
|
|
options: -v ${{ github.workspace }}:/io -w /io
|
|
run: |
|
|
apk add py3-pip
|
|
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links /io/dist/ --force-reinstall
|
|
ruff --help
|
|
python -m ruff --help
|
|
- name: "Upload wheels"
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: wheels
|
|
path: dist
|
|
- name: "Archive binary"
|
|
run: |
|
|
ARCHIVE_FILE=ruff-${{ inputs.tag }}-${{ matrix.target }}.tar.gz
|
|
tar czvf $ARCHIVE_FILE -C target/${{ matrix.target }}/release ruff
|
|
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
|
- name: "Upload binary"
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: binaries
|
|
path: |
|
|
*.tar.gz
|
|
*.sha256
|
|
|
|
musllinux-cross:
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
matrix:
|
|
platform:
|
|
- target: aarch64-unknown-linux-musl
|
|
arch: aarch64
|
|
maturin_docker_options: -e JEMALLOC_SYS_WITH_LG_PAGE=16
|
|
- target: armv7-unknown-linux-musleabihf
|
|
arch: armv7
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.sha }}
|
|
- uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
- name: "Prep README.md"
|
|
run: python scripts/transform_readme.py --target pypi
|
|
- name: "Build wheels"
|
|
uses: PyO3/maturin-action@v1
|
|
with:
|
|
target: ${{ matrix.platform.target }}
|
|
manylinux: musllinux_1_2
|
|
args: --release --out dist
|
|
docker-options: ${{ matrix.platform.maturin_docker_options }}
|
|
- uses: uraimo/run-on-arch-action@v2
|
|
name: Test wheel
|
|
with:
|
|
arch: ${{ matrix.platform.arch }}
|
|
distro: alpine_latest
|
|
githubToken: ${{ github.token }}
|
|
install: |
|
|
apk add py3-pip
|
|
run: |
|
|
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
|
|
ruff check --help
|
|
- name: "Upload wheels"
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: wheels
|
|
path: dist
|
|
- name: "Archive binary"
|
|
run: |
|
|
ARCHIVE_FILE=ruff-${{ inputs.tag }}-${{ matrix.platform.target }}.tar.gz
|
|
tar czvf $ARCHIVE_FILE -C target/${{ matrix.platform.target }}/release ruff
|
|
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
|
- name: "Upload binary"
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: binaries
|
|
path: |
|
|
*.tar.gz
|
|
*.sha256
|
|
|
|
validate-tag:
|
|
name: Validate tag
|
|
runs-on: ubuntu-latest
|
|
# If you don't set an input tag, it's a dry run (no uploads).
|
|
if: ${{ inputs.tag }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
ref: main # We checkout the main branch to check for the commit
|
|
- name: Check main branch
|
|
if: ${{ inputs.sha }}
|
|
run: |
|
|
# Fetch the main branch since a shallow checkout is used by default
|
|
git fetch origin main --unshallow
|
|
if ! git branch --contains ${{ inputs.sha }} | grep -E '(^|\s)main$'; then
|
|
echo "The specified sha is not on the main branch" >&2
|
|
exit 1
|
|
fi
|
|
- name: Check tag consistency
|
|
run: |
|
|
# Switch to the commit we want to release
|
|
git checkout ${{ inputs.sha }}
|
|
version=$(grep "version = " pyproject.toml | sed -e 's/version = "\(.*\)"/\1/g')
|
|
if [ "${{ inputs.tag }}" != "${version}" ]; then
|
|
echo "The input tag does not match the version from pyproject.toml:" >&2
|
|
echo "${{ inputs.tag }}" >&2
|
|
echo "${version}" >&2
|
|
exit 1
|
|
else
|
|
echo "Releasing ${version}"
|
|
fi
|
|
|
|
upload-release:
|
|
name: Upload to PyPI
|
|
runs-on: ubuntu-latest
|
|
needs:
|
|
- macos-universal
|
|
- macos-x86_64
|
|
- windows
|
|
- linux
|
|
- linux-cross
|
|
- musllinux
|
|
- musllinux-cross
|
|
- validate-tag
|
|
# If you don't set an input tag, it's a dry run (no uploads).
|
|
if: ${{ inputs.tag }}
|
|
environment:
|
|
name: release
|
|
permissions:
|
|
# For pypi trusted publishing
|
|
id-token: write
|
|
steps:
|
|
- uses: actions/download-artifact@v3
|
|
with:
|
|
name: wheels
|
|
path: wheels
|
|
- name: Publish to PyPi
|
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
with:
|
|
skip-existing: true
|
|
packages-dir: wheels
|
|
verbose: true
|
|
|
|
tag-release:
|
|
name: Tag release
|
|
runs-on: ubuntu-latest
|
|
needs: upload-release
|
|
# If you don't set an input tag, it's a dry run (no uploads).
|
|
if: ${{ inputs.tag }}
|
|
permissions:
|
|
# For git tag
|
|
contents: write
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.sha }}
|
|
- name: git tag
|
|
run: |
|
|
git config user.email "hey@astral.sh"
|
|
git config user.name "Ruff Release CI"
|
|
git tag -m "v${{ inputs.tag }}" "v${{ inputs.tag }}"
|
|
# If there is duplicate tag, this will fail. The publish to pypi action will have been a noop (due to skip
|
|
# existing), so we make a non-destructive exit here
|
|
git push --tags
|
|
|
|
publish-release:
|
|
name: Publish to GitHub
|
|
runs-on: ubuntu-latest
|
|
needs: tag-release
|
|
# If you don't set an input tag, it's a dry run (no uploads).
|
|
if: ${{ inputs.tag }}
|
|
permissions:
|
|
# For GitHub release publishing
|
|
contents: write
|
|
steps:
|
|
- uses: actions/download-artifact@v3
|
|
with:
|
|
name: binaries
|
|
path: binaries
|
|
- name: "Publish to GitHub"
|
|
uses: softprops/action-gh-release@v1
|
|
with:
|
|
draft: true
|
|
files: binaries/*
|
|
tag_name: v${{ inputs.tag }}
|
|
|
|
docker-publish:
|
|
# This action doesn't need to wait on any other task, it's easy to re-tag if something failed and we're validating
|
|
# the tag here also
|
|
name: Push Docker image ghcr.io/astral-sh/ruff
|
|
runs-on: ubuntu-latest
|
|
environment:
|
|
name: release
|
|
permissions:
|
|
# For the docker push
|
|
packages: write
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.sha }}
|
|
|
|
- uses: docker/setup-buildx-action@v3
|
|
|
|
- uses: docker/login-action@v3
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.repository_owner }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Extract metadata (tags, labels) for Docker
|
|
id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ghcr.io/astral-sh/ruff
|
|
|
|
- name: Check tag consistency
|
|
# Unlike validate-tag we don't check if the commit is on the main branch, but it seems good enough since we can
|
|
# change docker tags
|
|
if: ${{ inputs.tag }}
|
|
run: |
|
|
version=$(grep "version = " pyproject.toml | sed -e 's/version = "\(.*\)"/\1/g')
|
|
if [ "${{ inputs.tag }}" != "${version}" ]; then
|
|
echo "The input tag does not match the version from pyproject.toml:" >&2
|
|
echo "${{ inputs.tag }}" >&2
|
|
echo "${version}" >&2
|
|
exit 1
|
|
else
|
|
echo "Releasing ${version}"
|
|
fi
|
|
|
|
- name: "Build and push Docker image"
|
|
uses: docker/build-push-action@v5
|
|
with:
|
|
context: .
|
|
platforms: linux/amd64,linux/arm64
|
|
# Reuse the builder
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
push: ${{ inputs.tag != '' }}
|
|
tags: ghcr.io/astral-sh/ruff:latest,ghcr.io/astral-sh/ruff:${{ inputs.tag || 'dry-run' }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
|
|
# After the release has been published, we update downstream repositories
|
|
# This is separate because if this fails the release is still fine, we just need to do some manual workflow triggers
|
|
update-dependents:
|
|
name: Update dependents
|
|
runs-on: ubuntu-latest
|
|
needs: publish-release
|
|
steps:
|
|
- name: "Update pre-commit mirror"
|
|
uses: actions/github-script@v7
|
|
with:
|
|
github-token: ${{ secrets.RUFF_PRE_COMMIT_PAT }}
|
|
script: |
|
|
github.rest.actions.createWorkflowDispatch({
|
|
owner: 'astral-sh',
|
|
repo: 'ruff-pre-commit',
|
|
workflow_id: 'main.yml',
|
|
ref: 'main',
|
|
})
|