Simplify the version bump process. ### Description

Simplify the version bump process.

- Use substitution hook in docs to update CDN URL.
  - In `dev` or `prerelease` versions, it will point to `dev` url
  - In `stable` versions, it will point it `vX.Y.Z` url
- Introduce a version bump script `tools/bump_version.py`.


~- Use `bump2version` to bump Python versions (continuing from #2460)~
~- Use `npm version` to bump JS versions~
~- Update `run_docker` script to use latest deployed pre-built docker image when `--pre-built` option is specified.~

### Checklists

- [x] Add new / update outdated documentation

# setup: import numpy as np ; N = 50 ; X, Y = np.random.randn(30,N), np.random.randn(20,N)
# run: allpairs_distances_loops(X, Y)

# pythran export allpairs_distances_loops(float64[][], float64[][])
import numpy as np


def allpairs_distances_loops(X, Y):
    result = np.zeros((X.shape[0], Y.shape[0]), X.dtype)
    for i in range(X.shape[0]):
        for j in range(Y.shape[0]):
            result[i, j] = np.sum((X[i, :] - Y[j, :]) ** 2)
    return result

# setup: import numpy as np ; N = 50 ; X, Y = np.random.randn(30,N), np.random.randn(20,N)
# run: allpairs_distances_loops(X, Y)

# pythran export allpairs_distances_loops(float64[][], float64[][])
import numpy as np


def allpairs_distances_loops(X, Y):
    result = np.zeros((X.shape[0], Y.shape[0]), X.dtype)
    for i in range(X.shape[0]):
        for j in range(Y.shape[0]):
            result[i, j] = np.sum((X[i, :] - Y[j, :]) ** 2)
    return result
