prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  release infrastrucutre doesn't handle "out of order" releases
  Specifically if we issue an `0.X` release, then an `0.X+1` release, and then we go to do an `0.X.1` release, the wheel automation won't work, since it builds a wheel for the latest release.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `release.py`
  Content:
  ```
  1 # This file is dual licensed under the terms of the Apache License, Version
  2 # 2.0, and the BSD License. See the LICENSE file in the root of this repository
  3 # for complete details.
  4 
  5 from __future__ import absolute_import, division, print_function
  6 
  7 import getpass
  8 import io
  9 import os
  10 import subprocess
  11 import time
  12 
  13 import click
  14 
  15 from clint.textui.progress import Bar as ProgressBar
  16 
  17 import requests
  18 
  19 
  20 JENKINS_URL = (
  21     "https://ci.cryptography.io/job/cryptography-support-jobs/"
  22     "job/wheel-builder"
  23 )
  24 
  25 
  26 def run(*args, **kwargs):
  27     kwargs.setdefault("stderr", subprocess.STDOUT)
  28     try:
  29         subprocess.check_output(list(args), **kwargs)
  30     except subprocess.CalledProcessError as e:
  31         # Reraise this with a different type so that str(e) is something with
  32         # stdout in it.
  33         raise Exception(e.cmd, e.returncode, e.output)
  34 
  35 
  36 def wait_for_build_completed(session):
  37     # Wait 20 seconds before actually checking if the build is complete, to
  38     # ensure that it had time to really start.
  39     time.sleep(20)
  40     while True:
  41         response = session.get(
  42             "{0}/lastBuild/api/json/".format(JENKINS_URL),
  43             headers={
  44                 "Accept": "application/json",
  45             }
  46         )
  47         response.raise_for_status()
  48         if not response.json()["building"]:
  49             assert response.json()["result"] == "SUCCESS"
  50             break
  51         time.sleep(0.1)
  52 
  53 
  54 def download_artifacts(session):
  55     response = session.get(
  56         "{0}/lastBuild/api/json/".format(JENKINS_URL),
  57         headers={
  58             "Accept": "application/json"
  59         }
  60     )
  61     response.raise_for_status()
  62     json_response = response.json()
  63     assert not json_response["building"]
  64     assert json_response["result"] == "SUCCESS"
  65 
  66     paths = []
  67 
  68     for artifact in json_response["artifacts"]:
  69         response = session.get(
  70             "{0}artifact/{1}".format(
  71                 json_response["url"], artifact["relativePath"]
  72             ), stream=True
  73         )
  74         assert response.headers["content-length"]
  75         print("Downloading {0}".format(artifact["fileName"]))
  76         bar = ProgressBar(
  77             expected_size=int(response.headers["content-length"]),
  78             filled_char="="
  79         )
  80         content = io.BytesIO()
  81         for data in response.iter_content(chunk_size=8192):
  82             content.write(data)
  83             bar.show(content.tell())
  84         assert bar.expected_size == content.tell()
  85         bar.done()
  86         out_path = os.path.join(
  87             os.path.dirname(__file__),
  88             "dist",
  89             artifact["fileName"],
  90         )
  91         with open(out_path, "wb") as f:
  92             f.write(content.getvalue())
  93         paths.append(out_path)
  94     return paths
  95 
  96 
  97 @click.command()
  98 @click.argument("version")
  99 def release(version):
  100     """
  101     ``version`` should be a string like '0.4' or '1.0'.
  102     """
  103     run("git", "tag", "-s", version, "-m", "{0} release".format(version))
  104     run("git", "push", "--tags")
  105 
  106     run("python", "setup.py", "sdist")
  107     run("python", "setup.py", "sdist", "bdist_wheel", cwd="vectors/")
  108 
  109     run(
  110         "twine", "upload", "-s", "dist/cryptography-{0}*".format(version),
  111         "vectors/dist/cryptography_vectors-{0}*".format(version), shell=True
  112     )
  113 
  114     session = requests.Session()
  115 
  116     # This tells the CDN to delete the cached response for the URL. We do this
  117     # so that the Jenkins builders will see the new sdist immediately when they
  118     # go to build the wheels.
  119     response = session.request(
  120         "PURGE", "https://pypi.python.org/simple/cryptography/"
  121     )
  122     response.raise_for_status()
  123 
  124     token = getpass.getpass("Input the Jenkins token: ")
  125     response = session.get(
  126         "{0}/build".format(JENKINS_URL),
  127         params={
  128             "token": token,
  129             "cause": "Building wheels for {0}".format(version)
  130         }
  131     )
  132     response.raise_for_status()
  133     wait_for_build_completed(session)
  134     paths = download_artifacts(session)
  135     run("twine", "upload", " ".join(paths))
  136 
  137 
  138 if __name__ == "__main__":
  139     release()
  140
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/release.py b/release.py
  --- a/release.py
  +++ b/release.py
  @@ -126,6 +126,7 @@
           "{0}/build".format(JENKINS_URL),
           params={
               "token": token,
  +            "BUILD_VERSION": version,
               "cause": "Building wheels for {0}".format(version)
           }
       )
  
verification_info: {"golden_diff": "diff --git a/release.py b/release.py\n--- a/release.py\n+++ b/release.py\n@@ -126,6 +126,7 @@\n         \"{0}/build\".format(JENKINS_URL),\n         params={\n             \"token\": token,\n+            \"BUILD_VERSION\": version,\n             \"cause\": \"Building wheels for {0}\".format(version)\n         }\n     )\n", "issue": "release infrastrucutre doesn't handle \"out of order\" releases\nSpecifically if we issue an `0.X` release, then an `0.X+1` release, and then we go to do an `0.X.1` release, the wheel automation won't work, since it builds a wheel for the latest release.\n\n", "before_files": [{"content": "# This file is dual licensed under the terms of the Apache License, Version\n# 2.0, and the BSD License. See the LICENSE file in the root of this repository\n# for complete details.\n\nfrom __future__ import absolute_import, division, print_function\n\nimport getpass\nimport io\nimport os\nimport subprocess\nimport time\n\nimport click\n\nfrom clint.textui.progress import Bar as ProgressBar\n\nimport requests\n\n\nJENKINS_URL = (\n    \"https://ci.cryptography.io/job/cryptography-support-jobs/\"\n    \"job/wheel-builder\"\n)\n\n\ndef run(*args, **kwargs):\n    kwargs.setdefault(\"stderr\", subprocess.STDOUT)\n    try:\n        subprocess.check_output(list(args), **kwargs)\n    except subprocess.CalledProcessError as e:\n        # Reraise this with a different type so that str(e) is something with\n        # stdout in it.\n        raise Exception(e.cmd, e.returncode, e.output)\n\n\ndef wait_for_build_completed(session):\n    # Wait 20 seconds before actually checking if the build is complete, to\n    # ensure that it had time to really start.\n    time.sleep(20)\n    while True:\n        response = session.get(\n            \"{0}/lastBuild/api/json/\".format(JENKINS_URL),\n            headers={\n                \"Accept\": \"application/json\",\n            }\n        )\n        response.raise_for_status()\n        if not response.json()[\"building\"]:\n            assert response.json()[\"result\"] == \"SUCCESS\"\n            break\n        time.sleep(0.1)\n\n\ndef download_artifacts(session):\n    response = session.get(\n        \"{0}/lastBuild/api/json/\".format(JENKINS_URL),\n        headers={\n            \"Accept\": \"application/json\"\n        }\n    )\n    response.raise_for_status()\n    json_response = response.json()\n    assert not json_response[\"building\"]\n    assert json_response[\"result\"] == \"SUCCESS\"\n\n    paths = []\n\n    for artifact in json_response[\"artifacts\"]:\n        response = session.get(\n            \"{0}artifact/{1}\".format(\n                json_response[\"url\"], artifact[\"relativePath\"]\n            ), stream=True\n        )\n        assert response.headers[\"content-length\"]\n        print(\"Downloading {0}\".format(artifact[\"fileName\"]))\n        bar = ProgressBar(\n            expected_size=int(response.headers[\"content-length\"]),\n            filled_char=\"=\"\n        )\n        content = io.BytesIO()\n        for data in response.iter_content(chunk_size=8192):\n            content.write(data)\n            bar.show(content.tell())\n        assert bar.expected_size == content.tell()\n        bar.done()\n        out_path = os.path.join(\n            os.path.dirname(__file__),\n            \"dist\",\n            artifact[\"fileName\"],\n        )\n        with open(out_path, \"wb\") as f:\n            f.write(content.getvalue())\n        paths.append(out_path)\n    return paths\n\n\n@click.command()\n@click.argument(\"version\")\ndef release(version):\n    \"\"\"\n    ``version`` should be a string like '0.4' or '1.0'.\n    \"\"\"\n    run(\"git\", \"tag\", \"-s\", version, \"-m\", \"{0} release\".format(version))\n    run(\"git\", \"push\", \"--tags\")\n\n    run(\"python\", \"setup.py\", \"sdist\")\n    run(\"python\", \"setup.py\", \"sdist\", \"bdist_wheel\", cwd=\"vectors/\")\n\n    run(\n        \"twine\", \"upload\", \"-s\", \"dist/cryptography-{0}*\".format(version),\n        \"vectors/dist/cryptography_vectors-{0}*\".format(version), shell=True\n    )\n\n    session = requests.Session()\n\n    # This tells the CDN to delete the cached response for the URL. We do this\n    # so that the Jenkins builders will see the new sdist immediately when they\n    # go to build the wheels.\n    response = session.request(\n        \"PURGE\", \"https://pypi.python.org/simple/cryptography/\"\n    )\n    response.raise_for_status()\n\n    token = getpass.getpass(\"Input the Jenkins token: \")\n    response = session.get(\n        \"{0}/build\".format(JENKINS_URL),\n        params={\n            \"token\": token,\n            \"cause\": \"Building wheels for {0}\".format(version)\n        }\n    )\n    response.raise_for_status()\n    wait_for_build_completed(session)\n    paths = download_artifacts(session)\n    run(\"twine\", \"upload\", \" \".join(paths))\n\n\nif __name__ == \"__main__\":\n    release()\n", "path": "release.py"}], "after_files": [{"content": "# This file is dual licensed under the terms of the Apache License, Version\n# 2.0, and the BSD License. See the LICENSE file in the root of this repository\n# for complete details.\n\nfrom __future__ import absolute_import, division, print_function\n\nimport getpass\nimport io\nimport os\nimport subprocess\nimport time\n\nimport click\n\nfrom clint.textui.progress import Bar as ProgressBar\n\nimport requests\n\n\nJENKINS_URL = (\n    \"https://ci.cryptography.io/job/cryptography-support-jobs/\"\n    \"job/wheel-builder\"\n)\n\n\ndef run(*args, **kwargs):\n    kwargs.setdefault(\"stderr\", subprocess.STDOUT)\n    try:\n        subprocess.check_output(list(args), **kwargs)\n    except subprocess.CalledProcessError as e:\n        # Reraise this with a different type so that str(e) is something with\n        # stdout in it.\n        raise Exception(e.cmd, e.returncode, e.output)\n\n\ndef wait_for_build_completed(session):\n    # Wait 20 seconds before actually checking if the build is complete, to\n    # ensure that it had time to really start.\n    time.sleep(20)\n    while True:\n        response = session.get(\n            \"{0}/lastBuild/api/json/\".format(JENKINS_URL),\n            headers={\n                \"Accept\": \"application/json\",\n            }\n        )\n        response.raise_for_status()\n        if not response.json()[\"building\"]:\n            assert response.json()[\"result\"] == \"SUCCESS\"\n            break\n        time.sleep(0.1)\n\n\ndef download_artifacts(session):\n    response = session.get(\n        \"{0}/lastBuild/api/json/\".format(JENKINS_URL),\n        headers={\n            \"Accept\": \"application/json\"\n        }\n    )\n    response.raise_for_status()\n    json_response = response.json()\n    assert not json_response[\"building\"]\n    assert json_response[\"result\"] == \"SUCCESS\"\n\n    paths = []\n\n    for artifact in json_response[\"artifacts\"]:\n        response = session.get(\n            \"{0}artifact/{1}\".format(\n                json_response[\"url\"], artifact[\"relativePath\"]\n            ), stream=True\n        )\n        assert response.headers[\"content-length\"]\n        print(\"Downloading {0}\".format(artifact[\"fileName\"]))\n        bar = ProgressBar(\n            expected_size=int(response.headers[\"content-length\"]),\n            filled_char=\"=\"\n        )\n        content = io.BytesIO()\n        for data in response.iter_content(chunk_size=8192):\n            content.write(data)\n            bar.show(content.tell())\n        assert bar.expected_size == content.tell()\n        bar.done()\n        out_path = os.path.join(\n            os.path.dirname(__file__),\n            \"dist\",\n            artifact[\"fileName\"],\n        )\n        with open(out_path, \"wb\") as f:\n            f.write(content.getvalue())\n        paths.append(out_path)\n    return paths\n\n\n@click.command()\n@click.argument(\"version\")\ndef release(version):\n    \"\"\"\n    ``version`` should be a string like '0.4' or '1.0'.\n    \"\"\"\n    run(\"git\", \"tag\", \"-s\", version, \"-m\", \"{0} release\".format(version))\n    run(\"git\", \"push\", \"--tags\")\n\n    run(\"python\", \"setup.py\", \"sdist\")\n    run(\"python\", \"setup.py\", \"sdist\", \"bdist_wheel\", cwd=\"vectors/\")\n\n    run(\n        \"twine\", \"upload\", \"-s\", \"dist/cryptography-{0}*\".format(version),\n        \"vectors/dist/cryptography_vectors-{0}*\".format(version), shell=True\n    )\n\n    session = requests.Session()\n\n    # This tells the CDN to delete the cached response for the URL. We do this\n    # so that the Jenkins builders will see the new sdist immediately when they\n    # go to build the wheels.\n    response = session.request(\n        \"PURGE\", \"https://pypi.python.org/simple/cryptography/\"\n    )\n    response.raise_for_status()\n\n    token = getpass.getpass(\"Input the Jenkins token: \")\n    response = session.get(\n        \"{0}/build\".format(JENKINS_URL),\n        params={\n            \"token\": token,\n            \"BUILD_VERSION\": version,\n            \"cause\": \"Building wheels for {0}\".format(version)\n        }\n    )\n    response.raise_for_status()\n    wait_for_build_completed(session)\n    paths = download_artifacts(session)\n    run(\"twine\", \"upload\", \" \".join(paths))\n\n\nif __name__ == \"__main__\":\n    release()\n", "path": "release.py"}]}